Source Code Cross Referenced for ClassFile.java in  » Development » yguardlib » com » yworks » yguard » obf » classfile » 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.classfile 
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.classfile;
0026:
0027:        import java.io.*;
0028:        import java.util.*;
0029:        import com.yworks.yguard.obf.*;
0030:        import java.lang.reflect.Modifier;
0031:        import com.yworks.yguard.Conversion;
0032:        import com.yworks.yguard.ParseException;
0033:
0034:        /**
0035:         * This is a representation of the data in a Java class-file (*.class).
0036:         * A ClassFile instance representing a *.class file can be generated
0037:         * using the static create(DataInput) method, manipulated using various
0038:         * operators, and persisted back using the write(DataOutput) method.
0039:         *
0040:         * @author      Mark Welsh
0041:         */
0042:        public class ClassFile implements  ClassConstants {
0043:            // Constants -------------------------------------------------------------
0044:            public static final String SEP_REGULAR = "/";
0045:            public static final String SEP_INNER = "$";
0046:            public static final String LOG_DANGER_HEADER1 = "Methods are called which may break in obfuscated version at runtime.";
0047:            public static final String LOG_DANGER_HEADER2 = "Please review your source code to ensure that the dangerous methods are not intended";
0048:            public static final String LOG_DANGER_HEADER3 = "to act on classes which have been obfuscated.";
0049:            private static final String[] SEMI_DANGEROUS_CLASS_SIMPLENAME_DESCRIPTOR_ARRAY = {
0050:                    "forName(Ljava/lang/String;)Ljava/lang/Class;",
0051:                    "forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", };
0052:            private static final String[] DANGEROUS_CLASS_SIMPLENAME_DESCRIPTOR_ARRAY = {
0053:                    "forName(Ljava/lang/String;)Ljava/lang/Class;",
0054:                    "forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
0055:                    "getDeclaredField(Ljava/lang/String;)Ljava/lang/reflect/Field;",
0056:                    "getField(Ljava/lang/String;)Ljava/lang/reflect/Field;",
0057:                    "getDeclaredMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;",
0058:                    "getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" };
0059:            private static final String LOG_DANGER_CLASS_PRE = "    Your class ";
0060:            private static final String LOG_DANGER_CLASS_MID = " calls the java.lang.Class method ";
0061:            private static final String[] DANGEROUS_CLASSLOADER_SIMPLENAME_DESCRIPTOR_ARRAY = {
0062:                    "defineClass(Ljava/lang/String;[BII)Ljava/lang/Class;",
0063:                    "findLoadedClass(Ljava/lang/String;)Ljava/lang/Class;",
0064:                    "findSystemClass(Ljava/lang/String;)Ljava/lang/Class;",
0065:                    "loadClass(Ljava/lang/String;)Ljava/lang/Class;",
0066:                    "loadClass(Ljava/lang/String;Z)Ljava/lang/Class;" };
0067:            private static final String LOG_DANGER_CLASSLOADER_PRE = "    Your class ";
0068:            private static final String LOG_DANGER_CLASSLOADER_MID = " calls the java.lang.ClassLoader method ";
0069:
0070:            // Fields ----------------------------------------------------------------
0071:            private int u4magic;
0072:            private int u2minorVersion;
0073:            private int u2majorVersion;
0074:            private ConstantPool constantPool;
0075:            private int u2accessFlags;
0076:            private int u2this Class;
0077:            private int u2super Class;
0078:            private int u2interfacesCount;
0079:            private int u2interfaces[];
0080:            private int u2fieldsCount;
0081:            private FieldInfo fields[];
0082:            private int u2methodsCount;
0083:            private MethodInfo methods[];
0084:            private int u2attributesCount;
0085:            private AttrInfo attributes[];
0086:
0087:            private boolean isUnkAttrGone = false;
0088:
0089:            private static boolean writeIdString = false;
0090:            private static CpInfo cpIdString = null;
0091:
0092:            // Class Methods ---------------------------------------------------------
0093:            /**
0094:             * Define a constant String to include in every output class file.
0095:             */
0096:            public static void defineIdString(String id) {
0097:                if (id != null) {
0098:                    writeIdString = true;
0099:                    cpIdString = new Utf8CpInfo(id);
0100:                } else {
0101:                    writeIdString = false;
0102:                    cpIdString = null;
0103:                }
0104:            }
0105:
0106:            /**
0107:             * Create a new ClassFile from the class file format data in the DataInput
0108:             * stream.
0109:             *
0110:             * @throws IOException if class file is corrupt or incomplete
0111:             */
0112:            public static ClassFile create(DataInput din)
0113:                    throws java.io.IOException {
0114:                if (din == null)
0115:                    throw new NullPointerException(
0116:                            "No input stream was provided.");
0117:                ClassFile cf = new ClassFile();
0118:                cf.read(din);
0119:                return cf;
0120:            }
0121:
0122:            /** Parse a method or field descriptor into a list of parameter names (for methods)
0123:             *  and a return type, in same format as the Class.forName() method returns . */
0124:            public static String[] parseDescriptor(String descriptor) {
0125:                return parseDescriptor(descriptor, false);
0126:            }
0127:
0128:            /** Parse a method or field descriptor into a list of parameter names (for methods)
0129:             *  and a return type, in same format as the Class.forName() method returns . */
0130:            public static String[] parseDescriptor(String descriptor,
0131:                    boolean isDisplay) {
0132:                // Check for field descriptor
0133:                String[] names = null;
0134:                if (descriptor.charAt(0) != '(') {
0135:                    names = new String[1];
0136:                    names[0] = descriptor;
0137:                } else {
0138:                    // Method descriptor
0139:                    Vector namesVec = new Vector();
0140:                    descriptor = descriptor.substring(1);
0141:                    String type = "";
0142:                    while (descriptor.length() > 0) {
0143:                        switch (descriptor.charAt(0)) {
0144:                        case '[':
0145:                            type = type + "[";
0146:                            descriptor = descriptor.substring(1);
0147:                            break;
0148:
0149:                        case 'B':
0150:                        case 'C':
0151:                        case 'D':
0152:                        case 'F':
0153:                        case 'I':
0154:                        case 'J':
0155:                        case 'S':
0156:                        case 'Z':
0157:                        case 'V':
0158:                            namesVec.addElement(type
0159:                                    + descriptor.substring(0, 1));
0160:                            descriptor = descriptor.substring(1);
0161:                            type = "";
0162:                            break;
0163:
0164:                        case ')':
0165:                            descriptor = descriptor.substring(1);
0166:                            break;
0167:
0168:                        case 'L': {
0169:                            int pos = descriptor.indexOf(';') + 1;
0170:                            namesVec.addElement(type
0171:                                    + descriptor.substring(0, pos));
0172:                            descriptor = descriptor.substring(pos);
0173:                            type = "";
0174:                        }
0175:                            break;
0176:
0177:                        default:
0178:                            throw new IllegalArgumentException(
0179:                                    "Illegal field or method descriptor: "
0180:                                            + descriptor);
0181:                        }
0182:                    }
0183:                    names = new String[namesVec.size()];
0184:                    for (int i = 0; i < names.length; i++) {
0185:                        names[i] = (String) namesVec.elementAt(i);
0186:                    }
0187:                }
0188:
0189:                // Translate the names from JVM to Class.forName() format.
0190:                String[] translatedNames = new String[names.length];
0191:                for (int i = 0; i < names.length; i++) {
0192:                    translatedNames[i] = translateType(names[i], isDisplay);
0193:                }
0194:                return translatedNames;
0195:            }
0196:
0197:            /** Translate a type specifier from the internal JVM convention to the Class.forName() one. */
0198:            public static String translateType(String inName, boolean isDisplay) {
0199:                String outName = null;
0200:                switch (inName.charAt(0)) {
0201:                case '[': // For array types, Class.forName() inconsistently uses the internal type name
0202:                    // but with '/' --> '.'
0203:                    if (!isDisplay) {
0204:                        // return the Class.forName() form
0205:                        outName = translate(inName);
0206:                    } else {
0207:                        // return the pretty display form
0208:                        outName = translateType(inName.substring(1), true)
0209:                                + "[]";
0210:                    }
0211:                    break;
0212:
0213:                case 'B':
0214:                    outName = Byte.TYPE.getName();
0215:                    break;
0216:
0217:                case 'C':
0218:                    outName = Character.TYPE.getName();
0219:                    break;
0220:
0221:                case 'D':
0222:                    outName = Double.TYPE.getName();
0223:                    break;
0224:
0225:                case 'F':
0226:                    outName = Float.TYPE.getName();
0227:                    break;
0228:
0229:                case 'I':
0230:                    outName = Integer.TYPE.getName();
0231:                    break;
0232:
0233:                case 'J':
0234:                    outName = Long.TYPE.getName();
0235:                    break;
0236:
0237:                case 'S':
0238:                    outName = Short.TYPE.getName();
0239:                    break;
0240:
0241:                case 'Z':
0242:                    outName = Boolean.TYPE.getName();
0243:                    break;
0244:
0245:                case 'V':
0246:                    outName = Void.TYPE.getName();
0247:                    break;
0248:
0249:                case 'L': {
0250:                    int pos = inName.indexOf(';');
0251:                    outName = translate(inName
0252:                            .substring(1, inName.indexOf(';')));
0253:                }
0254:                    break;
0255:
0256:                default:
0257:                    throw new IllegalArgumentException(
0258:                            "Illegal field or method name: " + inName);
0259:                }
0260:                return outName;
0261:            }
0262:
0263:            /** Translate a class name from the internal '/' convention to the regular '.' one. */
0264:            public static String translate(String name) {
0265:                return name.replace('/', '.');
0266:            }
0267:
0268:            // Instance Methods ------------------------------------------------------
0269:            // Private constructor.
0270:            private ClassFile() {
0271:            }
0272:
0273:            // Import the class data to internal representation.
0274:            private void read(DataInput din) throws java.io.IOException {
0275:                // Read the class file
0276:                u4magic = din.readInt();
0277:                u2minorVersion = din.readUnsignedShort();
0278:                u2majorVersion = din.readUnsignedShort();
0279:
0280:                // Check this is a valid classfile that we can handle
0281:                if (u4magic != MAGIC) {
0282:                    throw new IOException("Invalid magic number in class file.");
0283:                }
0284:                if (u2majorVersion > MAJOR_VERSION) {
0285:                    throw new IOException(
0286:                            "Incompatible version number for class file format: "
0287:                                    + u2majorVersion + "." + u2minorVersion);
0288:                }
0289:
0290:                int u2constantPoolCount = din.readUnsignedShort();
0291:                CpInfo[] cpInfo = new CpInfo[u2constantPoolCount];
0292:                // Fill the constant pool, recalling the zero entry
0293:                // is not persisted, nor are the entries following a Long or Double
0294:                for (int i = 1; i < u2constantPoolCount; i++) {
0295:                    cpInfo[i] = CpInfo.create(din);
0296:                    if ((cpInfo[i] instanceof  LongCpInfo)
0297:                            || (cpInfo[i] instanceof  DoubleCpInfo)) {
0298:                        i++;
0299:                    }
0300:                }
0301:                constantPool = new ConstantPool(this , cpInfo);
0302:
0303:                u2accessFlags = din.readUnsignedShort();
0304:                u2this Class = din.readUnsignedShort();
0305:                u2super Class = din.readUnsignedShort();
0306:                u2interfacesCount = din.readUnsignedShort();
0307:                u2interfaces = new int[u2interfacesCount];
0308:                for (int i = 0; i < u2interfacesCount; i++) {
0309:                    u2interfaces[i] = din.readUnsignedShort();
0310:                }
0311:                u2fieldsCount = din.readUnsignedShort();
0312:                fields = new FieldInfo[u2fieldsCount];
0313:                for (int i = 0; i < u2fieldsCount; i++) {
0314:                    fields[i] = FieldInfo.create(din, this );
0315:                }
0316:                u2methodsCount = din.readUnsignedShort();
0317:                methods = new MethodInfo[u2methodsCount];
0318:                for (int i = 0; i < u2methodsCount; i++) {
0319:                    methods[i] = MethodInfo.create(din, this );
0320:                }
0321:                u2attributesCount = din.readUnsignedShort();
0322:                attributes = new AttrInfo[u2attributesCount];
0323:                for (int i = 0; i < u2attributesCount; i++) {
0324:                    attributes[i] = AttrInfo.create(din, this );
0325:                }
0326:            }
0327:
0328:            public int getClassFileAccess() {
0329:                return u2accessFlags;
0330:            }
0331:
0332:            public int getModifiers() {
0333:                int mods = 0;
0334:                if ((u2accessFlags & 0x0001) == 0x0001)
0335:                    mods |= Modifier.PUBLIC;
0336:                if ((u2accessFlags & 0x0010) == 0x0010)
0337:                    mods |= Modifier.FINAL;
0338:                if ((u2accessFlags & 0x0200) == 0x0200)
0339:                    mods |= Modifier.INTERFACE;
0340:                if ((u2accessFlags & 0x0400) == 0x0400)
0341:                    mods |= Modifier.ABSTRACT;
0342:                return mods;
0343:            }
0344:
0345:            /** Return the name of this classfile. */
0346:            public String getName() {
0347:                return toName(u2this Class);
0348:            }
0349:
0350:            /** Return the name of this class's superclass. */
0351:            public String getSuper() {
0352:                // This may be java/lang/Object, in which case there is no super
0353:                return (u2super Class == 0) ? null : toName(u2super Class);
0354:            }
0355:
0356:            /** Return the names of this class's interfaces. */
0357:            public String[] getInterfaces() {
0358:                String[] interfaces = new String[u2interfacesCount];
0359:                for (int i = 0; i < u2interfacesCount; i++) {
0360:                    interfaces[i] = toName(u2interfaces[i]);
0361:                }
0362:                return interfaces;
0363:            }
0364:
0365:            // Convert a CP index to a class name.
0366:            private String toName(int u2index) {
0367:                CpInfo classEntry = getCpEntry(u2index);
0368:                if (classEntry instanceof  ClassCpInfo) {
0369:                    CpInfo nameEntry = getCpEntry(((ClassCpInfo) classEntry)
0370:                            .getNameIndex());
0371:                    if (nameEntry instanceof  Utf8CpInfo) {
0372:                        return ((Utf8CpInfo) nameEntry).getString();
0373:                    } else {
0374:                        throw new ParseException(
0375:                                "Inconsistent Constant Pool in class file.");
0376:                    }
0377:                } else {
0378:                    throw new ParseException(
0379:                            "Inconsistent Constant Pool in class file.");
0380:                }
0381:            }
0382:
0383:            /** Return an enumeration of method name/descriptor pairs. */
0384:            public Enumeration getMethodEnum() {
0385:                Vector vec = new Vector();
0386:                for (int i = 0; i < methods.length; i++) {
0387:                    vec.addElement(new Cons(new Cons(new Boolean(methods[i]
0388:                            .isSynthetic()), methods[i].getName()), new Cons(
0389:                            methods[i].getDescriptor(), new Integer(methods[i]
0390:                                    .getAccessFlags()))));
0391:                }
0392:                return vec.elements();
0393:            }
0394:
0395:            /** Return an enumeration of field name/descriptor pairs. */
0396:            public Enumeration getFieldEnum() {
0397:                Vector vec = new Vector();
0398:                for (int i = 0; i < fields.length; i++) {
0399:                    vec.addElement(new Cons(new Cons(new Boolean(fields[i]
0400:                            .isSynthetic()), fields[i].getName()), new Cons(
0401:                            fields[i].getDescriptor(), new Integer(fields[i]
0402:                                    .getAccessFlags()))));
0403:                }
0404:                return vec.elements();
0405:            }
0406:
0407:            /** Lookup the entry in the constant pool and return as an Object. */
0408:            protected CpInfo getCpEntry(int cpIndex) {
0409:                return constantPool.getCpEntry(cpIndex);
0410:            }
0411:
0412:            /** Check for methods which can break the obfuscated code, and log them to a String[]. */
0413:            public String[] logDangerousMethods(boolean replaceClassNameStrings) {
0414:                Vector warningVec = new Vector();
0415:
0416:                // Need only check CONSTANT_Methodref entries of constant pool since
0417:                // dangerous methods belong to classes 'Class' and 'ClassLoader', not to interfaces.
0418:                for (Enumeration enumeration = constantPool.elements(); enumeration
0419:                        .hasMoreElements();) {
0420:                    Object o = enumeration.nextElement();
0421:                    if (o instanceof  MethodrefCpInfo) {
0422:                        // Get the method class name, simple name and descriptor
0423:                        MethodrefCpInfo entry = (MethodrefCpInfo) o;
0424:                        ClassCpInfo classEntry = (ClassCpInfo) getCpEntry(entry
0425:                                .getClassIndex());
0426:                        String className = ((Utf8CpInfo) getCpEntry(classEntry
0427:                                .getNameIndex())).getString();
0428:                        NameAndTypeCpInfo ntEntry = (NameAndTypeCpInfo) getCpEntry(entry
0429:                                .getNameAndTypeIndex());
0430:                        String name = ((Utf8CpInfo) getCpEntry(ntEntry
0431:                                .getNameIndex())).getString();
0432:                        String descriptor = ((Utf8CpInfo) getCpEntry(ntEntry
0433:                                .getDescriptorIndex())).getString();
0434:
0435:                        // Check if this is on the proscribed list
0436:                        if (className.equals("java/lang/Class")
0437:                                && Tools
0438:                                        .isInArray(name + descriptor,
0439:                                                DANGEROUS_CLASS_SIMPLENAME_DESCRIPTOR_ARRAY)) {
0440:                            if (replaceClassNameStrings) {
0441:                                if (!Tools
0442:                                        .isInArray(name + descriptor,
0443:                                                SEMI_DANGEROUS_CLASS_SIMPLENAME_DESCRIPTOR_ARRAY)) {
0444:                                    String jMethod = Conversion.toJavaMethod(
0445:                                            name, descriptor);
0446:                                    warningVec.addElement(LOG_DANGER_CLASS_PRE
0447:                                            + Conversion.toJavaClass(getName())
0448:                                            + LOG_DANGER_CLASS_MID + jMethod);
0449:                                }
0450:                            }
0451:                        } else if (Tools
0452:                                .isInArray(name + descriptor,
0453:                                        DANGEROUS_CLASSLOADER_SIMPLENAME_DESCRIPTOR_ARRAY)) {
0454:                            String jMethod = Conversion.toJavaMethod(name,
0455:                                    descriptor);
0456:                            warningVec.addElement(LOG_DANGER_CLASSLOADER_PRE
0457:                                    + Conversion.toJavaClass(getName())
0458:                                    + LOG_DANGER_CLASSLOADER_MID + jMethod);
0459:                        } else if ("class$(Ljava/lang/String;)Ljava/lang/Class;"
0460:                                .equals(name + descriptor)) {
0461:                            if (!replaceClassNameStrings) {
0462:                                warningVec
0463:                                        .addElement(LOG_DANGER_CLASS_PRE
0464:                                                + Conversion
0465:                                                        .toJavaClass(getName())
0466:                                                + " seems to be using the '.class' construct!");
0467:                            }
0468:                        }
0469:                    }
0470:                }
0471:
0472:                // Copy any warnings to a String[]
0473:                String[] warnings = new String[warningVec.size()];
0474:                for (int i = 0; i < warnings.length; i++) {
0475:                    warnings[i] = (String) warningVec.elementAt(i);
0476:                }
0477:                return warnings;
0478:            }
0479:
0480:            /** Check for methods which can break the obfuscated code, and log them. */
0481:            private static boolean hasHeader = false;
0482:
0483:            public static void resetDangerHeader() {
0484:                hasHeader = false;
0485:            }
0486:
0487:            public void logDangerousMethods(PrintWriter log,
0488:                    boolean replaceClassNameStrings) {
0489:                // Get any warnings and print them to the logfile
0490:                String[] warnings = logDangerousMethods(replaceClassNameStrings);
0491:                if (warnings != null && warnings.length > 0) {
0492:                    if (!hasHeader) {
0493:                        log.println("<!-- WARNING");
0494:                        log.println(LOG_DANGER_HEADER1);
0495:                        log.println(LOG_DANGER_HEADER2);
0496:                        log.println(LOG_DANGER_HEADER3);
0497:
0498:                        Logger logger = Logger.getInstance();
0499:                        logger
0500:                                .warning(LOG_DANGER_HEADER1
0501:                                        + '\n'
0502:                                        + LOG_DANGER_HEADER2
0503:                                        + '\n'
0504:                                        + LOG_DANGER_HEADER3
0505:                                        + '\n'
0506:                                        + "See the logfile for a list of these classes and methods.");
0507:
0508:                        log.println("-->");
0509:                        hasHeader = true;
0510:                    }
0511:                    if (warnings.length > 0) {
0512:                        log.println("<!--");
0513:                        for (int i = 0; i < warnings.length; i++) {
0514:                            log.println(" " + warnings[i]);
0515:                        }
0516:                        log.println("-->");
0517:                    }
0518:                }
0519:            }
0520:
0521:            /** Check for direct references to Utf8 constant pool entries. */
0522:            public void markUtf8Refs(ConstantPool pool) {
0523:                try {
0524:                    // Check for references to Utf8 from outside the constant pool
0525:                    for (int i = 0; i < fields.length; i++) {
0526:                        fields[i].markUtf8Refs(pool);
0527:                    }
0528:                    for (int i = 0; i < methods.length; i++) {
0529:                        methods[i].markUtf8Refs(pool); // also checks Code/LVT attrs here
0530:                    }
0531:                    for (int i = 0; i < attributes.length; i++) {
0532:                        attributes[i].markUtf8Refs(pool); // checks InnerClasses, SourceFile and all attr names
0533:                    }
0534:
0535:                    // Now check for references from other CP entries
0536:                    for (Enumeration enumeration = pool.elements(); enumeration
0537:                            .hasMoreElements();) {
0538:                        Object o = enumeration.nextElement();
0539:                        if (o instanceof  NameAndTypeCpInfo
0540:                                || o instanceof  ClassCpInfo
0541:                                || o instanceof  StringCpInfo) {
0542:                            ((CpInfo) o).markUtf8Refs(pool);
0543:                        }
0544:                    }
0545:                } catch (ArrayIndexOutOfBoundsException e) {
0546:                    throw new ParseException(
0547:                            "Inconsistent reference to constant pool.");
0548:                }
0549:            }
0550:
0551:            /** Check for direct references to NameAndType constant pool entries. */
0552:            public void markNTRefs(ConstantPool pool) {
0553:                try {
0554:                    // Now check the method and field CP entries
0555:                    for (Enumeration enumeration = pool.elements(); enumeration
0556:                            .hasMoreElements();) {
0557:                        Object o = enumeration.nextElement();
0558:                        if (o instanceof  RefCpInfo) {
0559:                            ((CpInfo) o).markNTRefs(pool);
0560:                        }
0561:                    }
0562:                } catch (ArrayIndexOutOfBoundsException e) {
0563:                    throw new ParseException(
0564:                            "Inconsistent reference to constant pool.");
0565:                }
0566:            }
0567:
0568:            /**
0569:             * Trim attributes from the classfile ('Code', 'Exceptions', 'ConstantValue'
0570:             * are preserved, all others except the list in the String[] are killed).
0571:             */
0572:            public void trimAttrsExcept(String[] extraAttrs) {
0573:                // Merge additional attributes with required list
0574:                String[] keepAttrs = REQUIRED_ATTRS;
0575:                if (extraAttrs != null && extraAttrs.length > 0) {
0576:                    String[] tmp = new String[keepAttrs.length
0577:                            + extraAttrs.length];
0578:                    System.arraycopy(keepAttrs, 0, tmp, 0, keepAttrs.length);
0579:                    System.arraycopy(extraAttrs, 0, tmp, keepAttrs.length,
0580:                            extraAttrs.length);
0581:                    keepAttrs = tmp;
0582:                }
0583:
0584:                // Traverse all attributes, removing all except those on 'keep' list
0585:                for (int i = 0; i < fields.length; i++) {
0586:                    fields[i].trimAttrsExcept(keepAttrs);
0587:                }
0588:                for (int i = 0; i < methods.length; i++) {
0589:                    methods[i].trimAttrsExcept(keepAttrs);
0590:                }
0591:                for (int i = 0; i < attributes.length; i++) {
0592:                    if (Tools.isInArray(attributes[i].getAttrName(), keepAttrs)) {
0593:                        attributes[i].trimAttrsExcept(keepAttrs);
0594:                    } else {
0595:                        attributes[i] = null;
0596:                    }
0597:                }
0598:
0599:                // Delete the marked attributes
0600:                AttrInfo[] left = new AttrInfo[attributes.length];
0601:                int j = 0;
0602:                for (int i = 0; i < attributes.length; i++) {
0603:                    if (attributes[i] != null) {
0604:                        left[j++] = attributes[i];
0605:                    }
0606:                }
0607:                attributes = new AttrInfo[j];
0608:                System.arraycopy(left, 0, attributes, 0, j);
0609:                u2attributesCount = j;
0610:
0611:                // Signal that unknown attributes are gone
0612:                isUnkAttrGone = true;
0613:
0614:                // Update the constant pool reference counts
0615:                constantPool.updateRefCount();
0616:            }
0617:
0618:            public Map getInnerClassModifiers() {
0619:                Map map = new HashMap();
0620:                for (int i = 0; i < u2attributesCount; i++) {
0621:                    AttrInfo attrInfo = attributes[i];
0622:                    if (attrInfo instanceof  InnerClassesAttrInfo) {
0623:                        InnerClassesInfo[] info = ((InnerClassesAttrInfo) attrInfo)
0624:                                .getInfo();
0625:                        for (int j = 0; j < info.length; j++) {
0626:                            InnerClassesInfo ici = info[j];
0627:                            int index = info[j].getInnerNameIndex();
0628:                            if (index == 0) { // unnamed inner class
0629:                                continue;
0630:                            }
0631:                            CpInfo cpInfo = getCpEntry(info[j]
0632:                                    .getInnerNameIndex());
0633:                            if (cpInfo instanceof  Utf8CpInfo) {
0634:                                Utf8CpInfo utf = (Utf8CpInfo) cpInfo;
0635:                                String origClass = utf.getString();
0636:                                map.put(origClass, new Integer(ici
0637:                                        .getModifiers()));
0638:                            }
0639:                        }
0640:                    }
0641:                }
0642:                return map;
0643:            }
0644:
0645:            /**
0646:             * Trim attributes from the classfile ('Code', 'Exceptions', 'ConstantValue'
0647:             * are preserved, all others are killed).
0648:             */
0649:            public void trimAttrs() {
0650:                trimAttrsExcept(null);
0651:            }
0652:
0653:            private boolean containsDotClassMethodReference() {
0654:                // Need only check CONSTANT_Methodref entries of constant pool since
0655:                // dangerous methods belong to classes 'Class' and 'ClassLoader', not to interfaces.
0656:                for (Enumeration enumeration = constantPool.elements(); enumeration
0657:                        .hasMoreElements();) {
0658:                    Object o = enumeration.nextElement();
0659:                    if (o instanceof  MethodrefCpInfo) {
0660:                        // Get the method class name, simple name and descriptor
0661:                        MethodrefCpInfo entry = (MethodrefCpInfo) o;
0662:                        ClassCpInfo classEntry = (ClassCpInfo) getCpEntry(entry
0663:                                .getClassIndex());
0664:                        String className = ((Utf8CpInfo) getCpEntry(classEntry
0665:                                .getNameIndex())).getString();
0666:                        NameAndTypeCpInfo ntEntry = (NameAndTypeCpInfo) getCpEntry(entry
0667:                                .getNameAndTypeIndex());
0668:                        String name = ((Utf8CpInfo) getCpEntry(ntEntry
0669:                                .getNameIndex())).getString();
0670:
0671:                        if (name.equals("class$")) {
0672:                            String descriptor = ((Utf8CpInfo) getCpEntry(ntEntry
0673:                                    .getDescriptorIndex())).getString();
0674:                            if (descriptor
0675:                                    .equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
0676:                                return true;
0677:                            }
0678:                        }
0679:                    }
0680:                }
0681:                return false;
0682:            }
0683:
0684:            private boolean containsClassMethodReference(String cName,
0685:                    String des) {
0686:                // Need only check CONSTANT_Methodref entries of constant pool since
0687:                // dangerous methods belong to classes 'Class' and 'ClassLoader', not to interfaces.
0688:                for (Enumeration enumeration = constantPool.elements(); enumeration
0689:                        .hasMoreElements();) {
0690:                    Object o = enumeration.nextElement();
0691:                    if (o instanceof  MethodrefCpInfo) {
0692:                        // Get the method class name, simple name and descriptor
0693:                        MethodrefCpInfo entry = (MethodrefCpInfo) o;
0694:                        ClassCpInfo classEntry = (ClassCpInfo) getCpEntry(entry
0695:                                .getClassIndex());
0696:                        String className = ((Utf8CpInfo) getCpEntry(classEntry
0697:                                .getNameIndex())).getString();
0698:                        NameAndTypeCpInfo ntEntry = (NameAndTypeCpInfo) getCpEntry(entry
0699:                                .getNameAndTypeIndex());
0700:                        String name = ((Utf8CpInfo) getCpEntry(ntEntry
0701:                                .getNameIndex())).getString();
0702:                        String descriptor = ((Utf8CpInfo) getCpEntry(ntEntry
0703:                                .getDescriptorIndex())).getString();
0704:
0705:                        // Check if this is on the proscribed list
0706:                        if (className.equals(cName)
0707:                                && (name + descriptor).equals(des)) {
0708:                            return true;
0709:                        }
0710:                    }
0711:                }
0712:                return false;
0713:            }
0714:
0715:            /** Remap the entities in the specified ClassFile. */
0716:            public void remap(NameMapper nm, boolean replaceClassNameStrings,
0717:                    PrintWriter log) {
0718:                // Remap all the package/interface/class/method/field names
0719:                //
0720:                String this ClassName = ((Utf8CpInfo) getCpEntry(((ClassCpInfo) getCpEntry(u2this Class))
0721:                        .getNameIndex())).getString();
0722:
0723:                // Remove unnecessary attributes from the class
0724:                final String[] attributesToKeep = nm
0725:                        .getAttrsToKeep(this ClassName);
0726:                if (attributesToKeep.length > 0) {
0727:                    trimAttrsExcept(attributesToKeep);
0728:                } else {
0729:                    trimAttrs();
0730:                }
0731:
0732:                // Remap the 'inner name' reference of the 'InnerClasses' attribute
0733:                for (int i = 0; i < u2attributesCount; i++) {
0734:                    AttrInfo attrInfo = attributes[i];
0735:                    if (attrInfo instanceof  RuntimeVisibleAnnotationsAttrInfo) {
0736:                        remapAnnotations(
0737:                                (RuntimeVisibleAnnotationsAttrInfo) attrInfo,
0738:                                nm);
0739:                    } else if (attrInfo instanceof  InnerClassesAttrInfo) {
0740:                        // For each inner class referemce,
0741:                        InnerClassesInfo[] info = ((InnerClassesAttrInfo) attrInfo)
0742:                                .getInfo();
0743:                        for (int j = 0; j < info.length; j++) {
0744:                            // Get the 'inner name' (it is a CONSTANT_Utf8)
0745:                            CpInfo cpInfo = getCpEntry(info[j]
0746:                                    .getInnerNameIndex());
0747:                            if (cpInfo instanceof  Utf8CpInfo) {
0748:                                // Get the remapped class name
0749:                                Utf8CpInfo utf = (Utf8CpInfo) cpInfo;
0750:                                String origClass = utf.getString();
0751:
0752:                                // Only remap non-anonymous classes (anon are "")
0753:                                if (!origClass.equals("")) {
0754:                                    // Get the full inner class name
0755:                                    ClassCpInfo innerClassInfo = (ClassCpInfo) getCpEntry(info[j]
0756:                                            .getInnerClassIndex());
0757:                                    String innerClassName = ((Utf8CpInfo) getCpEntry(innerClassInfo
0758:                                            .getNameIndex())).getString();
0759:
0760:                                    // It is the remapped simple name that must be stored, so truncate it
0761:                                    String remapClass = nm
0762:                                            .mapClass(innerClassName);
0763:                                    remapClass = remapClass
0764:                                            .substring(remapClass
0765:                                                    .lastIndexOf('$') + 1);
0766:                                    int remapIndex = constantPool.remapUtf8To(
0767:                                            remapClass, info[j]
0768:                                                    .getInnerNameIndex());
0769:                                    info[j].setInnerNameIndex(remapIndex);
0770:                                }
0771:                            }
0772:                        }
0773:                    } else if (attrInfo instanceof  EnclosingMethodAttrInfo) {
0774:                        EnclosingMethodAttrInfo eam = (EnclosingMethodAttrInfo) attrInfo;
0775:
0776:                        // get the class name of the enclosing file:
0777:                        CpInfo cpi = getCpEntry(eam.getClassIndex());
0778:                        if (cpi instanceof  ClassCpInfo) {
0779:                            ClassCpInfo ccpi = (ClassCpInfo) cpi;
0780:                            cpi = getCpEntry(ccpi.getNameIndex());
0781:                            if (cpi instanceof  Utf8CpInfo) {
0782:                                Utf8CpInfo utf = (Utf8CpInfo) cpi;
0783:                                String origClass = utf.getString();
0784:
0785:                                // do not remap the ClassCpInfo now, it will be remapped automatically, later!
0786:                                String remapClass = nm.mapClass(origClass);
0787:
0788:                                // if NT > 0 there is a valid NT to be remapped
0789:                                if (eam.getNameAndTypeIndex() > 0) {
0790:                                    cpi = getCpEntry(eam.getNameAndTypeIndex());
0791:                                    if (cpi instanceof  NameAndTypeCpInfo) {
0792:                                        NameAndTypeCpInfo nameTypeInfo = (NameAndTypeCpInfo) cpi;
0793:                                        Utf8CpInfo refUtf = (Utf8CpInfo) getCpEntry(nameTypeInfo
0794:                                                .getNameIndex());
0795:                                        Utf8CpInfo descUtf = (Utf8CpInfo) getCpEntry(nameTypeInfo
0796:                                                .getDescriptorIndex());
0797:                                        String origMethodName = refUtf
0798:                                                .getString();
0799:                                        String origDescriptor = descUtf
0800:                                                .getString();
0801:                                        String remapRef = nm.mapMethod(
0802:                                                origClass, origMethodName,
0803:                                                origDescriptor);
0804:                                        String remapDesc = nm
0805:                                                .mapDescriptor(descUtf
0806:                                                        .getString());
0807:                                        eam
0808:                                                .setNameAndTypeIndex(remapNT(
0809:                                                        refUtf,
0810:                                                        remapRef,
0811:                                                        descUtf,
0812:                                                        remapDesc,
0813:                                                        nameTypeInfo,
0814:                                                        eam
0815:                                                                .getNameAndTypeIndex()));
0816:                                    }
0817:                                }
0818:                            }
0819:                        }
0820:                    } else if (attrInfo instanceof  SignatureAttrInfo) {
0821:                        remapSignature(nm, (SignatureAttrInfo) attrInfo);
0822:                    } else if (attrInfo instanceof  SourceFileAttrInfo) {
0823:                        SourceFileAttrInfo source = (SourceFileAttrInfo) attrInfo;
0824:                        CpInfo cpInfo = getCpEntry(source.getSourceFileIndex());
0825:                        if (cpInfo instanceof  Utf8CpInfo) {
0826:                            Utf8CpInfo utf = (Utf8CpInfo) cpInfo;
0827:                            String origName = utf.getString();
0828:                            if (origName != null && origName.length() > 0) {
0829:                                String newName = nm.mapSourceFile(
0830:                                        this ClassName, origName);
0831:                                if (!origName.equals(newName)) {
0832:                                    if (newName == null || newName.length() < 1) {
0833:                                        AttrInfo[] newAttributes = new AttrInfo[attributes.length - 1];
0834:                                        System.arraycopy(attributes, 0,
0835:                                                newAttributes, 0, i);
0836:                                        if (newAttributes.length > i) {
0837:                                            System.arraycopy(attributes, i + 1,
0838:                                                    newAttributes, i,
0839:                                                    newAttributes.length - i);
0840:                                        }
0841:                                        attributes = newAttributes;
0842:                                        u2attributesCount--;
0843:                                        i--;
0844:                                        constantPool.decRefCount(source
0845:                                                .getAttrNameIndex());
0846:                                        utf.decRefCount();
0847:                                    } else {
0848:                                        int remapIndex = constantPool
0849:                                                .remapUtf8To(newName, source
0850:                                                        .getSourceFileIndex());
0851:                                        source.setSourceFileIndex(remapIndex);
0852:                                    }
0853:                                }
0854:                            }
0855:                        }
0856:                    }
0857:                }
0858:
0859:                // Remap the 'name' and 'descriptor' references of the 'LocalVariableTable'
0860:                // attribute, in the 'Code' attribute of method structures.
0861:                for (int i = 0; i < u2methodsCount; i++) {
0862:                    for (int j = 0; j < methods[i].u2attributesCount; j++) {
0863:                        final String methodName = methods[i].getName();
0864:                        final String descriptor = methods[i].getDescriptor();
0865:                        AttrInfo attrInfo = methods[i].attributes[j];
0866:
0867:                        if (attrInfo instanceof  AnnotationDefaultAttrInfo) {
0868:                            remapAnnotationDefault(
0869:                                    (AnnotationDefaultAttrInfo) attrInfo, nm);
0870:                        } else if (attrInfo instanceof  RuntimeVisibleAnnotationsAttrInfo) {
0871:                            remapAnnotations(
0872:                                    (RuntimeVisibleAnnotationsAttrInfo) attrInfo,
0873:                                    nm);
0874:                        } else if (attrInfo instanceof  RuntimeVisibleParameterAnnotationsAttrInfo) {
0875:                            remapAnnotations(
0876:                                    (RuntimeVisibleParameterAnnotationsAttrInfo) attrInfo,
0877:                                    nm);
0878:                        } else if (attrInfo instanceof  SignatureAttrInfo) {
0879:                            remapSignature(nm, (SignatureAttrInfo) attrInfo);
0880:                        } else if (attrInfo instanceof  CodeAttrInfo) {
0881:                            CodeAttrInfo codeAttrInfo = (CodeAttrInfo) attrInfo;
0882:                            for (int k = 0; k < codeAttrInfo.u2attributesCount; k++) {
0883:                                AttrInfo innerAttrInfo = codeAttrInfo.attributes[k];
0884:                                if (innerAttrInfo instanceof  LocalVariableTableAttrInfo) {
0885:                                    LocalVariableTableAttrInfo lvtAttrInfo = (LocalVariableTableAttrInfo) innerAttrInfo;
0886:                                    LocalVariableInfo[] lvts = lvtAttrInfo
0887:                                            .getLocalVariableTable();
0888:                                    for (int m = 0; m < lvts.length; m++) {
0889:                                        // Remap name
0890:                                        Utf8CpInfo nameUtf = (Utf8CpInfo) getCpEntry(lvts[m]
0891:                                                .getNameIndex());
0892:                                        String remapName = nm
0893:                                                .mapLocalVariable(
0894:                                                        this ClassName,
0895:                                                        methodName, descriptor,
0896:                                                        nameUtf.getString());
0897:                                        if (remapName == null
0898:                                                || remapName.length() < 1) {
0899:                                            constantPool.decRefCount(lvts[m]
0900:                                                    .getNameIndex());
0901:                                            constantPool.decRefCount(lvts[m]
0902:                                                    .getDescriptorIndex());
0903:                                            LocalVariableInfo[] newArray = new LocalVariableInfo[lvts.length - 1];
0904:                                            System.arraycopy(lvts, 0, newArray,
0905:                                                    0, m);
0906:                                            if (newArray.length > m) {
0907:                                                System.arraycopy(lvts, m + 1,
0908:                                                        newArray, m,
0909:                                                        newArray.length - m);
0910:                                            }
0911:                                            lvts = newArray;
0912:                                            lvtAttrInfo
0913:                                                    .setLocalVariableTable(lvts);
0914:                                            m--;
0915:                                        } else {
0916:                                            lvts[m]
0917:                                                    .setNameIndex(constantPool
0918:                                                            .remapUtf8To(
0919:                                                                    remapName,
0920:                                                                    lvts[m]
0921:                                                                            .getNameIndex()));
0922:
0923:                                            // Remap descriptor
0924:                                            Utf8CpInfo descUtf = (Utf8CpInfo) getCpEntry(lvts[m]
0925:                                                    .getDescriptorIndex());
0926:                                            String remapDesc = nm
0927:                                                    .mapDescriptor(descUtf
0928:                                                            .getString());
0929:                                            lvts[m]
0930:                                                    .setDescriptorIndex(constantPool
0931:                                                            .remapUtf8To(
0932:                                                                    remapDesc,
0933:                                                                    lvts[m]
0934:                                                                            .getDescriptorIndex()));
0935:                                        }
0936:                                    }
0937:                                } else if (innerAttrInfo instanceof  LocalVariableTypeTableAttrInfo) {
0938:                                    LocalVariableTypeTableAttrInfo lvttAttrInfo = (LocalVariableTypeTableAttrInfo) innerAttrInfo;
0939:                                    LocalVariableTypeInfo[] lvts = lvttAttrInfo
0940:                                            .getLocalVariableTypeTable();
0941:                                    for (int m = 0; m < lvts.length; m++) {
0942:                                        // Remap name
0943:                                        Utf8CpInfo nameUtf = (Utf8CpInfo) getCpEntry(lvts[m]
0944:                                                .getNameIndex());
0945:                                        String remapName = nm
0946:                                                .mapLocalVariable(
0947:                                                        this ClassName,
0948:                                                        methodName, descriptor,
0949:                                                        nameUtf.getString());
0950:                                        if (remapName == null
0951:                                                || remapName.length() < 1) {
0952:                                            constantPool.decRefCount(lvts[m]
0953:                                                    .getNameIndex());
0954:                                            constantPool.decRefCount(lvts[m]
0955:                                                    .getSignatureIndex());
0956:                                            LocalVariableTypeInfo[] newArray = new LocalVariableTypeInfo[lvts.length - 1];
0957:                                            System.arraycopy(lvts, 0, newArray,
0958:                                                    0, m);
0959:                                            if (newArray.length > m) {
0960:                                                System.arraycopy(lvts, m + 1,
0961:                                                        newArray, m,
0962:                                                        newArray.length - m);
0963:                                            }
0964:                                            lvts = newArray;
0965:                                            lvttAttrInfo
0966:                                                    .setLocalVariableTypeTable(lvts);
0967:                                            m--;
0968:                                        } else {
0969:                                            lvts[m]
0970:                                                    .setNameIndex(constantPool
0971:                                                            .remapUtf8To(
0972:                                                                    remapName,
0973:                                                                    lvts[m]
0974:                                                                            .getNameIndex()));
0975:
0976:                                            // Remap descriptor
0977:                                            Utf8CpInfo signatureUtf = (Utf8CpInfo) getCpEntry(lvts[m]
0978:                                                    .getSignatureIndex());
0979:                                            String remapSig = nm
0980:                                                    .mapSignature(signatureUtf
0981:                                                            .getString());
0982:                                            lvts[m]
0983:                                                    .setSignatureIndex(constantPool
0984:                                                            .remapUtf8To(
0985:                                                                    remapSig,
0986:                                                                    lvts[m]
0987:                                                                            .getSignatureIndex()));
0988:                                        }
0989:                                    }
0990:                                } else if (innerAttrInfo instanceof  LineNumberTableAttrInfo) {
0991:                                    LineNumberTableAttrInfo ltai = (LineNumberTableAttrInfo) innerAttrInfo;
0992:                                    if (!nm.mapLineNumberTable(this ClassName,
0993:                                            methodName, descriptor, ltai)) {
0994:                                        AttrInfo[] newAtt = new AttrInfo[codeAttrInfo.u2attributesCount - 1];
0995:                                        System.arraycopy(
0996:                                                codeAttrInfo.attributes, 0,
0997:                                                newAtt, 0, k);
0998:                                        if (newAtt.length > k) {
0999:                                            System.arraycopy(
1000:                                                    codeAttrInfo.attributes,
1001:                                                    k + 1, newAtt, k,
1002:                                                    newAtt.length - k);
1003:                                        }
1004:                                        codeAttrInfo.attributes = newAtt;
1005:                                        codeAttrInfo.u2attributesCount--;
1006:                                        k--;
1007:                                    }
1008:                                }
1009:                            }
1010:                        }
1011:                    }
1012:                }
1013:
1014:                // Go through all of class's fields and methods mapping 'name' and 'descriptor' references
1015:                for (int i = 0; i < u2fieldsCount; i++) {
1016:                    // Remap field 'name', unless it is 'Synthetic'
1017:                    FieldInfo field = fields[i];
1018:                    Utf8CpInfo nameUtf = (Utf8CpInfo) getCpEntry(field
1019:                            .getNameIndex());
1020:                    if (!field.isSynthetic()
1021:                            || nameUtf.getString().startsWith("class$")) {
1022:                        String remapName = nm.mapField(this ClassName, nameUtf
1023:                                .getString());
1024:                        field.setNameIndex(constantPool.remapUtf8To(remapName,
1025:                                field.getNameIndex()));
1026:                    }
1027:
1028:                    for (int j = 0; j < field.u2attributesCount; j++) {
1029:                        AttrInfo attrInfo = field.attributes[j];
1030:                        if (attrInfo instanceof  RuntimeVisibleAnnotationsAttrInfo) {
1031:                            remapAnnotations(
1032:                                    (RuntimeVisibleAnnotationsAttrInfo) attrInfo,
1033:                                    nm);
1034:                        } else if (attrInfo instanceof  SignatureAttrInfo) {
1035:                            remapSignature(nm, (SignatureAttrInfo) attrInfo);
1036:                        }
1037:                    }
1038:
1039:                    // Remap field 'descriptor'
1040:                    Utf8CpInfo descUtf = (Utf8CpInfo) getCpEntry(field
1041:                            .getDescriptorIndex());
1042:                    String remapDesc = nm.mapDescriptor(descUtf.getString());
1043:                    field.setDescriptorIndex(constantPool.remapUtf8To(
1044:                            remapDesc, field.getDescriptorIndex()));
1045:                }
1046:                for (int i = 0; i < u2methodsCount; i++) {
1047:                    // Remap method 'name', unless it is 'Synthetic'
1048:                    MethodInfo method = methods[i];
1049:                    Utf8CpInfo descUtf = (Utf8CpInfo) getCpEntry(method
1050:                            .getDescriptorIndex());
1051:                    if (!method.isSynthetic()) {
1052:                        Utf8CpInfo nameUtf = (Utf8CpInfo) getCpEntry(method
1053:                                .getNameIndex());
1054:                        String remapName = nm.mapMethod(this ClassName, nameUtf
1055:                                .getString(), descUtf.getString());
1056:                        method.setNameIndex(constantPool.remapUtf8To(remapName,
1057:                                method.getNameIndex()));
1058:                    }
1059:
1060:                    // Remap method 'descriptor'
1061:                    String remapDesc = nm.mapDescriptor(descUtf.getString());
1062:                    method.setDescriptorIndex(constantPool.remapUtf8To(
1063:                            remapDesc, method.getDescriptorIndex()));
1064:                }
1065:
1066:                // check whether .class constructs of Class.forName calls reside in the code..
1067:                if (replaceClassNameStrings && nm instanceof  ClassTree)
1068:                //          && 
1069:                //          (containsClassMethodReference("java/lang/Class","forName(Ljava/lang/String;)Ljava/lang/Class;")) ||
1070:                //          (containsClassMethodReference("java/lang/Class","forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;")) ||
1071:                //          (containsDotClassMethodReference()))
1072:                {
1073:                    this .replaceConstantPoolStrings((ClassTree) nm);
1074:                }
1075:
1076:                // Remap all field/method names and descriptors in the constant pool (depends on class names)
1077:                int currentCpLength = constantPool.length(); // constant pool can be extended (never contracted) during loop
1078:                for (int i = 0; i < currentCpLength; i++) {
1079:                    CpInfo cpInfo = getCpEntry(i);
1080:                    if (cpInfo != null) {
1081:                        // If this is a CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref
1082:                        // get the CONSTANT_NameAndType and remap the name and the components of the
1083:                        // descriptor string.
1084:                        if (cpInfo instanceof  RefCpInfo) {
1085:                            // Get the unmodified class name
1086:                            ClassCpInfo classInfo = (ClassCpInfo) getCpEntry(((RefCpInfo) cpInfo)
1087:                                    .getClassIndex());
1088:                            Utf8CpInfo classUtf = (Utf8CpInfo) getCpEntry(classInfo
1089:                                    .getNameIndex());
1090:                            String className = classUtf.getString();
1091:
1092:                            // Get the current N&T reference and its 'name' and 'descriptor' utf's
1093:                            int ntIndex = ((RefCpInfo) cpInfo)
1094:                                    .getNameAndTypeIndex();
1095:
1096:                            NameAndTypeCpInfo nameTypeInfo = (NameAndTypeCpInfo) getCpEntry(ntIndex);
1097:                            Utf8CpInfo refUtf = (Utf8CpInfo) getCpEntry(nameTypeInfo
1098:                                    .getNameIndex());
1099:                            Utf8CpInfo descUtf = (Utf8CpInfo) getCpEntry(nameTypeInfo
1100:                                    .getDescriptorIndex());
1101:
1102:                            // Get the remapped versions of 'name' and 'descriptor'
1103:                            String remapRef;
1104:                            if (cpInfo instanceof  FieldrefCpInfo) {
1105:                                remapRef = nm.mapField(className, refUtf
1106:                                        .getString());
1107:
1108:                                // check if this is a compiler generated field
1109:                                // supporting the JDK1.2-or-later '.class' construct
1110:                                if (refUtf.getString().startsWith("class$")) {
1111:                                    if (!replaceClassNameStrings) {
1112:                                        String internalClassName = refUtf
1113:                                                .getString().substring(6);
1114:                                        String realClassName = internalClassName
1115:                                                .replace('$', '.');
1116:                                        internalClassName = internalClassName
1117:                                                .replace('$', '/');
1118:                                        String map = nm
1119:                                                .mapClass(internalClassName);
1120:                                        if (map != null
1121:                                                && !internalClassName
1122:                                                        .equals(map)) {
1123:                                            String warning = realClassName
1124:                                                    + " shouldn't be obfuscated: it is most likely referenced as "
1125:                                                    + realClassName
1126:                                                    + ".class from "
1127:                                                    + Conversion
1128:                                                            .toJavaClass(this ClassName);
1129:                                            Logger.getInstance().warning(
1130:                                                    warning);
1131:                                            log.println("<!-- WARNING: "
1132:                                                    + warning + " -->");
1133:                                        }
1134:                                    }
1135:                                }
1136:                            } else {
1137:                                remapRef = nm.mapMethod(className, refUtf
1138:                                        .getString(), descUtf.getString());
1139:                            }
1140:                            String remapDesc = nm.mapDescriptor(descUtf
1141:                                    .getString());
1142:                            ((RefCpInfo) cpInfo).setNameAndTypeIndex(remapNT(
1143:                                    refUtf, remapRef, descUtf, remapDesc,
1144:                                    nameTypeInfo, ((RefCpInfo) cpInfo)
1145:                                            .getNameAndTypeIndex()));
1146:                        }
1147:                    }
1148:                }
1149:
1150:                // Finally, remap all class references to Utf
1151:                for (int i = 0; i < constantPool.length(); i++) {
1152:                    CpInfo cpInfo = getCpEntry(i);
1153:                    if (cpInfo != null) {
1154:                        // If this is CONSTANT_Class, remap the class-name Utf8 entry
1155:                        if (cpInfo instanceof  ClassCpInfo) {
1156:                            ClassCpInfo classInfo = (ClassCpInfo) cpInfo;
1157:                            Utf8CpInfo utf = (Utf8CpInfo) getCpEntry(classInfo
1158:                                    .getNameIndex());
1159:                            String remapClass = nm.mapClass(utf.getString());
1160:                            int remapIndex = constantPool.remapUtf8To(
1161:                                    remapClass, classInfo.getNameIndex());
1162:                            classInfo.setNameIndex(remapIndex);
1163:                        }
1164:                    }
1165:                }
1166:            }
1167:
1168:            private void remapAnnotationDefault(
1169:                    AnnotationDefaultAttrInfo annotationDefault, NameMapper nm) {
1170:                remapElementValue(annotationDefault.elementValue, nm);
1171:            }
1172:
1173:            private void remapAnnotations(
1174:                    RuntimeVisibleAnnotationsAttrInfo annotation, NameMapper nm) {
1175:                final AnnotationInfo[] annotations = annotation
1176:                        .getAnnotations();
1177:                if (annotations != null) {
1178:                    for (int i = 0; i < annotations.length; i++) {
1179:                        remapAnnotation(annotations[i], nm);
1180:                    }
1181:                }
1182:            }
1183:
1184:            private void remapAnnotations(
1185:                    RuntimeVisibleParameterAnnotationsAttrInfo annotation,
1186:                    NameMapper nm) {
1187:                final ParameterAnnotationInfo[] annotations = annotation
1188:                        .getParameterAnnotations();
1189:                if (annotations != null) {
1190:                    for (int i = 0; i < annotations.length; i++) {
1191:                        final ParameterAnnotationInfo info = annotations[i];
1192:                        final AnnotationInfo[] a = info.getAnnotations();
1193:                        if (a != null) {
1194:                            for (int j = 0; j < a.length; j++) {
1195:                                remapAnnotation(a[j], nm);
1196:                            }
1197:                        }
1198:                    }
1199:                }
1200:            }
1201:
1202:            private void remapAnnotation(AnnotationInfo annotation,
1203:                    NameMapper nm) {
1204:                CpInfo info = getCpEntry(annotation.u2typeIndex);
1205:                if (info instanceof  Utf8CpInfo) {
1206:                    Utf8CpInfo utf = (Utf8CpInfo) info;
1207:                    String s = utf.getString();
1208:                    if (s.length() > 2 && s.charAt(0) == 'L'
1209:                            && s.charAt(s.length() - 1) == ';') {
1210:                        String fqn = s.substring(1, s.length() - 1);
1211:                        String newFqn = nm.mapClass(fqn);
1212:                        if (!fqn.equals(newFqn)) {
1213:                            annotation.u2typeIndex = constantPool.remapUtf8To(
1214:                                    'L' + newFqn + ';', annotation.u2typeIndex);
1215:                        }
1216:                        final ElementValuePairInfo[] evp = annotation
1217:                                .getElementValuePairs();
1218:                        if (evp != null) {
1219:                            for (int i = 0; i < evp.length; i++) {
1220:                                final ElementValuePairInfo elementValuePair = evp[i];
1221:                                utf = (Utf8CpInfo) getCpEntry(elementValuePair.u2ElementNameIndex);
1222:                                String remapName = nm.mapAnnotationField(fqn,
1223:                                        utf.getString());
1224:                                if (!remapName.equals(utf.getString())) {
1225:                                    elementValuePair.u2ElementNameIndex = constantPool
1226:                                            .remapUtf8To(
1227:                                                    remapName,
1228:                                                    elementValuePair.u2ElementNameIndex);
1229:                                }
1230:                                final ElementValueInfo elementValue = elementValuePair.elementValue;
1231:                                remapElementValue(elementValue, nm);
1232:                            }
1233:                        }
1234:                    }
1235:                }
1236:            }
1237:
1238:            private void remapElementValue(ElementValueInfo elementValue,
1239:                    NameMapper nm) {
1240:                switch (elementValue.u1Tag) {
1241:                case 'B':
1242:                case 'C':
1243:                case 'D':
1244:                case 'F':
1245:                case 'I':
1246:                case 'J':
1247:                case 'S':
1248:                case 'Z':
1249:                case 's':
1250:                    // do nothing, this is a constant
1251:                    break;
1252:                case 'e':
1253:                    // remap the type...
1254:                {
1255:                    Utf8CpInfo utf = (Utf8CpInfo) getCpEntry(elementValue.u2typeNameIndex);
1256:                    String name = utf.getString();
1257:                    if (name.length() > 22 & name.charAt(0) == 'L'
1258:                            && name.charAt(name.length() - 1) == ';') {
1259:                        name = name.substring(1, name.length() - 1);
1260:                        String remapName = 'L' + nm.mapClass(name) + ';';
1261:                        elementValue.u2typeNameIndex = constantPool
1262:                                .remapUtf8To(remapName,
1263:                                        elementValue.u2typeNameIndex);
1264:                    }
1265:                }
1266:                    // leave the constant value in u2constNameIndex
1267:                    break;
1268:                case 'c': {
1269:                    Utf8CpInfo utf = (Utf8CpInfo) getCpEntry(elementValue.u2cpIndex);
1270:                    String name = utf.getString();
1271:                    if (name.length() > 22 & name.charAt(0) == 'L'
1272:                            && name.charAt(name.length() - 1) == ';') {
1273:                        name = name.substring(1, name.length() - 1);
1274:                        String remapName = 'L' + nm.mapClass(name) + ';';
1275:                        elementValue.u2cpIndex = constantPool.remapUtf8To(
1276:                                remapName, elementValue.u2cpIndex);
1277:                    }
1278:                }
1279:                    break;
1280:                case '@':
1281:                    remapAnnotation(elementValue.nestedAnnotation, nm);
1282:                    break;
1283:                case '[':
1284:                    for (int j = 0; j < elementValue.arrayValues.length; j++) {
1285:                        final ElementValueInfo evi = elementValue.arrayValues[j];
1286:                        remapElementValue(evi, nm);
1287:                    }
1288:                    break;
1289:                default:
1290:                    throw new RuntimeException(
1291:                            "Unknown type tag in annotation!");
1292:                }
1293:            }
1294:
1295:            private void remapSignature(NameMapper nm,
1296:                    SignatureAttrInfo signature) {
1297:                CpInfo cpInfo = getCpEntry(signature.getSignatureIndex());
1298:                if (cpInfo instanceof  Utf8CpInfo) {
1299:                    Utf8CpInfo utf = (Utf8CpInfo) cpInfo;
1300:                    String sig = utf.getString();
1301:                    String remapSignature = nm.mapSignature(sig);
1302:                    if (!sig.equals(remapSignature)) {
1303:                        int remapIndex = constantPool.remapUtf8To(
1304:                                remapSignature, signature.getSignatureIndex());
1305:                        signature.setSignatureIndex(remapIndex);
1306:                    }
1307:                }
1308:            }
1309:
1310:            private int remapNT(Utf8CpInfo refUtf, String remapRef,
1311:                    Utf8CpInfo descUtf, String remapDesc,
1312:                    NameAndTypeCpInfo nameTypeInfo, int nameAndTypeIndex) {
1313:                // If a remap is required, make a new N&T (increment ref count on 'name' and
1314:                // 'descriptor', decrement original N&T's ref count, set new N&T ref count to 1),
1315:                // remap new N&T's utf's
1316:                if (!remapRef.equals(refUtf.getString())
1317:                        || !remapDesc.equals(descUtf.getString())) {
1318:                    // Get the new N&T guy
1319:                    NameAndTypeCpInfo newNameTypeInfo;
1320:                    if (nameTypeInfo.getRefCount() == 1) {
1321:                        newNameTypeInfo = nameTypeInfo;
1322:                    } else {
1323:                        // Create the new N&T info
1324:                        newNameTypeInfo = (NameAndTypeCpInfo) nameTypeInfo
1325:                                .clone();
1326:
1327:                        // Adjust its reference counts of its utf's
1328:                        ((CpInfo) getCpEntry(newNameTypeInfo.getNameIndex()))
1329:                                .incRefCount();
1330:                        ((CpInfo) getCpEntry(newNameTypeInfo
1331:                                .getDescriptorIndex())).incRefCount();
1332:
1333:                        // Append it to the Constant Pool, and
1334:                        // point the RefCpInfo entry to the new N&T data
1335:                        nameAndTypeIndex = constantPool
1336:                                .addEntry(newNameTypeInfo);
1337:
1338:                        // Adjust reference counts from RefCpInfo
1339:                        newNameTypeInfo.incRefCount();
1340:                        nameTypeInfo.decRefCount();
1341:                    }
1342:
1343:                    // Remap the 'name' and 'descriptor' utf's in N&T
1344:                    newNameTypeInfo.setNameIndex(constantPool.remapUtf8To(
1345:                            remapRef, newNameTypeInfo.getNameIndex()));
1346:                    newNameTypeInfo.setDescriptorIndex(constantPool
1347:                            .remapUtf8To(remapDesc, newNameTypeInfo
1348:                                    .getDescriptorIndex()));
1349:                }
1350:                return nameAndTypeIndex;
1351:            }
1352:
1353:            /**
1354:             * goes through the constantpool, identifies classnamestrings and replaces
1355:             * them appropriately if necessary
1356:             */
1357:            private void replaceConstantPoolStrings(ClassTree ct) {
1358:                for (Enumeration enumeration = constantPool.elements(); enumeration
1359:                        .hasMoreElements();) {
1360:                    CpInfo cpi = (CpInfo) enumeration.nextElement();
1361:                    if (cpi instanceof  Utf8CpInfo) {
1362:                        Utf8CpInfo ui = (Utf8CpInfo) cpi;
1363:                        String s = ui.getString();
1364:                        boolean jikes = false;
1365:                        if (s.length() > 5 && s.startsWith("[L")
1366:                                && s.endsWith(";")) {
1367:                            s = s.substring(2, s.length() - 1);
1368:                            jikes = true;
1369:                        }
1370:                        if (s.length() > 2
1371:                                && Character.isJavaIdentifierPart(s.charAt(s
1372:                                        .length() - 1)) && s.indexOf(' ') < 0
1373:                                && s.indexOf('.') > 0) {
1374:                            Cl cl = ct.findClassForName(s);
1375:                            if (cl != null) {
1376:                                if (!cl.getFullInName().equals(
1377:                                        cl.getFullOutName())) {
1378:                                    if (jikes) {
1379:                                        ui.setString("[L"
1380:                                                + cl.getFullOutName().replace(
1381:                                                        '/', '.') + ";");
1382:                                    } else {
1383:                                        ui.setString(cl.getFullOutName()
1384:                                                .replace('/', '.'));
1385:                                    }
1386:                                }
1387:                            }
1388:                        }
1389:                    }
1390:                }
1391:            }
1392:
1393:            /** Export the representation to a DataOutput stream. */
1394:            public void write(DataOutput dout) throws java.io.IOException {
1395:                if (dout == null)
1396:                    throw new NullPointerException(
1397:                            "No output stream was provided.");
1398:                dout.writeInt(u4magic);
1399:                dout.writeShort(u2minorVersion);
1400:                dout.writeShort(u2majorVersion);
1401:                dout
1402:                        .writeShort(constantPool.length()
1403:                                + (writeIdString ? 1 : 0));
1404:                for (Enumeration enumeration = constantPool.elements(); enumeration
1405:                        .hasMoreElements();) {
1406:                    CpInfo cpInfo = (CpInfo) enumeration.nextElement();
1407:                    if (cpInfo != null) {
1408:                        cpInfo.write(dout);
1409:                    }
1410:                }
1411:                if (writeIdString) {
1412:                    cpIdString.write(dout);
1413:                }
1414:                dout.writeShort(u2accessFlags);
1415:                dout.writeShort(u2this Class);
1416:                dout.writeShort(u2super Class);
1417:                dout.writeShort(u2interfacesCount);
1418:                for (int i = 0; i < u2interfacesCount; i++) {
1419:                    dout.writeShort(u2interfaces[i]);
1420:                }
1421:                dout.writeShort(u2fieldsCount);
1422:                for (int i = 0; i < u2fieldsCount; i++) {
1423:                    fields[i].write(dout);
1424:                }
1425:                dout.writeShort(u2methodsCount);
1426:                for (int i = 0; i < u2methodsCount; i++) {
1427:                    methods[i].write(dout);
1428:                }
1429:                dout.writeShort(u2attributesCount);
1430:                for (int i = 0; i < u2attributesCount; i++) {
1431:                    attributes[i].write(dout);
1432:                }
1433:            }
1434:
1435:            /** Dump the content of the class file to the specified file (used for debugging). */
1436:            public void dump(PrintWriter pw) {
1437:                pw
1438:                        .println("_____________________________________________________________________");
1439:                pw.println("CLASS: " + getName());
1440:                pw.println("Magic: " + Integer.toHexString(u4magic));
1441:                pw.println("Minor version: "
1442:                        + Integer.toHexString(u2minorVersion));
1443:                pw.println("Major version: "
1444:                        + Integer.toHexString(u2majorVersion));
1445:                pw.println();
1446:                pw.println("CP length: "
1447:                        + Integer.toHexString(constantPool.length()));
1448:                for (int i = 0; i < constantPool.length(); i++) {
1449:                    CpInfo cpInfo = (CpInfo) constantPool.getCpEntry(i);
1450:                    if (cpInfo != null) {
1451:                        cpInfo.dump(pw, this , i);
1452:                    }
1453:                }
1454:                pw.println("Access: " + Integer.toHexString(u2accessFlags));
1455:                pw.println("This class: " + getName());
1456:                pw.println("Superclass: " + getSuper());
1457:                pw.println("Interfaces count: "
1458:                        + Integer.toHexString(u2interfacesCount));
1459:                for (int i = 0; i < u2interfacesCount; i++) {
1460:                    CpInfo info = getCpEntry(u2interfaces[i]);
1461:                    if (info == null) {
1462:                        pw.println("  Interface " + Integer.toHexString(i)
1463:                                + ": (null)");
1464:                    } else {
1465:                        pw.println("  Interface "
1466:                                + Integer.toHexString(i)
1467:                                + ": "
1468:                                + ((Utf8CpInfo) getCpEntry(((ClassCpInfo) info)
1469:                                        .getNameIndex())).getString());
1470:                    }
1471:                }
1472:                pw.println("Fields count: "
1473:                        + Integer.toHexString(u2fieldsCount));
1474:                for (int i = 0; i < u2fieldsCount; i++) {
1475:                    ClassItemInfo info = fields[i];
1476:                    if (info == null) {
1477:                        pw.println("  Field " + Integer.toHexString(i)
1478:                                + ": (null)");
1479:                    } else {
1480:                        pw
1481:                                .println("  Field "
1482:                                        + Integer.toHexString(i)
1483:                                        + ": "
1484:                                        + ((Utf8CpInfo) getCpEntry(info
1485:                                                .getNameIndex())).getString()
1486:                                        + " "
1487:                                        + ((Utf8CpInfo) getCpEntry(info
1488:                                                .getDescriptorIndex()))
1489:                                                .getString());
1490:                    }
1491:                    pw.println("    Attrs count: "
1492:                            + Integer.toHexString(info.u2attributesCount));
1493:                    for (int j = 0; j < info.u2attributesCount; j++) {
1494:                        pw.println(info.attributes[j]);
1495:                    }
1496:                }
1497:                pw.println("Methods count: "
1498:                        + Integer.toHexString(u2methodsCount));
1499:                for (int i = 0; i < u2methodsCount; i++) {
1500:                    ClassItemInfo info = methods[i];
1501:                    if (info == null) {
1502:                        pw.println("  Method " + Integer.toHexString(i)
1503:                                + ": (null)");
1504:                    } else {
1505:                        pw
1506:                                .println("  Method "
1507:                                        + Integer.toHexString(i)
1508:                                        + ": "
1509:                                        + ((Utf8CpInfo) getCpEntry(info
1510:                                                .getNameIndex())).getString()
1511:                                        + " "
1512:                                        + ((Utf8CpInfo) getCpEntry(info
1513:                                                .getDescriptorIndex()))
1514:                                                .getString()
1515:                                        + " "
1516:                                        + Integer.toHexString(info
1517:                                                .getAccessFlags()));
1518:                    }
1519:                    pw.println("    Attrs count: "
1520:                            + Integer.toHexString(info.u2attributesCount));
1521:                    for (int j = 0; j < info.u2attributesCount; j++) {
1522:                        if (info.attributes[j] instanceof  CodeAttrInfo) {
1523:                            pw.println(info.attributes[j]);
1524:                            CodeAttrInfo cai = (CodeAttrInfo) info.attributes[j];
1525:                            for (int k = 0; k < cai.u2attributesCount; k++) {
1526:                                pw.println(cai.attributes[k]);
1527:                            }
1528:                        } else {
1529:                            pw.println(info.attributes[j]);
1530:                        }
1531:                    }
1532:                }
1533:                pw.println("Attrs count: "
1534:                        + Integer.toHexString(u2attributesCount));
1535:                for (int i = 0; i < u2attributesCount; i++) {
1536:                    pw.println(attributes[i]);
1537:                }
1538:            }
1539:
1540:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.