Source Code Cross Referenced for ClassTree.java in  » Development » yguardlib » com » yworks » yguard » 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 » yguardlib » com.yworks.yguard.obf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * YGuard -- an obfuscation library for Java(TM) classfiles.
0003:         *
0004:         * Original Copyright (c) 1999 Mark Welsh (markw@retrologic.com)
0005:         * Modifications Copyright (c) 2002 yWorks GmbH (yguard@yworks.com)
0006:         *
0007:         * This library is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU Lesser General Public
0009:         * License as published by the Free Software Foundation; either
0010:         * version 2 of the License, or (at your option) any later version.
0011:         *
0012:         * This library is distributed in the hope that it will be useful,
0013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015:         * Lesser General Public License for more details.
0016:         *
0017:         * You should have received a copy of the GNU Lesser General Public
0018:         * License along with this library; if not, write to the Free Software
0019:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0020:         *
0021:         * The author may be contacted at yguard@yworks.com 
0022:         *
0023:         * Java and all Java-based marks are trademarks or registered 
0024:         * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
0025:         */package com.yworks.yguard.obf;
0026:
0027:        import com.yworks.yguard.Conversion;
0028:        import com.yworks.yguard.ParseException;
0029:        import com.yworks.yguard.obf.classfile.ClassConstants;
0030:        import com.yworks.yguard.obf.classfile.ClassFile;
0031:        import com.yworks.yguard.obf.classfile.LineNumberTableAttrInfo;
0032:        import com.yworks.yguard.obf.classfile.Logger;
0033:        import com.yworks.yguard.obf.classfile.NameMapper;
0034:
0035:        import java.io.PrintWriter;
0036:        import java.lang.reflect.Modifier;
0037:        import java.util.ArrayList;
0038:        import java.util.Enumeration;
0039:        import java.util.HashSet;
0040:        import java.util.List;
0041:        import java.util.Set;
0042:        import java.util.StringTokenizer;
0043:        import java.util.Vector;
0044:
0045:        /**
0046:         * Tree structure of package levels, classes, methods and fields used for obfuscation.
0047:         *
0048:         * @author      Mark Welsh
0049:         */
0050:        public class ClassTree implements  NameMapper {
0051:            // Constants -------------------------------------------------------------
0052:            public static final char PACKAGE_LEVEL = '/';
0053:            public static final char CLASS_LEVEL = '$';
0054:            public static final char METHOD_FIELD_LEVEL = '/';
0055:
0056:            // Fields ----------------------------------------------------------------
0057:            private Vector retainAttrs = new Vector(); // List of attributes to retain
0058:            private Pk root = null; // Root package in database (Java default package)
0059:
0060:            // Class methods ---------------------------------------------------------
0061:            /** Return a fully qualified name broken into package/class segments. */
0062:            public static Enumeration getNameEnum(String name) {
0063:                Vector vec = new Vector();
0064:                String nameOrig = name;
0065:                while (!name.equals("")) {
0066:                    int posP = name.indexOf(PACKAGE_LEVEL);
0067:                    int posC = name.indexOf(CLASS_LEVEL);
0068:                    Cons cons = null;
0069:                    if (posP == -1 && posC == -1) {
0070:                        cons = new Cons(new Character(CLASS_LEVEL), name);
0071:                        name = "";
0072:                    }
0073:                    if (posP == -1 && posC != -1) {
0074:                        cons = new Cons(new Character(CLASS_LEVEL), name
0075:                                .substring(0, posC));
0076:                        //fixes retroguard bug, where 
0077:                        // 'ClassName$$InnerClassName' leads to a runtimeerror
0078:                        while ((posC + 1 < name.length())
0079:                                && (name.charAt(posC + 1) == CLASS_LEVEL))
0080:                            posC++;
0081:                        name = name.substring(posC + 1, name.length());
0082:                    }
0083:                    if (posP != -1 && posC == -1) {
0084:                        cons = new Cons(new Character(PACKAGE_LEVEL), name
0085:                                .substring(0, posP));
0086:                        name = name.substring(posP + 1, name.length());
0087:                    }
0088:                    if (posP != -1 && posC != -1) {
0089:                        if (posP < posC) {
0090:                            cons = new Cons(new Character(PACKAGE_LEVEL), name
0091:                                    .substring(0, posP));
0092:                            name = name.substring(posP + 1, name.length());
0093:                        } else {
0094:                            throw new IllegalArgumentException(
0095:                                    "Invalid fully qualified name (a): "
0096:                                            + nameOrig);
0097:                        }
0098:                    }
0099:                    if (((String) cons.cdr).equals("")) {
0100:                        throw new IllegalArgumentException(
0101:                                "Invalid fully qualified name (b): " + nameOrig);
0102:                    }
0103:                    vec.addElement(cons);
0104:                }
0105:                return vec.elements();
0106:            }
0107:
0108:            // Instance Methods ------------------------------------------------------
0109:            /** Ctor. */
0110:            public ClassTree() {
0111:                root = Pk.createRoot(this );
0112:            }
0113:
0114:            /** Return the root node. */
0115:            public Pk getRoot() {
0116:                return root;
0117:            }
0118:
0119:            /**
0120:             * finds tree items by looking for name components only...
0121:             */
0122:            public TreeItem findTreeItem(String[] nameParts) {
0123:                TreeItem tmp = root;
0124:                for (int i = 0; tmp != null && i < nameParts.length; i++) {
0125:                    String name = nameParts[i];
0126:                    tmp = findSubItem(tmp, name);
0127:                }
0128:                return tmp;
0129:            }
0130:
0131:            /**
0132:             * walks the tree of TreeItems in order to find a class forName
0133:             */
0134:            public Cl findClassForName(String name) {
0135:                int dindex = name.indexOf('$');
0136:                String innerClass = null;
0137:                if (dindex > 0) {
0138:                    innerClass = name.substring(dindex + 1);
0139:                    name = name.substring(0, dindex);
0140:                }
0141:                int pindex = name.lastIndexOf('.');
0142:                String packageName = null;
0143:                if (pindex > 0) {
0144:                    packageName = name.substring(0, pindex);
0145:                    name = name.substring(pindex + 1);
0146:                }
0147:                Pk pk = root;
0148:                if (packageName != null) {
0149:                    for (StringTokenizer st = new StringTokenizer(packageName,
0150:                            ".", false); st.hasMoreTokens();) {
0151:                        String token = st.nextToken();
0152:                        pk = findPackage(pk, token);
0153:                        if (pk == null)
0154:                            return null;
0155:                    }
0156:                }
0157:                Cl cl = findClass(pk, name);
0158:                if (cl != null && innerClass != null) {
0159:                    for (StringTokenizer st = new StringTokenizer(innerClass,
0160:                            "$", false); st.hasMoreTokens();) {
0161:                        String token = st.nextToken();
0162:                        cl = findClass(cl, token);
0163:                        if (cl == null)
0164:                            return null;
0165:                    }
0166:                }
0167:                return cl;
0168:            }
0169:
0170:            private Pk findPackage(TreeItem parent, String pName) {
0171:                if (parent instanceof  Pk) {
0172:                    for (Enumeration enumeration = ((Pk) parent)
0173:                            .getPackageEnum(); enumeration.hasMoreElements();) {
0174:                        Pk subPk = (Pk) enumeration.nextElement();
0175:                        if (subPk.getInName().equals(pName)) {
0176:                            return subPk;
0177:                        }
0178:                    }
0179:                }
0180:                return null;
0181:            }
0182:
0183:            private Cl findClass(PkCl parent, String pName) {
0184:                for (Enumeration enumeration = ((PkCl) parent).getClassEnum(); enumeration
0185:                        .hasMoreElements();) {
0186:                    Cl cl = (Cl) enumeration.nextElement();
0187:                    if (cl.getInName().equals(pName)) {
0188:                        return cl;
0189:                    }
0190:                }
0191:                return null;
0192:            }
0193:
0194:            private TreeItem findSubItem(TreeItem parent, String childName) {
0195:                if (parent instanceof  Pk) {
0196:                    for (Enumeration enumeration = ((Pk) parent)
0197:                            .getPackageEnum(); enumeration.hasMoreElements();) {
0198:                        Pk subPk = (Pk) enumeration.nextElement();
0199:                        if (subPk.getInName().equals(childName)) {
0200:                            return subPk;
0201:                        }
0202:                    }
0203:                    for (Enumeration enumeration = ((Pk) parent).getClassEnum(); enumeration
0204:                            .hasMoreElements();) {
0205:                        Cl cl = (Cl) enumeration.nextElement();
0206:                        if (cl.getInName().equals(childName)) {
0207:                            return cl;
0208:                        }
0209:                    }
0210:                }
0211:                if (parent instanceof  Cl) {
0212:                    for (Enumeration enumeration = ((Cl) parent).getClassEnum(); enumeration
0213:                            .hasMoreElements();) {
0214:                        Cl cl = (Cl) enumeration.nextElement();
0215:                        if (cl.getInName().equals(childName)) {
0216:                            return cl;
0217:                        }
0218:                    }
0219:                    return null;
0220:                }
0221:                return null;
0222:            }
0223:
0224:            /** Update the path of the passed filename, if that path corresponds to a package. */
0225:            public String getOutName(String inName) {
0226:                try {
0227:                    TreeItem ti = root;
0228:                    StringBuffer sb = new StringBuffer();
0229:                    for (Enumeration nameEnum = getNameEnum(inName); nameEnum
0230:                            .hasMoreElements();) {
0231:                        Cons nameSegment = (Cons) nameEnum.nextElement();
0232:                        char tag = ((Character) nameSegment.car).charValue();
0233:                        String name = (String) nameSegment.cdr;
0234:                        switch (tag) {
0235:                        case PACKAGE_LEVEL:
0236:                            if (ti != null) {
0237:                                ti = ((Pk) ti).getPackage(name);
0238:                                if (ti != null) {
0239:                                    sb.append(ti.getOutName());
0240:                                } else {
0241:                                    sb.append(name);
0242:                                }
0243:                            } else {
0244:                                sb.append(name);
0245:                            }
0246:                            sb.append(PACKAGE_LEVEL);
0247:                            break;
0248:
0249:                        case CLASS_LEVEL:
0250:                            sb.append(name);
0251:                            return sb.toString();
0252:
0253:                        default:
0254:                            throw new RuntimeException(
0255:                                    "Internal error: illegal package/class name tag");
0256:                        }
0257:                    }
0258:                } catch (Exception e) {
0259:                    // Just drop through and return the original name
0260:                }
0261:                return inName;
0262:            }
0263:
0264:            /** Add a classfile's package, class, method and field entries to database. */
0265:            public void addClassFile(ClassFile cf) {
0266:                // Add the fully qualified class name
0267:                TreeItem ti = root;
0268:                char parentTag = PACKAGE_LEVEL;
0269:                for (Enumeration nameEnum = getNameEnum(cf.getName()); nameEnum
0270:                        .hasMoreElements();) {
0271:                    Cons nameSegment = (Cons) nameEnum.nextElement();
0272:                    char tag = ((Character) nameSegment.car).charValue();
0273:                    String name = (String) nameSegment.cdr;
0274:                    switch (tag) {
0275:                    case PACKAGE_LEVEL:
0276:                        ti = ((Pk) ti).addPackage(name);
0277:                        break;
0278:
0279:                    case CLASS_LEVEL:
0280:                        // If this is an inner class, just add placeholder classes up the tree
0281:                        if (nameEnum.hasMoreElements()) {
0282:                            ti = ((PkCl) ti).addPlaceholderClass(name);
0283:                        } else {
0284:                            Cl cl = ((PkCl) ti).addClass(name, cf.getSuper(),
0285:                                    cf.getInterfaces(), cf.getModifiers());
0286:                            cl.setInnerClassModifiers(cf
0287:                                    .getInnerClassModifiers());
0288:                            cl.setClassFileAccess(cf.getClassFileAccess());
0289:                            ti = cl;
0290:                        }
0291:                        break;
0292:
0293:                    default:
0294:                        throw new ParseException(
0295:                                "Internal error: illegal package/class name tag");
0296:                    }
0297:                    parentTag = tag;
0298:                }
0299:
0300:                // We must have a class before adding methods and fields
0301:                if (ti instanceof  Cl) {
0302:                    Cl cl = (Cl) ti;
0303:                    cl.access = cf.getModifiers();
0304:
0305:                    // Add the class's methods to the database
0306:                    for (Enumeration enumeration = cf.getMethodEnum(); enumeration
0307:                            .hasMoreElements();) {
0308:                        Cons cons = (Cons) enumeration.nextElement();
0309:                        cl.addMethod(((Boolean) ((Cons) cons.car).car)
0310:                                .booleanValue(),
0311:                                (String) ((Cons) cons.car).cdr,
0312:                                (String) ((Cons) cons.cdr).car,
0313:                                ((Integer) ((Cons) cons.cdr).cdr).intValue());
0314:                    }
0315:
0316:                    // Add the class's fields to the database
0317:                    for (Enumeration enumeration = cf.getFieldEnum(); enumeration
0318:                            .hasMoreElements();) {
0319:                        Cons cons = (Cons) enumeration.nextElement();
0320:                        cl.addField(((Boolean) ((Cons) cons.car).car)
0321:                                .booleanValue(),
0322:                                (String) ((Cons) cons.car).cdr,
0323:                                (String) ((Cons) cons.cdr).car,
0324:                                ((Integer) ((Cons) cons.cdr).cdr).intValue());
0325:                    }
0326:                } else {
0327:                    throw new ParseException("Inconsistent class file.");
0328:                }
0329:            }
0330:
0331:            /** Mark an attribute type for retention. */
0332:            public void retainAttribute(String name) {
0333:                retainAttrs.addElement(name);
0334:            }
0335:
0336:            private boolean modifierMatch(int level, int mods) {
0337:                if (level == YGuardRule.LEVEL_NONE)
0338:                    return false;
0339:                if (Modifier.isPublic(mods)) {
0340:                    return (level & YGuardRule.PUBLIC) == YGuardRule.PUBLIC;
0341:                }
0342:                if (Modifier.isProtected(mods)) {
0343:                    return (level & YGuardRule.PROTECTED) == YGuardRule.PROTECTED;
0344:                }
0345:                if (Modifier.isPrivate(mods)) {
0346:                    return (level & YGuardRule.PRIVATE) == YGuardRule.PRIVATE;
0347:                }
0348:                // package friendly left only
0349:                return (level & YGuardRule.FRIENDLY) == YGuardRule.FRIENDLY;
0350:            }
0351:
0352:            /** Mark a class/interface type (and possibly methods and fields defined in class) for retention. */
0353:            public void retainClass(String name, int classLevel,
0354:                    int methodLevel, int fieldLevel, boolean retainHierarchy) {
0355:
0356:                // Mark the class (or classes, if this is a wildcarded specifier)
0357:                for (Enumeration clEnum = getClEnum(name, classLevel); clEnum
0358:                        .hasMoreElements();) {
0359:                    Cl classItem = (Cl) clEnum.nextElement();
0360:                    if (retainHierarchy && classLevel != YGuardRule.LEVEL_NONE)
0361:                        retainHierarchy(classItem);
0362:                    // Retain methods if requested
0363:                    if (methodLevel != YGuardRule.LEVEL_NONE) {
0364:                        for (Enumeration enumeration = classItem
0365:                                .getMethodEnum(); enumeration.hasMoreElements();) {
0366:                            Md md = (Md) enumeration.nextElement();
0367:                            if (modifierMatch(methodLevel, md.getModifiers())) {
0368:                                md.setOutName(md.getInName());
0369:                                md.setFromScript();
0370:                            }
0371:                        }
0372:                        // do super classes and interfaces...
0373:                        if ((methodLevel & (YGuardRule.PUBLIC
0374:                                | YGuardRule.PROTECTED | YGuardRule.FRIENDLY)) != 0
0375:                                || (fieldLevel & (YGuardRule.PUBLIC
0376:                                        | YGuardRule.PROTECTED | YGuardRule.FRIENDLY)) != 0) {
0377:                            int mask = YGuardRule.PRIVATE;
0378:                            int ml = methodLevel & ~mask;
0379:                            int fl = fieldLevel & ~mask;
0380:                            int cl = classLevel & ~mask;
0381:                            String[] interfaces = classItem.getInterfaces();
0382:                            if (interfaces != null) {
0383:                                for (int i = 0; i < interfaces.length; i++) {
0384:                                    String interfaceClass = interfaces[i];
0385:                                    retainClass(interfaceClass, cl, ml, fl,
0386:                                            false);
0387:                                }
0388:                            }
0389:                            String super Class = classItem.getSuperClass();
0390:                            if (super Class != null) {
0391:                                // staying in package?!
0392:                                if (!super Class.startsWith(classItem
0393:                                        .getParent().getFullInName())) {
0394:                                    mask |= YGuardRule.FRIENDLY;
0395:                                    ml = methodLevel & ~mask;
0396:                                    fl = fieldLevel & ~mask;
0397:                                    cl = classLevel & ~mask;
0398:                                }
0399:                                retainClass(super Class, cl, ml, fl, false);
0400:                            }
0401:                        }
0402:                    }
0403:
0404:                    // Retain fields if requested
0405:                    if (fieldLevel != YGuardRule.LEVEL_NONE) {
0406:                        for (Enumeration enumeration = classItem.getFieldEnum(); enumeration
0407:                                .hasMoreElements();) {
0408:                            Fd fd = (Fd) enumeration.nextElement();
0409:                            if (modifierMatch(fieldLevel, fd.getModifiers())) {
0410:                                fd.setOutName(fd.getInName());
0411:                                fd.setFromScript();
0412:                            }
0413:                        }
0414:                    }
0415:                }
0416:            }
0417:
0418:            /** Mark a method type for retention. */
0419:            public void retainMethod(String name, String descriptor) {
0420:                for (Enumeration enumeration = getMdEnum(name, descriptor); enumeration
0421:                        .hasMoreElements();) {
0422:                    Md md = (Md) enumeration.nextElement();
0423:                    md.setOutName(md.getInName());
0424:                    md.setFromScript();
0425:                }
0426:            }
0427:
0428:            /** Mark a field type for retention. */
0429:            public void retainField(String name) {
0430:                for (Enumeration enumeration = getFdEnum(name); enumeration
0431:                        .hasMoreElements();) {
0432:                    Fd fd = (Fd) enumeration.nextElement();
0433:                    fd.setOutName(fd.getInName());
0434:                    fd.setFromScript();
0435:                }
0436:            }
0437:
0438:            /** Mark a package for retention, and specify its new name. */
0439:            public void retainPackageMap(String name, String obfName) {
0440:                retainItemMap(getPk(name), obfName);
0441:            }
0442:
0443:            /** Mark a class/interface type for retention, and specify its new name. */
0444:            public void retainClassMap(String name, String obfName) {
0445:                retainItemMap(getCl(name), obfName);
0446:            }
0447:
0448:            /** Mark a method type for retention, and specify its new name. */
0449:            public void retainMethodMap(String name, String descriptor,
0450:                    String obfName) {
0451:                retainItemMap(getMd(name, descriptor), obfName);
0452:            }
0453:
0454:            /** Mark a field type for retention, and specify its new name. */
0455:            public void retainFieldMap(String name, String obfName) {
0456:                retainItemMap(getFd(name), obfName);
0457:            }
0458:
0459:            // Mark an item for retention, and specify its new name.
0460:            private void retainItemMap(TreeItem item, String obfName) {
0461:                if (!item.isFixed()) {
0462:                    item.setOutName(obfName);
0463:                    item.setFromScriptMap();
0464:                } else {
0465:                    if (!item.getOutName().equals(obfName)) {
0466:                        item.setOutName(obfName);
0467:                        item.setFromScriptMap();
0468:                        // do warning
0469:                        Logger.getInstance().warning(
0470:                                "'" + item.getFullInName()
0471:                                        + "' will be remapped to '" + obfName
0472:                                        + "' according to mapping rule!");
0473:                    }
0474:                }
0475:                //        if (!item.isFixed())
0476:                //        {
0477:                //          item.setFromScriptMap();
0478:                //        }
0479:                //        item.setOutName(obfName);
0480:            }
0481:
0482:            /** Traverse the class tree, generating obfuscated names within each namespace. */
0483:            public void generateNames() {
0484:                walkTree(new TreeAction() {
0485:                    public void packageAction(Pk pk) {
0486:                        pk.generateNames();
0487:                    }
0488:
0489:                    public void classAction(Cl cl) {
0490:                        cl.generateNames();
0491:                    }
0492:                });
0493:            }
0494:
0495:            /** Resolve the polymorphic dependencies of each class. */
0496:            public void resolveClasses() throws ClassNotFoundException {
0497:                walkTree(new TreeAction() {
0498:                    public void classAction(Cl cl) {
0499:                        cl.resetResolve();
0500:                    }
0501:                });
0502:                walkTree(new TreeAction() {
0503:                    public void classAction(Cl cl) {
0504:                        cl.setupNameListDowns();
0505:                    }
0506:                });
0507:                Cl.nameSpace = 0;
0508:                final ClassNotFoundException[] ex = new ClassNotFoundException[1];
0509:                try {
0510:                    walkTree(new TreeAction() {
0511:                        public void classAction(Cl cl) {
0512:                            try {
0513:                                cl.resolveOptimally();
0514:                            } catch (ClassNotFoundException cnfe) {
0515:                                ex[0] = cnfe;
0516:                                throw new RuntimeException();
0517:                            }
0518:                        }
0519:                    });
0520:                } catch (RuntimeException rte) {
0521:                    if (ex[0] != null) {
0522:                        throw ex[0];
0523:                    } else {
0524:                        throw rte;
0525:                    }
0526:                }
0527:            }
0528:
0529:            /** Return a list of attributes marked to keep. */
0530:            public String[] getAttrsToKeep() {
0531:                String[] attrs = new String[retainAttrs.size()];
0532:                for (int i = 0; i < attrs.length; i++) {
0533:                    attrs[i] = (String) retainAttrs.elementAt(i);
0534:                }
0535:                return attrs;
0536:            }
0537:
0538:            /** Get classes in tree from the fully qualified name
0539:                (can be wildcarded). */
0540:            public Enumeration getClEnum(String fullName) {
0541:                return getClEnum(fullName, YGuardRule.LEVEL_PRIVATE);
0542:            }
0543:
0544:            /** Get classes in tree from the fully qualified name
0545:                (can be wildcarded). */
0546:            public Enumeration getClEnum(String fullName, final int classMode) {
0547:                final Vector vec = new Vector();
0548:
0549:                // Wildcarded?
0550:                // Then return list of all classes (including inner classes) in package
0551:                if (fullName.indexOf('*') != -1) {
0552:                    // Recursive?
0553:                    if (fullName.indexOf('!') == 0) {
0554:                        final String fName = fullName.substring(1);
0555:                        walkTree(new TreeAction() {
0556:                            public void classAction(Cl cl) {
0557:                                if (cl.isWildcardMatch(fName)
0558:                                        && modifierMatch(classMode, cl
0559:                                                .getModifiers())) {
0560:                                    vec.addElement(cl);
0561:                                }
0562:                            }
0563:                        });
0564:                    } else {
0565:                        // non-recursive
0566:                        final String fName = fullName;
0567:                        walkTree(new TreeAction() {
0568:                            public void classAction(Cl cl) {
0569:                                if (cl.isNRWildcardMatch(fName)
0570:                                        && modifierMatch(classMode, cl
0571:                                                .getModifiers())) {
0572:                                    vec.addElement(cl);
0573:                                }
0574:                            }
0575:                        });
0576:                    }
0577:                } else {
0578:                    // Single class
0579:                    Cl cl = getCl(fullName);
0580:                    if (cl != null) {
0581:                        int mods = cl.getModifiers();
0582:                        if (cl.isInnerClass()) {
0583:                            Cl outer = (Cl) cl.getParent();
0584:                        }
0585:                        boolean match = modifierMatch(classMode, cl
0586:                                .getModifiers());
0587:                        if (match || classMode == YGuardRule.LEVEL_NONE) { //(RW)
0588:                            vec.addElement(cl);
0589:                        }
0590:                    }
0591:                }
0592:                return vec.elements();
0593:            }
0594:
0595:            /** Get methods in tree from the fully qualified, and possibly
0596:                wildcarded, name. */
0597:            public Enumeration getMdEnum(String fullName, String descriptor) {
0598:                final Vector vec = new Vector();
0599:                final String fDesc = descriptor;
0600:                if (fullName.indexOf('*') != -1
0601:                        || descriptor.indexOf('*') != -1) {
0602:                    // Recursive?
0603:                    if (fullName.indexOf('!') == 0) {
0604:                        final String fName = fullName.substring(1);
0605:                        // recursive wildcarding
0606:                        walkTree(new TreeAction() {
0607:                            public void methodAction(Md md) {
0608:                                if (md.isWildcardMatch(fName, fDesc)) {
0609:                                    vec.addElement(md);
0610:                                }
0611:                            }
0612:                        });
0613:                    } else {
0614:                        final String fName = fullName;
0615:                        // non-recursive wildcarding
0616:                        walkTree(new TreeAction() {
0617:                            public void methodAction(Md md) {
0618:                                if (md.isNRWildcardMatch(fName, fDesc)) {
0619:                                    vec.addElement(md);
0620:                                }
0621:                            }
0622:                        });
0623:                    }
0624:                } else {
0625:                    Md md = getMd(fullName, descriptor);
0626:                    if (md != null) {
0627:                        vec.addElement(md);
0628:                    }
0629:                }
0630:                return vec.elements();
0631:            }
0632:
0633:            /** Get fields in tree from the fully qualified, and possibly
0634:                wildcarded, name. */
0635:            public Enumeration getFdEnum(String fullName) {
0636:                final Vector vec = new Vector();
0637:                if (fullName.indexOf('*') != -1) {
0638:                    // Recursive?
0639:                    if (fullName.indexOf('!') == 0) {
0640:                        // recursive wildcarding
0641:                        final String fName = fullName.substring(1);
0642:                        walkTree(new TreeAction() {
0643:                            public void fieldAction(Fd fd) {
0644:                                if (fd.isWildcardMatch(fName)) {
0645:                                    vec.addElement(fd);
0646:                                }
0647:                            }
0648:                        });
0649:                    } else {
0650:                        // non-recursive wildcarding
0651:                        final String fName = fullName;
0652:                        walkTree(new TreeAction() {
0653:                            public void fieldAction(Fd fd) {
0654:                                if (fd.isNRWildcardMatch(fName)) {
0655:                                    vec.addElement(fd);
0656:                                }
0657:                            }
0658:                        });
0659:                    }
0660:                } else {
0661:                    Fd fd = getFd(fullName);
0662:                    if (fd != null) {
0663:                        vec.addElement(fd);
0664:                    }
0665:                }
0666:                return vec.elements();
0667:            }
0668:
0669:            /** Get class in tree from the fully qualified name, returning null if name not found. */
0670:            public Cl getCl(String fullName) {
0671:                TreeItem ti = root;
0672:                for (Enumeration nameEnum = getNameEnum(fullName); nameEnum
0673:                        .hasMoreElements();) {
0674:                    Cons nameSegment = (Cons) nameEnum.nextElement();
0675:                    char tag = ((Character) nameSegment.car).charValue();
0676:                    String name = (String) nameSegment.cdr;
0677:                    switch (tag) {
0678:                    case PACKAGE_LEVEL:
0679:                        ti = ((Pk) ti).getPackage(name);
0680:                        break;
0681:
0682:                    case CLASS_LEVEL:
0683:                        ti = ((PkCl) ti).getClass(name);
0684:                        break;
0685:
0686:                    default:
0687:                        throw new ParseException(
0688:                                "Internal error: illegal package/class name tag");
0689:                    }
0690:
0691:                    // If the name is not in the database, return null
0692:                    if (ti == null) {
0693:                        return null;
0694:                    }
0695:                }
0696:
0697:                // It is an error if we do not end up with a class or interface
0698:                if (!(ti instanceof  Cl)) {
0699:                    throw new ParseException(
0700:                            "Inconsistent class or interface name.");
0701:                }
0702:                return (Cl) ti;
0703:            }
0704:
0705:            /** Get package in tree from the fully qualified name, returning null if name not found. */
0706:            public Pk getPk(String fullName) {
0707:                TreeItem ti = root;
0708:                for (Enumeration nameEnum = getNameEnum(fullName); nameEnum
0709:                        .hasMoreElements();) {
0710:                    Cons nameSegment = (Cons) nameEnum.nextElement();
0711:                    String name = (String) nameSegment.cdr;
0712:                    ti = ((Pk) ti).getPackage(name);
0713:
0714:                    // If the name is not in the database, return null
0715:                    if (ti == null) {
0716:                        return null;
0717:                    }
0718:                    // It is an error if we do not end up with a package
0719:                    if (!(ti instanceof  Pk)) {
0720:                        throw new ParseException("Inconsistent package.");
0721:                    }
0722:                }
0723:                return (Pk) ti;
0724:            }
0725:
0726:            /** Get method in tree from the fully qualified name. */
0727:            public Md getMd(String fullName, String descriptor) {
0728:                // Split into class and method names
0729:                int pos = fullName.lastIndexOf(METHOD_FIELD_LEVEL);
0730:                Cl cl = getCl(fullName.substring(0, pos));
0731:                return cl.getMethod(fullName.substring(pos + 1), descriptor);
0732:            }
0733:
0734:            /** Get field in tree from the fully qualified name. */
0735:            public Fd getFd(String fullName) {
0736:                // Split into class and field names
0737:                int pos = fullName.lastIndexOf(METHOD_FIELD_LEVEL);
0738:                Cl cl = getCl(fullName.substring(0, pos));
0739:                return cl.getField(fullName.substring(pos + 1));
0740:            }
0741:
0742:            public String[] getAttrsToKeep(String className) {
0743:                Cl cl = getCl(className);
0744:                if (cl != null) {
0745:                    Set attrs = cl.getAttributesToKeep();
0746:                    if (attrs != null && attrs.size() > 0) {
0747:                        String[] other = getAttrsToKeep();
0748:                        Set tmp = new HashSet(attrs);
0749:                        for (int i = 0; i < other.length; i++) {
0750:                            tmp.add(other[i]);
0751:                        }
0752:                        return (String[]) tmp.toArray(new String[tmp.size()]);
0753:                    } else {
0754:                        return getAttrsToKeep();
0755:                    }
0756:                } else {
0757:                    return getAttrsToKeep();
0758:                }
0759:            }
0760:
0761:            public String mapLocalVariable(String this ClassName,
0762:                    String methodName, String descriptor, String string) {
0763:                return string;
0764:            }
0765:
0766:            /** Mapping for fully qualified class name.
0767:             *  @see NameMapper#mapClass */
0768:            public String mapClass(String className) {
0769:                //      System.out.println("map class " + className);
0770:                // Check for array -- requires special handling
0771:                if (className.length() > 0 && className.charAt(0) == '[') {
0772:                    StringBuffer newName = new StringBuffer();
0773:                    int i = 0;
0774:                    while (i < className.length()) {
0775:                        char ch = className.charAt(i++);
0776:                        switch (ch) {
0777:                        case '[':
0778:                        case ';':
0779:                            newName.append(ch);
0780:                            break;
0781:
0782:                        case 'L':
0783:                            newName.append(ch);
0784:                            int pos = className.indexOf(';', i);
0785:                            if (pos < 0) {
0786:                                throw new ParseException(
0787:                                        "Invalid class name encountered: "
0788:                                                + className);
0789:                            }
0790:                            newName
0791:                                    .append(mapClass(className
0792:                                            .substring(i, pos)));
0793:                            i = pos;
0794:                            break;
0795:
0796:                        default:
0797:                            return className;
0798:                        }
0799:                    }
0800:                    return newName.toString();
0801:                } else {
0802:                    Cl cl = getCl(className);
0803:                    if (cl == null) {
0804:                        try {
0805:                            Class aClass = Cl.getClassResolver().resolve(
0806:                                    Conversion.toJavaClass(className));
0807:                            // ok class exists...
0808:                            return className;
0809:                        } catch (ClassNotFoundException e) {
0810:                            if (pedantic) {
0811:                                throw new NoSuchMappingException("Class "
0812:                                        + Conversion.toJavaClass(className));
0813:                            } else {
0814:                                Logger.getInstance().warningToLogfile(
0815:                                        "Unresolved external dependency: "
0816:                                                + Conversion
0817:                                                        .toJavaClass(className)
0818:                                                + " not found!");
0819:                                Logger.getInstance().setUnresolved();
0820:                                return className;
0821:                            }
0822:                        }
0823:                    }
0824:                    return cl.getFullOutName();
0825:                }
0826:            }
0827:
0828:            /** Mapping for method name, of fully qualified class.
0829:             *  @see NameMapper#mapMethod */
0830:            public String mapMethod(String className, String methodName,
0831:                    String descriptor) {
0832:                // check if the className is an array...
0833:                if (className.startsWith("[") && className.endsWith(";")) {
0834:                    int count = 0;
0835:                    while (className.charAt(count) == '[') {
0836:                        count++;
0837:                    }
0838:                    if (className.charAt(count) == 'L') {
0839:                        className = className.substring(count + 1, className
0840:                                .length() - 1);
0841:                    }
0842:                }
0843:                Cl cl = getCl(className);
0844:                if (cl != null && cl.getMethod(methodName, descriptor) != null) {
0845:                    return cl.getMethod(methodName, descriptor).getOutName();
0846:                } else {
0847:                    if (cl == null) {
0848:                        try {
0849:                            Class aClass = Cl.getClassResolver().resolve(
0850:                                    Conversion.toJavaClass(className));
0851:                        } catch (ClassNotFoundException e) {
0852:                            if (pedantic) {
0853:                                throw new NoSuchMappingException("Class "
0854:                                        + Conversion.toJavaClass(className));
0855:                            } else {
0856:                                Logger
0857:                                        .getInstance()
0858:                                        .warningToLogfile(
0859:                                                "No mapping found: "
0860:                                                        + Conversion
0861:                                                                .toJavaClass(className));
0862:                            }
0863:                        }
0864:                        // method is not in database use unobfuscated name...
0865:                        return methodName;
0866:                    } else {
0867:                        try {
0868:                            //              System.out.println("Try: "+cl.getFieldObfNameUp(fieldName));
0869:                            String result = cl.getMethodOutNameUp(methodName,
0870:                                    descriptor);
0871:                            if (result != null)
0872:                                return result;
0873:                        } catch (Exception ex) {
0874:                            System.out.println(ex);
0875:                            //System.out.println("ME: Error: Try not succeeded");
0876:                        }
0877:                        if ((!methodName.equals("<init>") && (!methodName
0878:                                .equals("<clinit>")))) {
0879:                            if (pedantic) {
0880:                                throw new NoSuchMappingException("Method "
0881:                                        + Conversion.toJavaClass(className)
0882:                                        + "." + methodName);
0883:                            } else {
0884:                                Logger
0885:                                        .getInstance()
0886:                                        .error(
0887:                                                "Method "
0888:                                                        + Conversion
0889:                                                                .toJavaClass(className)
0890:                                                        + "."
0891:                                                        + methodName
0892:                                                        + " could not be mapped !\n Probably broken code! Try rebuilding from source!");
0893:                                return methodName;
0894:                            }
0895:                        }
0896:                        return methodName;
0897:                    }
0898:                }
0899:            }
0900:
0901:            /** Mapping for annotation field/method name, of fully qualified class.
0902:             *  @see NameMapper#mapAnnotationField */
0903:            public String mapAnnotationField(String className, String methodName) {
0904:                Cl cl = getCl(className);
0905:                if (cl != null) {
0906:                    for (Enumeration enumeration = cl.getMethodEnum(); enumeration
0907:                            .hasMoreElements();) {
0908:                        Md md = (Md) enumeration.nextElement();
0909:                        if (md.getInName().equals(methodName)) {
0910:                            return md.getOutName();
0911:                        }
0912:                    }
0913:                    // actually this should not happen - is this an exception?!
0914:                    return methodName;
0915:                } else {
0916:                    // method is not in database use unobfuscated name...
0917:                    return methodName;
0918:                }
0919:            }
0920:
0921:            /** Mapping for field name, of fully qualified class.
0922:             *  @see NameMapper#mapField */
0923:            public String mapField(String className, String fieldName) {
0924:                //        System.out.println("Map "+className+"."+fieldName);
0925:                Cl cl = getCl(className);
0926:                if ((cl != null) && (cl.getField(fieldName) != null)) {
0927:                    //special .class construct name mapping....
0928:                    if (fieldName.startsWith("class$")
0929:                            && isReplaceClassNameStrings()) {
0930:                        String realClassName = fieldName.substring(6);
0931:                        List nameParts = new ArrayList(20);
0932:                        for (StringTokenizer st = new StringTokenizer(
0933:                                realClassName, "$", false); st.hasMoreTokens();) {
0934:                            nameParts.add(st.nextToken());
0935:                        }
0936:                        String[] names = new String[nameParts.size()];
0937:                        nameParts.toArray(names);
0938:                        TreeItem ti = findTreeItem(names);
0939:                        if (ti instanceof  Cl) {
0940:                            Fd fd = cl.getField(fieldName);
0941:                            String newClassName = mapClass(ti.getFullInName());
0942:                            String outName = "class$"
0943:                                    + newClassName.replace('/', '$');
0944:                            fd.setOutName(outName);
0945:                            return outName;
0946:                        }
0947:                    }
0948:                    //        System.out.println("Standard Field Map");
0949:                    return cl.getField(fieldName).getOutName();
0950:                } else {
0951:                    if (cl == null) {
0952:                        //            System.out.println("Error: "+className+
0953:                        //                               " class not found !");
0954:                        return fieldName;
0955:                    } else {
0956:                        //            System.out.println("ERROR: "+className+"."+fieldName+
0957:                        //                               " cannot be mapped !");
0958:                        try {
0959:                            //              System.out.println("Try: "+cl.getFieldObfNameUp(fieldName));
0960:                            String result = cl.getFieldOutNameUp(fieldName);
0961:                            if (result != null)
0962:                                return result;
0963:                        } catch (Exception ex) {
0964:                            //              System.out.println("Try not succeeded");
0965:                        }
0966:                        if (!fieldName.equals("this")) {
0967:                            if (pedantic) {
0968:                                throw new NoSuchMappingException("Field "
0969:                                        + className + "." + fieldName);
0970:                            } else {
0971:                                Logger
0972:                                        .getInstance()
0973:                                        .error(
0974:                                                "Field "
0975:                                                        + className
0976:                                                        + "."
0977:                                                        + fieldName
0978:                                                        + " could not be mapped !\n Probably broken code! Try rebuilding from source!");
0979:                            }
0980:                        }
0981:                        return fieldName;
0982:                    }
0983:                }
0984:
0985:                //        return cl != null && cl.getField(fieldName) != null ?
0986:                //                    cl.getField(fieldName).getOutName() :
0987:                //                    fieldName;
0988:            }
0989:
0990:            /** Mapping for signatures (used for generics in 1.5).
0991:             *  @see NameMapper#mapSignature 
0992:             */
0993:            public String mapSignature(String signature) {
0994:                // Pass everything through unchanged, except for the String between
0995:                // 'L' and ';' -- this is passed through mapClass(String)
0996:
0997:                //      System.out.println( "signature: "+signature );
0998:
0999:                StringBuffer classString = new StringBuffer();
1000:
1001:                StringBuffer newSignature = new StringBuffer();
1002:                int i = 0;
1003:                while (i < signature.length()) {
1004:                    char ch = signature.charAt(i++);
1005:                    switch (ch) {
1006:                    case '[':
1007:                    case 'B':
1008:                    case 'C':
1009:                    case 'D':
1010:                    case 'F':
1011:                    case 'I':
1012:                    case 'J':
1013:                    case 'S':
1014:                    case 'Z':
1015:                    case 'V':
1016:                    case '(':
1017:                    case ')':
1018:                    case '+':
1019:                    case ':':
1020:                    case '-':
1021:                    case '*':
1022:                        newSignature.append(ch);
1023:                        break;
1024:                    case ';':
1025:                        newSignature.append(ch);
1026:                        classString.setLength(0);
1027:                        break;
1028:                    case 'T': { // Template name
1029:                        newSignature.append(ch);
1030:                        int pos = signature.indexOf(';', i);
1031:                        if (pos < 0) {
1032:                            throw new ParseException(
1033:                                    "Invalid signature string encountered.");
1034:                        }
1035:                        newSignature.append(signature.substring(i, pos));
1036:                        i = pos;
1037:                        break;
1038:                    }
1039:                    case '<': {
1040:                        // formal parameters
1041:                        newSignature.append(ch);
1042:                        while (true) {
1043:                            int first = i;
1044:                            while (signature.charAt(i) != ':') {
1045:                                i++;
1046:                            }
1047:                            String templateName = signature.substring(first, i);
1048:                            newSignature.append(templateName);
1049:
1050:                            while (signature.charAt(i) == ':') {
1051:                                newSignature.append(':');
1052:                                i++;
1053:                                int firstPos = i;
1054:                                int bracketCount = 0;
1055:                                while (!(bracketCount == 0 && signature
1056:                                        .charAt(i) == ';')) {
1057:                                    if (signature.charAt(i) == '<') {
1058:                                        bracketCount++;
1059:                                    } else if (signature.charAt(i) == '>') {
1060:                                        bracketCount--;
1061:                                    }
1062:                                    i++;
1063:                                }
1064:                                i++;
1065:                                newSignature.append(mapSignature(signature
1066:                                        .substring(firstPos, i)));
1067:                            }
1068:                            if (signature.charAt(i) == '>') {
1069:                                newSignature.append('>');
1070:                                i++;
1071:                                break;
1072:                            }
1073:                        }
1074:                        break;
1075:                    }
1076:
1077:                    case '^': {
1078:                        newSignature.append(ch);
1079:                        if (signature.charAt(i) == 'T') {
1080:                            // identifier
1081:                            while (signature.charAt(i) != ';') {
1082:                                newSignature.append(signature.charAt(i));
1083:                                i++;
1084:                            }
1085:                            continue;
1086:                        } else if (signature.charAt(i) == 'L') {
1087:                            // class
1088:                            int first = i;
1089:                            int bracketCount = 0;
1090:                            while (signature.charAt(i) != ';'
1091:                                    || bracketCount != 0) {
1092:                                char c = signature.charAt(i);
1093:                                if (c == '<') {
1094:                                    bracketCount++;
1095:                                } else if (c == '>') {
1096:                                    bracketCount--;
1097:                                }
1098:                                i++;
1099:                            }
1100:                            i++;
1101:                            String classSig = signature.substring(first, i);
1102:                            newSignature.append(mapSignature(classSig));
1103:                        } else {
1104:                            throw new IllegalStateException(
1105:                                    "Could not map signature " + signature);
1106:                        }
1107:                    }
1108:                        break;
1109:                    case 'L':
1110:                    case '.': // inner class
1111:                    {
1112:                        newSignature.append(ch);
1113:                        int pos = signature.indexOf(';', i);
1114:                        int bracketPos = signature.indexOf('<', i);
1115:                        if (bracketPos >= i && bracketPos < pos) {
1116:                            // found a bracket - find the matching one..
1117:                            int bracketCount = 0;
1118:                            int closingBracket = signature.length();
1119:                            for (int walker = bracketPos + 1; walker < signature
1120:                                    .length(); walker++) {
1121:                                char c = signature.charAt(walker);
1122:                                if (c == '<') {
1123:                                    bracketCount++;
1124:                                } else if (c == '>') {
1125:                                    if (bracketCount == 0) {
1126:                                        closingBracket = walker;
1127:                                        break;
1128:                                    } else {
1129:                                        bracketCount--;
1130:                                    }
1131:                                }
1132:                            }
1133:                            // TODO check!!!!
1134:                            pos = closingBracket + 1;
1135:                            //                  pos = signature.indexOf(';', closingBracket);
1136:                            String templateArg = signature.substring(
1137:                                    bracketPos + 1, closingBracket);
1138:                            String classNamePart = signature.substring(i,
1139:                                    bracketPos);
1140:                            if (ch == '.') { // inner class part - translate to class file name
1141:                                classString.append('$');
1142:                                classString.append(classNamePart);
1143:                                String className = classString.toString();
1144:                                String result;
1145:
1146:                                // do basically the same that mapClass() does, but return the last part only.
1147:                                Cl cl = getCl(className);
1148:                                if (cl == null) {
1149:                                    try {
1150:                                        Class aClass = Cl
1151:                                                .getClassResolver()
1152:                                                .resolve(
1153:                                                        Conversion
1154:                                                                .toJavaClass(className));
1155:                                        // ok class exists...
1156:                                        result = classNamePart;
1157:                                    } catch (ClassNotFoundException e) {
1158:                                        if (pedantic) {
1159:                                            throw new NoSuchMappingException(
1160:                                                    "Class "
1161:                                                            + Conversion
1162:                                                                    .toJavaClass(className));
1163:                                        } else {
1164:                                            Logger
1165:                                                    .getInstance()
1166:                                                    .warningToLogfile(
1167:                                                            "Unresolved external dependency: "
1168:                                                                    + Conversion
1169:                                                                            .toJavaClass(className)
1170:                                                                    + " not found!");
1171:                                            Logger.getInstance()
1172:                                                    .setUnresolved();
1173:                                            result = classNamePart;
1174:                                        }
1175:                                    }
1176:                                } else {
1177:                                    result = cl.getOutName();
1178:                                }
1179:                                newSignature.append(result);
1180:                            } else { // toplevel class 'L'
1181:                                classString.append(classNamePart);
1182:                                newSignature.append(mapClass(classString
1183:                                        .toString()));
1184:                            }
1185:                            newSignature.append('<');
1186:                            newSignature.append(mapSignature(templateArg));
1187:                            newSignature.append('>');
1188:                            i = pos;
1189:                        } else {
1190:                            if (pos < 0) {
1191:                                throw new ParseException(
1192:                                        "Invalid signature string encountered: "
1193:                                                + signature);
1194:                            }
1195:                            String classNamePart = signature.substring(i, pos);
1196:                            if (ch == '.') { // inner class part - translate to class file name
1197:                                classString.append('$');
1198:                            }
1199:                            classString.append(classNamePart);
1200:                            newSignature
1201:                                    .append(mapClass(classString.toString()));
1202:                            i = pos;
1203:                        }
1204:                        break;
1205:                    }
1206:                    default:
1207:                        throw new ParseException(
1208:                                "Invalid signature string encountered: "
1209:                                        + signature + " parsing char " + ch);
1210:                    }
1211:                }
1212:                return newSignature.toString();
1213:            }
1214:
1215:            public String mapSourceFile(String className, String sourceFileName) {
1216:                final Cl cl = getCl(className);
1217:                if (cl.isSourceFileMappingSet()) {
1218:                    return cl.getSourceFileMapping();
1219:                } else {
1220:                    return sourceFileName;
1221:                }
1222:            }
1223:
1224:            public boolean mapLineNumberTable(String className,
1225:                    String methodName, String methodSignature,
1226:                    LineNumberTableAttrInfo info) {
1227:                final Cl cl = getCl(className);
1228:                if (cl.getLineNumberTableMapper() != null) {
1229:                    return cl.getLineNumberTableMapper().mapLineNumberTable(
1230:                            className, methodName, methodSignature, info);
1231:                } else {
1232:                    return true;
1233:                }
1234:            }
1235:
1236:            /** Mapping for descriptor of field or method.
1237:             *  @see NameMapper#mapDescriptor */
1238:            public String mapDescriptor(String descriptor) {
1239:                // Pass everything through unchanged, except for the String between
1240:                // 'L' and ';' -- this is passed through mapClass(String)
1241:                StringBuffer newDesc = new StringBuffer();
1242:                int i = 0;
1243:                while (i < descriptor.length()) {
1244:                    char ch = descriptor.charAt(i++);
1245:                    switch (ch) {
1246:                    case '[':
1247:                    case 'B':
1248:                    case 'C':
1249:                    case 'D':
1250:                    case 'F':
1251:                    case 'I':
1252:                    case 'J':
1253:                    case 'S':
1254:                    case 'Z':
1255:                    case 'V':
1256:                    case '(':
1257:                    case ')':
1258:                    case ';':
1259:                        newDesc.append(ch);
1260:                        break;
1261:
1262:                    case 'L':
1263:                        newDesc.append(ch);
1264:                        int pos = descriptor.indexOf(';', i);
1265:                        if (pos < 0) {
1266:                            throw new ParseException(
1267:                                    "Invalid descriptor string encountered.");
1268:                        }
1269:                        newDesc.append(mapClass(descriptor.substring(i, pos)));
1270:                        i = pos;
1271:                        break;
1272:
1273:                    default:
1274:                        throw new ParseException(
1275:                                "Invalid descriptor string encountered.");
1276:                    }
1277:                }
1278:                return newDesc.toString();
1279:            }
1280:
1281:            /** Dump the content of the class tree to the specified file (used for logging). */
1282:            public void dump(final PrintWriter log) {
1283:                log.println("<expose>");
1284:                walkTree(new TreeAction() {
1285:                    public void classAction(Cl cl) {
1286:                        if (cl.isFromScript()) {
1287:                            String cla = toUtf8XmlString(Conversion
1288:                                    .toJavaClass(cl.getFullInName()));
1289:                            log.println("  <class name=\"" + cla + "\"/>");
1290:                        }
1291:                    }
1292:
1293:                    public void methodAction(Md md) {
1294:                        if (md.isFromScript()) {
1295:                            String cla = toUtf8XmlString(Conversion
1296:                                    .toJavaClass(md.getParent().getFullInName()));
1297:                            String method = toUtf8XmlString(Conversion
1298:                                    .toJavaMethod(md.getInName(), md
1299:                                            .getDescriptor()));
1300:                            log.println("  <method class=\"" + cla
1301:                                    + "\" name=\"" + method + "\"/>");
1302:                        }
1303:                    }
1304:
1305:                    public void fieldAction(Fd fd) {
1306:                        if (fd.isFromScript()) {
1307:                            String cla = toUtf8XmlString(Conversion
1308:                                    .toJavaClass(fd.getParent().getFullInName()));
1309:                            log.println("  <field class=\"" + cla
1310:                                    + "\" name=\""
1311:                                    + toUtf8XmlString(fd.getInName()) + "\"/>");
1312:                        }
1313:                    }
1314:
1315:                    public void packageAction(Pk pk) {
1316:                        // No action
1317:                    }
1318:                });
1319:                log.println("</expose>");
1320:                log.println("<map>");
1321:                walkTree(new TreeAction() {
1322:                    public void classAction(Cl cl) {
1323:                        if (!cl.isFromScript()) {
1324:                            String cla = toUtf8XmlString(Conversion
1325:                                    .toJavaClass(cl.getFullInName()));
1326:                            log
1327:                                    .println("  <class name=\""
1328:                                            + toUtf8XmlString(cla)
1329:                                            + "\" map=\""
1330:                                            + toUtf8XmlString(cl.getOutName())
1331:                                            + "\"/>");
1332:                        }
1333:                    }
1334:
1335:                    public void methodAction(Md md) {
1336:                        if (!md.isFromScript()) {
1337:                            String cla = toUtf8XmlString(Conversion
1338:                                    .toJavaClass(md.getParent().getFullInName()));
1339:                            String method = toUtf8XmlString(Conversion
1340:                                    .toJavaMethod(md.getInName(), md
1341:                                            .getDescriptor()));
1342:                            log
1343:                                    .println("  <method class=\"" + cla
1344:                                            + "\" name=\"" + method
1345:                                            + "\" map=\""
1346:                                            + toUtf8XmlString(md.getOutName())
1347:                                            + "\"/>");
1348:                        }
1349:                    }
1350:
1351:                    public void fieldAction(Fd fd) {
1352:                        if (!fd.isFromScript()) {
1353:                            String cla = toUtf8XmlString(Conversion
1354:                                    .toJavaClass(fd.getParent().getFullInName()));
1355:                            log
1356:                                    .println("  <field class=\"" + cla
1357:                                            + "\" name=\""
1358:                                            + toUtf8XmlString(fd.getInName())
1359:                                            + "\" map=\""
1360:                                            + toUtf8XmlString(fd.getOutName())
1361:                                            + "\"/>");
1362:                        }
1363:                    }
1364:
1365:                    public void packageAction(Pk pk) {
1366:                        if (!pk.isFromScript()
1367:                                && pk.getFullInName().length() > 0) {
1368:                            String pa = toUtf8XmlString(Conversion
1369:                                    .toJavaClass(pk.getFullInName()));
1370:                            log
1371:                                    .println("  <package name=\"" + pa
1372:                                            + "\" map=\""
1373:                                            + toUtf8XmlString(pk.getOutName())
1374:                                            + "\"/>");
1375:                        }
1376:                    }
1377:                });
1378:                log.println("</map>");
1379:            }
1380:
1381:            public static final String toUtf8XmlString(String s) {
1382:                boolean bad = false;
1383:                for (int i = 0; i < s.length(); i++) {
1384:                    char c = s.charAt(i);
1385:                    if ((c >= 0x80) || (c == '"') || (c == '<')) {
1386:                        bad = true;
1387:                        break;
1388:                    }
1389:                }
1390:                if (bad) {
1391:                    StringBuffer buf = new StringBuffer(s.length());
1392:                    for (int i = 0; i < s.length(); i++) {
1393:                        buf.append(toUtf8XmlChar(s.charAt(i)));
1394:                    }
1395:                    return buf.toString();
1396:                } else {
1397:                    return s;
1398:                }
1399:            }
1400:
1401:            private static final String toUtf8XmlChar(char c) {
1402:                if (c < 0x80) {
1403:                    if (c == '"') {
1404:                        return "&#x22;";
1405:                    } else if (c == '<') {
1406:                        return "&#x3c;";
1407:                    }
1408:                    return new String(new char[] { c });
1409:                } else if (c < 0x800) {
1410:                    StringBuffer buf = new StringBuffer(8);
1411:                    buf.append("&#x");
1412:                    buf.append(hex[(c >> 8) & 0xff]);
1413:                    buf.append(hex[c & 0xff]);
1414:                    buf.append(';');
1415:                    return buf.toString();
1416:                } else {
1417:                    StringBuffer buf = new StringBuffer(10);
1418:                    buf.append("&#x");
1419:                    buf.append(hex[(c >> 16) & 0xff]);
1420:                    buf.append(hex[(c >> 8) & 0xff]);
1421:                    buf.append(hex[c & 0xff]);
1422:                    buf.append(';');
1423:                    return buf.toString();
1424:                }
1425:            }
1426:
1427:            private static final String[] hex;
1428:            static {
1429:                hex = new String[256];
1430:                for (int i = 0; i < 256; i++) {
1431:                    hex[i] = toHex(i);
1432:                }
1433:            }
1434:
1435:            private static final String hexChars = "0123456789abcdef";
1436:
1437:            /** Holds value of property replaceClassNameStrings. */
1438:            private boolean replaceClassNameStrings;
1439:
1440:            /** Holds value of property pedantic. */
1441:            private boolean pedantic;
1442:
1443:            private static String toHex(int i) {
1444:                StringBuffer buf = new StringBuffer(2);
1445:                buf.append(hexChars.charAt((i / 16) & 15));
1446:                buf.append(hexChars.charAt(i & 15));
1447:                return buf.toString();
1448:            }
1449:
1450:            // Private Methods -------------------------------------------------------
1451:            // Mark TreeItem and all parents for retention.
1452:            private void retainHierarchy(TreeItem ti) {
1453:                if (!ti.isFixed()) {
1454:                    ti.setOutName(ti.getInName());
1455:                    ti.setFromScript();
1456:                }
1457:                if (ti.parent != null) {
1458:                    retainHierarchy(ti.parent);
1459:                }
1460:            }
1461:
1462:            /** Walk the whole tree taking action once only on each package level, class, method and field. */
1463:            public void walkTree(TreeAction ta) {
1464:                walkTree(ta, root);
1465:            }
1466:
1467:            // Walk the tree which has TreeItem as its root taking action once only on each
1468:            // package level, class, method and field.
1469:            private void walkTree(TreeAction ta, TreeItem ti) {
1470:                if (ti instanceof  Pk) {
1471:                    Enumeration packageEnum = ((Pk) ti).getPackageEnum();
1472:                    ta.packageAction((Pk) ti);
1473:                    while (packageEnum.hasMoreElements()) {
1474:                        walkTree(ta, (TreeItem) packageEnum.nextElement());
1475:                    }
1476:                }
1477:                if (ti instanceof  PkCl) {
1478:                    Enumeration classEnum = ((PkCl) ti).getClassEnum();
1479:                    while (classEnum.hasMoreElements()) {
1480:                        walkTree(ta, (TreeItem) classEnum.nextElement());
1481:                    }
1482:                }
1483:                if (ti instanceof  Cl) {
1484:                    Enumeration fieldEnum = ((Cl) ti).getFieldEnum();
1485:                    Enumeration methodEnum = ((Cl) ti).getMethodEnum();
1486:                    ta.classAction((Cl) ti);
1487:                    while (fieldEnum.hasMoreElements()) {
1488:                        ta.fieldAction((Fd) fieldEnum.nextElement());
1489:                    }
1490:                    while (methodEnum.hasMoreElements()) {
1491:                        ta.methodAction((Md) methodEnum.nextElement());
1492:                    }
1493:                }
1494:            }
1495:
1496:            /** Getter for property replaceClassNameStrings.
1497:             * @return Value of property replaceClassNameStrings.
1498:             *
1499:             */
1500:            public boolean isReplaceClassNameStrings() {
1501:                return this .replaceClassNameStrings;
1502:            }
1503:
1504:            /** Setter for property replaceClassNameStrings.
1505:             * @param replaceClassNameStrings New value of property replaceClassNameStrings.
1506:             *
1507:             */
1508:            public void setReplaceClassNameStrings(
1509:                    boolean replaceClassNameStrings) {
1510:                this .replaceClassNameStrings = replaceClassNameStrings;
1511:            }
1512:
1513:            /** Getter for property pedantic.
1514:             * @return Value of property pedantic.
1515:             *
1516:             */
1517:            public boolean isPedantic() {
1518:                return this .pedantic;
1519:            }
1520:
1521:            /** Setter for property pedantic.
1522:             * @param pedantic New value of property pedantic.
1523:             *
1524:             */
1525:            public void setPedantic(boolean pedantic) {
1526:                this .pedantic = pedantic;
1527:            }
1528:
1529:            public void retainSourceFileAttributeMap(String name, String obfName) {
1530:                for (Enumeration clEnum = getClEnum(name); clEnum
1531:                        .hasMoreElements();) {
1532:                    Cl classItem = (Cl) clEnum.nextElement();
1533:                    classItem.setSourceFileMapping(obfName);
1534:                    classItem.getAttributesToKeep().add(
1535:                            ClassConstants.ATTR_SourceFile);
1536:                }
1537:            }
1538:
1539:            public void retainLineNumberTable(String name,
1540:                    final LineNumberTableMapper lineNumberTableMapper) {
1541:                for (Enumeration clEnum = getClEnum(name); clEnum
1542:                        .hasMoreElements();) {
1543:                    Cl classItem = (Cl) clEnum.nextElement();
1544:                    classItem.setLineNumberTableMapper(lineNumberTableMapper);
1545:                    classItem.getAttributesToKeep().add(
1546:                            ClassConstants.ATTR_LineNumberTable);
1547:                }
1548:            }
1549:
1550:            public void retainAttributeForClass(String className,
1551:                    String attributeDescriptor) {
1552:                for (Enumeration clEnum = getClEnum(className); clEnum
1553:                        .hasMoreElements();) {
1554:                    Cl classItem = (Cl) clEnum.nextElement();
1555:                    final Set set = classItem.getAttributesToKeep();
1556:                    set.add(attributeDescriptor);
1557:                }
1558:            }
1559:
1560:            public void retainPackage(String packageName) {
1561:                retainHierarchy(getPk(packageName));
1562:            }
1563:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.