Source Code Cross Referenced for ClassReader.java in  » Scripting » mvel » org » mvel » asm » 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 » Scripting » mvel » org.mvel.asm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /***
0002:         * ASM: a very small and fast Java bytecode manipulation framework
0003:         * Copyright (c) 2000-2005 INRIA, France Telecom
0004:         * All rights reserved.
0005:         *
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions
0008:         * are met:
0009:         * 1. Redistributions of source code must retain the above copyright
0010:         *    notice, this list of conditions and the following disclaimer.
0011:         * 2. Redistributions in binary form must reproduce the above copyright
0012:         *    notice, this list of conditions and the following disclaimer in the
0013:         *    documentation and/or other materials provided with the distribution.
0014:         * 3. Neither the name of the copyright holders nor the names of its
0015:         *    contributors may be used to endorse or promote products derived from
0016:         *    this software without specific prior written permission.
0017:         *
0018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021:         * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022:         * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023:         * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024:         * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0028:         * THE POSSIBILITY OF SUCH DAMAGE.
0029:         */package org.mvel.asm;
0030:
0031:        import java.io.IOException;
0032:        import java.io.InputStream;
0033:
0034:        /**
0035:         * A Java class parser to make a {@link ClassVisitor} visit an existing class.
0036:         * This class parses a byte array conforming to the Java class file format and
0037:         * calls the appropriate visit methods of a given class visitor for each field,
0038:         * method and bytecode instruction encountered.
0039:         *
0040:         * @author Eric Bruneton
0041:         * @author Eugene Kuleshov
0042:         */
0043:        public class ClassReader {
0044:
0045:            /**
0046:             * Flag to skip method code. If this class is set <code>CODE</code>
0047:             * attribute won't be visited. This can be used, for example, to retrieve
0048:             * annotations for methods and method parameters.
0049:             */
0050:            public final static int SKIP_CODE = 1;
0051:
0052:            /**
0053:             * Flag to skip the debug information in the class. If this flag is set the
0054:             * debug information of the class is not visited, i.e. the
0055:             * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
0056:             * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
0057:             * called.
0058:             */
0059:            public final static int SKIP_DEBUG = 2;
0060:
0061:            /**
0062:             * Flag to skip the stack map frames in the class. If this flag is set the
0063:             * stack map frames of the class is not visited, i.e. the
0064:             * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
0065:             * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
0066:             * used: it avoids visiting frames that will be ignored and recomputed from
0067:             * scratch in the class writer.
0068:             */
0069:            public final static int SKIP_FRAMES = 4;
0070:
0071:            /**
0072:             * Flag to expand the stack map frames. By default stack map frames are
0073:             * visited in their original format (i.e. "expanded" for classes whose
0074:             * version is less than V1_6, and "compressed" for the other classes). If
0075:             * this flag is set, stack map frames are always visited in expanded format
0076:             * (this option adds a decompression/recompression step in ClassReader and
0077:             * ClassWriter which degrades performances quite a lot).
0078:             */
0079:            public final static int EXPAND_FRAMES = 8;
0080:
0081:            /**
0082:             * The class to be parsed. <i>The content of this array must not be
0083:             * modified. This field is intended for {@link Attribute} sub classes, and
0084:             * is normally not needed by class generators or adapters.</i>
0085:             */
0086:            public final byte[] b;
0087:
0088:            /**
0089:             * The start index of each constant pool item in {@link #b b}, plus one.
0090:             * The one byte offset skips the constant pool item tag that indicates its
0091:             * type.
0092:             */
0093:            private final int[] items;
0094:
0095:            /**
0096:             * The String objects corresponding to the CONSTANT_Utf8 items. This cache
0097:             * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
0098:             * which GREATLY improves performances (by a factor 2 to 3). This caching
0099:             * strategy could be extended to all constant pool items, but its benefit
0100:             * would not be so great for these items (because they are much less
0101:             * expensive to parse than CONSTANT_Utf8 items).
0102:             */
0103:            private final String[] strings;
0104:
0105:            /**
0106:             * Maximum length of the strings contained in the constant pool of the
0107:             * class.
0108:             */
0109:            private final int maxStringLength;
0110:
0111:            /**
0112:             * Start index of the class header information (access, name...) in
0113:             * {@link #b b}.
0114:             */
0115:            public final int header;
0116:
0117:            // ------------------------------------------------------------------------
0118:            // Constructors
0119:            // ------------------------------------------------------------------------
0120:
0121:            /**
0122:             * Constructs a new {@link ClassReader} object.
0123:             *
0124:             * @param b the bytecode of the class to be read.
0125:             */
0126:            public ClassReader(final byte[] b) {
0127:                this (b, 0, b.length);
0128:            }
0129:
0130:            /**
0131:             * Constructs a new {@link ClassReader} object.
0132:             *
0133:             * @param b   the bytecode of the class to be read.
0134:             * @param off the start offset of the class data.
0135:             * @param len the length of the class data.
0136:             */
0137:            public ClassReader(final byte[] b, final int off, final int len) {
0138:                this .b = b;
0139:                // parses the constant pool
0140:                items = new int[readUnsignedShort(off + 8)];
0141:                int n = items.length;
0142:                strings = new String[n];
0143:                int max = 0;
0144:                int index = off + 10;
0145:                for (int i = 1; i < n; ++i) {
0146:                    items[i] = index + 1;
0147:                    int size;
0148:                    switch (b[index]) {
0149:                    case ClassWriter.FIELD:
0150:                    case ClassWriter.METH:
0151:                    case ClassWriter.IMETH:
0152:                    case ClassWriter.INT:
0153:                    case ClassWriter.FLOAT:
0154:                    case ClassWriter.NAME_TYPE:
0155:                        size = 5;
0156:                        break;
0157:                    case ClassWriter.LONG:
0158:                    case ClassWriter.DOUBLE:
0159:                        size = 9;
0160:                        ++i;
0161:                        break;
0162:                    case ClassWriter.UTF8:
0163:                        size = 3 + readUnsignedShort(index + 1);
0164:                        if (size > max) {
0165:                            max = size;
0166:                        }
0167:                        break;
0168:                    // case ClassWriter.CLASS:
0169:                    // case ClassWriter.STR:
0170:                    default:
0171:                        size = 3;
0172:                        break;
0173:                    }
0174:                    index += size;
0175:                }
0176:                maxStringLength = max;
0177:                // the class header information starts just after the constant pool
0178:                header = index;
0179:            }
0180:
0181:            /**
0182:             * Returns the class's access flags (see {@link Opcodes}). This value may
0183:             * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
0184:             * and those flags are represented by attributes.
0185:             *
0186:             * @return the class access flags
0187:             * @see ClassVisitor#visit(int,int,String,String,String,String[])
0188:             */
0189:            public int getAccess() {
0190:                return readUnsignedShort(header);
0191:            }
0192:
0193:            /**
0194:             * Returns the internal name of the class (see
0195:             * {@link Type#getInternalName() getInternalName}).
0196:             *
0197:             * @return the internal class name
0198:             * @see ClassVisitor#visit(int,int,String,String,String,String[])
0199:             */
0200:            public String getClassName() {
0201:                return readClass(header + 2, new char[maxStringLength]);
0202:            }
0203:
0204:            /**
0205:             * Returns the internal of name of the super class (see
0206:             * {@link Type#getInternalName() getInternalName}). For interfaces, the
0207:             * super class is {@link Object}.
0208:             *
0209:             * @return the internal name of super class, or <tt>null</tt> for
0210:             *         {@link Object} class.
0211:             * @see ClassVisitor#visit(int,int,String,String,String,String[])
0212:             */
0213:            public String getSuperName() {
0214:                int n = items[readUnsignedShort(header + 4)];
0215:                return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
0216:            }
0217:
0218:            /**
0219:             * Returns the internal names of the class's interfaces (see
0220:             * {@link Type#getInternalName() getInternalName}).
0221:             *
0222:             * @return the array of internal names for all implemented interfaces or
0223:             *         <tt>null</tt>.
0224:             * @see ClassVisitor#visit(int,int,String,String,String,String[])
0225:             */
0226:            public String[] getInterfaces() {
0227:                int index = header + 6;
0228:                int n = readUnsignedShort(index);
0229:                String[] interfaces = new String[n];
0230:                if (n > 0) {
0231:                    char[] buf = new char[maxStringLength];
0232:                    for (int i = 0; i < n; ++i) {
0233:                        index += 2;
0234:                        interfaces[i] = readClass(index, buf);
0235:                    }
0236:                }
0237:                return interfaces;
0238:            }
0239:
0240:            /**
0241:             * Copies the constant pool data into the given {@link ClassWriter}. Should
0242:             * be called before the {@link #accept(ClassVisitor,int)} method.
0243:             *
0244:             * @param classWriter the {@link ClassWriter} to copy constant pool into.
0245:             */
0246:            void copyPool(final ClassWriter classWriter) {
0247:                char[] buf = new char[maxStringLength];
0248:                int ll = items.length;
0249:                Item[] items2 = new Item[ll];
0250:                for (int i = 1; i < ll; i++) {
0251:                    int index = items[i];
0252:                    int tag = b[index - 1];
0253:                    Item item = new Item(i);
0254:                    int nameType;
0255:                    switch (tag) {
0256:                    case ClassWriter.FIELD:
0257:                    case ClassWriter.METH:
0258:                    case ClassWriter.IMETH:
0259:                        nameType = items[readUnsignedShort(index + 2)];
0260:                        item.set(tag, readClass(index, buf), readUTF8(nameType,
0261:                                buf), readUTF8(nameType + 2, buf));
0262:                        break;
0263:
0264:                    case ClassWriter.INT:
0265:                        item.set(readInt(index));
0266:                        break;
0267:
0268:                    case ClassWriter.FLOAT:
0269:                        item.set(Float.intBitsToFloat(readInt(index)));
0270:                        break;
0271:
0272:                    case ClassWriter.NAME_TYPE:
0273:                        item.set(tag, readUTF8(index, buf), readUTF8(index + 2,
0274:                                buf), null);
0275:                        break;
0276:
0277:                    case ClassWriter.LONG:
0278:                        item.set(readLong(index));
0279:                        ++i;
0280:                        break;
0281:
0282:                    case ClassWriter.DOUBLE:
0283:                        item.set(Double.longBitsToDouble(readLong(index)));
0284:                        ++i;
0285:                        break;
0286:
0287:                    case ClassWriter.UTF8: {
0288:                        String s = strings[i];
0289:                        if (s == null) {
0290:                            index = items[i];
0291:                            s = strings[i] = readUTF(index + 2,
0292:                                    readUnsignedShort(index), buf);
0293:                        }
0294:                        item.set(tag, s, null, null);
0295:                    }
0296:                        break;
0297:
0298:                    // case ClassWriter.STR:
0299:                    // case ClassWriter.CLASS:
0300:                    default:
0301:                        item.set(tag, readUTF8(index, buf), null, null);
0302:                        break;
0303:                    }
0304:
0305:                    int index2 = item.hashCode % items2.length;
0306:                    item.next = items2[index2];
0307:                    items2[index2] = item;
0308:                }
0309:
0310:                int off = items[1] - 1;
0311:                classWriter.pool.putByteArray(b, off, header - off);
0312:                classWriter.items = items2;
0313:                classWriter.threshold = (int) (0.75d * ll);
0314:                classWriter.index = ll;
0315:            }
0316:
0317:            /**
0318:             * Constructs a new {@link ClassReader} object.
0319:             *
0320:             * @param is an input stream from which to read the class.
0321:             * @throws IOException if a problem occurs during reading.
0322:             */
0323:            public ClassReader(final InputStream is) throws IOException {
0324:                this (readClass(is));
0325:            }
0326:
0327:            /**
0328:             * Constructs a new {@link ClassReader} object.
0329:             *
0330:             * @param name the fully qualified name of the class to be read.
0331:             * @throws IOException if an exception occurs during reading.
0332:             */
0333:            public ClassReader(final String name) throws IOException {
0334:                this (ClassLoader.getSystemResourceAsStream(name.replace('.',
0335:                        '/')
0336:                        + ".class"));
0337:            }
0338:
0339:            /**
0340:             * Reads the bytecode of a class.
0341:             *
0342:             * @param is an input stream from which to read the class.
0343:             * @return the bytecode read from the given input stream.
0344:             * @throws IOException if a problem occurs during reading.
0345:             */
0346:            private static byte[] readClass(final InputStream is)
0347:                    throws IOException {
0348:                if (is == null) {
0349:                    throw new IOException("Class not found");
0350:                }
0351:                byte[] b = new byte[is.available()];
0352:                int len = 0;
0353:                while (true) {
0354:                    int n = is.read(b, len, b.length - len);
0355:                    if (n == -1) {
0356:                        if (len < b.length) {
0357:                            byte[] c = new byte[len];
0358:                            System.arraycopy(b, 0, c, 0, len);
0359:                            b = c;
0360:                        }
0361:                        return b;
0362:                    }
0363:                    len += n;
0364:                    if (len == b.length) {
0365:                        byte[] c = new byte[b.length + 1000];
0366:                        System.arraycopy(b, 0, c, 0, len);
0367:                        b = c;
0368:                    }
0369:                }
0370:            }
0371:
0372:            // ------------------------------------------------------------------------
0373:            // Public methods
0374:            // ------------------------------------------------------------------------
0375:
0376:            /**
0377:             * Makes the given visitor visit the Java class of this {@link ClassReader}.
0378:             * This class is the one specified in the constructor (see
0379:             * {@link #ClassReader(byte[]) ClassReader}).
0380:             *
0381:             * @param classVisitor the visitor that must visit this class.
0382:             * @param flags        option flags that can be used to modify the default behavior
0383:             *                     of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}.
0384:             */
0385:            public void accept(final ClassVisitor classVisitor, final int flags) {
0386:                accept(classVisitor, new Attribute[0], flags);
0387:            }
0388:
0389:            /**
0390:             * Makes the given visitor visit the Java class of this {@link ClassReader}.
0391:             * This class is the one specified in the constructor (see
0392:             * {@link #ClassReader(byte[]) ClassReader}).
0393:             *
0394:             * @param classVisitor the visitor that must visit this class.
0395:             * @param attrs        prototypes of the attributes that must be parsed during the
0396:             *                     visit of the class. Any attribute whose type is not equal to the
0397:             *                     type of one the prototypes will not be parsed: its byte array
0398:             *                     value will be passed unchanged to the ClassWriter. <i>This may
0399:             *                     corrupt it if this value contains references to the constant pool,
0400:             *                     or has syntactic or semantic links with a class element that has
0401:             *                     been transformed by a class adapter between the reader and the
0402:             *                     writer</i>.
0403:             * @param flags        option flags that can be used to modify the default behavior
0404:             *                     of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}.
0405:             */
0406:            public void accept(final ClassVisitor classVisitor,
0407:                    final Attribute[] attrs, final int flags) {
0408:                byte[] b = this .b; // the bytecode array
0409:                char[] c = new char[maxStringLength]; // buffer used to read strings
0410:                int i, j, k; // loop variables
0411:                int u, v, w; // indexes in b
0412:                Attribute attr;
0413:
0414:                int access;
0415:                String name;
0416:                String desc;
0417:                String attrName;
0418:                String signature;
0419:                int anns = 0;
0420:                int ianns = 0;
0421:                Attribute cattrs = null;
0422:
0423:                // visits the header
0424:                u = header;
0425:                access = readUnsignedShort(u);
0426:                name = readClass(u + 2, c);
0427:                v = items[readUnsignedShort(u + 4)];
0428:                String super ClassName = v == 0 ? null : readUTF8(v, c);
0429:                String[] implementedItfs = new String[readUnsignedShort(u + 6)];
0430:                w = 0;
0431:                u += 8;
0432:                for (i = 0; i < implementedItfs.length; ++i) {
0433:                    implementedItfs[i] = readClass(u, c);
0434:                    u += 2;
0435:                }
0436:
0437:                boolean skipCode = (flags & SKIP_CODE) != 0;
0438:                boolean skipDebug = (flags & SKIP_DEBUG) != 0;
0439:                boolean unzip = (flags & EXPAND_FRAMES) != 0;
0440:
0441:                // skips fields and methods
0442:                v = u;
0443:                i = readUnsignedShort(v);
0444:                v += 2;
0445:                for (; i > 0; --i) {
0446:                    j = readUnsignedShort(v + 6);
0447:                    v += 8;
0448:                    for (; j > 0; --j) {
0449:                        v += 6 + readInt(v + 2);
0450:                    }
0451:                }
0452:                i = readUnsignedShort(v);
0453:                v += 2;
0454:                for (; i > 0; --i) {
0455:                    j = readUnsignedShort(v + 6);
0456:                    v += 8;
0457:                    for (; j > 0; --j) {
0458:                        v += 6 + readInt(v + 2);
0459:                    }
0460:                }
0461:                // reads the class's attributes
0462:                signature = null;
0463:                String sourceFile = null;
0464:                String sourceDebug = null;
0465:                String enclosingOwner = null;
0466:                String enclosingName = null;
0467:                String enclosingDesc = null;
0468:
0469:                i = readUnsignedShort(v);
0470:                v += 2;
0471:                for (; i > 0; --i) {
0472:                    attrName = readUTF8(v, c);
0473:                    // tests are sorted in decreasing frequency order
0474:                    // (based on frequencies observed on typical classes)
0475:                    if (attrName.equals("SourceFile")) {
0476:                        sourceFile = readUTF8(v + 6, c);
0477:                    } else if (attrName.equals("InnerClasses")) {
0478:                        w = v + 6;
0479:                    } else if (attrName.equals("EnclosingMethod")) {
0480:                        enclosingOwner = readClass(v + 6, c);
0481:                        int item = readUnsignedShort(v + 8);
0482:                        if (item != 0) {
0483:                            enclosingName = readUTF8(items[item], c);
0484:                            enclosingDesc = readUTF8(items[item] + 2, c);
0485:                        }
0486:                    } else if (attrName.equals("Signature")) {
0487:                        signature = readUTF8(v + 6, c);
0488:                    } else if (attrName.equals("RuntimeVisibleAnnotations")) {
0489:                        anns = v + 6;
0490:                    } else if (attrName.equals("Deprecated")) {
0491:                        access |= Opcodes.ACC_DEPRECATED;
0492:                    } else if (attrName.equals("Synthetic")) {
0493:                        access |= Opcodes.ACC_SYNTHETIC;
0494:                    } else if (attrName.equals("SourceDebugExtension")) {
0495:                        int len = readInt(v + 2);
0496:                        sourceDebug = readUTF(v + 6, len, new char[len]);
0497:                    } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
0498:                        ianns = v + 6;
0499:                    } else {
0500:                        attr = readAttribute(attrs, attrName, v + 6,
0501:                                readInt(v + 2), c, -1, null);
0502:                        if (attr != null) {
0503:                            attr.next = cattrs;
0504:                            cattrs = attr;
0505:                        }
0506:                    }
0507:                    v += 6 + readInt(v + 2);
0508:                }
0509:                // calls the visit method
0510:                classVisitor.visit(readInt(4), access, name, signature,
0511:                        super ClassName, implementedItfs);
0512:
0513:                // calls the visitSource method
0514:                if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
0515:                    classVisitor.visitSource(sourceFile, sourceDebug);
0516:                }
0517:
0518:                // calls the visitOuterClass method
0519:                if (enclosingOwner != null) {
0520:                    classVisitor.visitOuterClass(enclosingOwner, enclosingName,
0521:                            enclosingDesc);
0522:                }
0523:
0524:                // visits the class annotations
0525:                for (i = 1; i >= 0; --i) {
0526:                    v = i == 0 ? ianns : anns;
0527:                    if (v != 0) {
0528:                        j = readUnsignedShort(v);
0529:                        v += 2;
0530:                        for (; j > 0; --j) {
0531:                            v = readAnnotationValues(v + 2, c, true,
0532:                                    classVisitor.visitAnnotation(
0533:                                            readUTF8(v, c), i != 0));
0534:                        }
0535:                    }
0536:                }
0537:
0538:                // visits the class attributes
0539:                while (cattrs != null) {
0540:                    attr = cattrs.next;
0541:                    cattrs.next = null;
0542:                    classVisitor.visitAttribute(cattrs);
0543:                    cattrs = attr;
0544:                }
0545:
0546:                // calls the visitInnerClass method
0547:                if (w != 0) {
0548:                    i = readUnsignedShort(w);
0549:                    w += 2;
0550:                    for (; i > 0; --i) {
0551:                        classVisitor.visitInnerClass(
0552:                                readUnsignedShort(w) == 0 ? null : readClass(w,
0553:                                        c),
0554:                                readUnsignedShort(w + 2) == 0 ? null
0555:                                        : readClass(w + 2, c),
0556:                                readUnsignedShort(w + 4) == 0 ? null
0557:                                        : readUTF8(w + 4, c),
0558:                                readUnsignedShort(w + 6));
0559:                        w += 8;
0560:                    }
0561:                }
0562:
0563:                // visits the fields
0564:                i = readUnsignedShort(u);
0565:                u += 2;
0566:                for (; i > 0; --i) {
0567:                    access = readUnsignedShort(u);
0568:                    name = readUTF8(u + 2, c);
0569:                    desc = readUTF8(u + 4, c);
0570:                    // visits the field's attributes and looks for a ConstantValue
0571:                    // attribute
0572:                    int fieldValueItem = 0;
0573:                    signature = null;
0574:                    anns = 0;
0575:                    ianns = 0;
0576:                    cattrs = null;
0577:
0578:                    j = readUnsignedShort(u + 6);
0579:                    u += 8;
0580:                    for (; j > 0; --j) {
0581:                        attrName = readUTF8(u, c);
0582:                        // tests are sorted in decreasing frequency order
0583:                        // (based on frequencies observed on typical classes)
0584:                        if (attrName.equals("ConstantValue")) {
0585:                            fieldValueItem = readUnsignedShort(u + 6);
0586:                        } else if (attrName.equals("Signature")) {
0587:                            signature = readUTF8(u + 6, c);
0588:                        } else if (attrName.equals("Deprecated")) {
0589:                            access |= Opcodes.ACC_DEPRECATED;
0590:                        } else if (attrName.equals("Synthetic")) {
0591:                            access |= Opcodes.ACC_SYNTHETIC;
0592:                        } else if (attrName.equals("RuntimeVisibleAnnotations")) {
0593:                            anns = u + 6;
0594:                        } else if (attrName
0595:                                .equals("RuntimeInvisibleAnnotations")) {
0596:                            ianns = u + 6;
0597:                        } else {
0598:                            attr = readAttribute(attrs, attrName, u + 6,
0599:                                    readInt(u + 2), c, -1, null);
0600:                            if (attr != null) {
0601:                                attr.next = cattrs;
0602:                                cattrs = attr;
0603:                            }
0604:                        }
0605:                        u += 6 + readInt(u + 2);
0606:                    }
0607:                    // visits the field
0608:                    FieldVisitor fv = classVisitor.visitField(access, name,
0609:                            desc, signature, fieldValueItem == 0 ? null
0610:                                    : readConst(fieldValueItem, c));
0611:                    // visits the field annotations and attributes
0612:                    if (fv != null) {
0613:                        for (j = 1; j >= 0; --j) {
0614:                            v = j == 0 ? ianns : anns;
0615:                            if (v != 0) {
0616:                                k = readUnsignedShort(v);
0617:                                v += 2;
0618:                                for (; k > 0; --k) {
0619:                                    v = readAnnotationValues(v + 2, c, true, fv
0620:                                            .visitAnnotation(readUTF8(v, c),
0621:                                                    j != 0));
0622:                                }
0623:                            }
0624:                        }
0625:                        while (cattrs != null) {
0626:                            attr = cattrs.next;
0627:                            cattrs.next = null;
0628:                            fv.visitAttribute(cattrs);
0629:                            cattrs = attr;
0630:                        }
0631:                        fv.visitEnd();
0632:                    }
0633:                }
0634:
0635:                // visits the methods
0636:                i = readUnsignedShort(u);
0637:                u += 2;
0638:                for (; i > 0; --i) {
0639:                    int u0 = u + 6;
0640:                    access = readUnsignedShort(u);
0641:                    name = readUTF8(u + 2, c);
0642:                    desc = readUTF8(u + 4, c);
0643:                    signature = null;
0644:                    anns = 0;
0645:                    ianns = 0;
0646:                    int dann = 0;
0647:                    int mpanns = 0;
0648:                    int impanns = 0;
0649:                    cattrs = null;
0650:                    v = 0;
0651:                    w = 0;
0652:
0653:                    // looks for Code and Exceptions attributes
0654:                    j = readUnsignedShort(u + 6);
0655:                    u += 8;
0656:                    for (; j > 0; --j) {
0657:                        attrName = readUTF8(u, c);
0658:                        int attrSize = readInt(u + 2);
0659:                        u += 6;
0660:                        // tests are sorted in decreasing frequency order
0661:                        // (based on frequencies observed on typical classes)
0662:                        if (attrName.equals("Code")) {
0663:                            if (!skipCode) {
0664:                                v = u;
0665:                            }
0666:                        } else if (attrName.equals("Exceptions")) {
0667:                            w = u;
0668:                        } else if (attrName.equals("Signature")) {
0669:                            signature = readUTF8(u, c);
0670:                        } else if (attrName.equals("Deprecated")) {
0671:                            access |= Opcodes.ACC_DEPRECATED;
0672:                        } else if (attrName.equals("RuntimeVisibleAnnotations")) {
0673:                            anns = u;
0674:                        } else if (attrName.equals("AnnotationDefault")) {
0675:                            dann = u;
0676:                        } else if (attrName.equals("Synthetic")) {
0677:                            access |= Opcodes.ACC_SYNTHETIC;
0678:                        } else if (attrName
0679:                                .equals("RuntimeInvisibleAnnotations")) {
0680:                            ianns = u;
0681:                        } else if (attrName
0682:                                .equals("RuntimeVisibleParameterAnnotations")) {
0683:                            mpanns = u;
0684:                        } else if (attrName
0685:                                .equals("RuntimeInvisibleParameterAnnotations")) {
0686:                            impanns = u;
0687:                        } else {
0688:                            attr = readAttribute(attrs, attrName, u, attrSize,
0689:                                    c, -1, null);
0690:                            if (attr != null) {
0691:                                attr.next = cattrs;
0692:                                cattrs = attr;
0693:                            }
0694:                        }
0695:                        u += attrSize;
0696:                    }
0697:                    // reads declared exceptions
0698:                    String[] exceptions;
0699:                    if (w == 0) {
0700:                        exceptions = null;
0701:                    } else {
0702:                        exceptions = new String[readUnsignedShort(w)];
0703:                        w += 2;
0704:                        for (j = 0; j < exceptions.length; ++j) {
0705:                            exceptions[j] = readClass(w, c);
0706:                            w += 2;
0707:                        }
0708:                    }
0709:
0710:                    // visits the method's code, if any
0711:                    MethodVisitor mv = classVisitor.visitMethod(access, name,
0712:                            desc, signature, exceptions);
0713:
0714:                    if (mv != null) {
0715:                        /*
0716:                         * if the returned MethodVisitor is in fact a MethodWriter, it
0717:                         * means there is no method adapter between the reader and the
0718:                         * writer. If, in addition, the writer's constant pool was
0719:                         * copied from this reader (mw.cw.cr == this), and the signature
0720:                         * and exceptions of the method have not been changed, then it
0721:                         * is possible to skip all visit events and just copy the
0722:                         * original code of the method to the writer (the access, name
0723:                         * and descriptor can have been changed, this is not important
0724:                         * since they are not copied as is from the reader).
0725:                         */
0726:                        if (mv instanceof  MethodWriter) {
0727:                            MethodWriter mw = (MethodWriter) mv;
0728:                            if (mw.cw.cr == this ) {
0729:                                if (signature == mw.signature) {
0730:                                    boolean sameExceptions = false;
0731:                                    if (exceptions == null) {
0732:                                        sameExceptions = mw.exceptionCount == 0;
0733:                                    } else {
0734:                                        if (exceptions.length == mw.exceptionCount) {
0735:                                            sameExceptions = true;
0736:                                            for (j = exceptions.length - 1; j >= 0; --j) {
0737:                                                w -= 2;
0738:                                                if (mw.exceptions[j] != readUnsignedShort(w)) {
0739:                                                    sameExceptions = false;
0740:                                                    break;
0741:                                                }
0742:                                            }
0743:                                        }
0744:                                    }
0745:                                    if (sameExceptions) {
0746:                                        /*
0747:                                         * we do not copy directly the code into
0748:                                         * MethodWriter to save a byte array copy
0749:                                         * operation. The real copy will be done in
0750:                                         * ClassWriter.toByteArray().
0751:                                         */
0752:                                        mw.classReaderOffset = u0;
0753:                                        mw.classReaderLength = u - u0;
0754:                                        continue;
0755:                                    }
0756:                                }
0757:                            }
0758:                        }
0759:
0760:                        if (dann != 0) {
0761:                            AnnotationVisitor dv = mv.visitAnnotationDefault();
0762:                            readAnnotationValue(dann, c, null, dv);
0763:                            if (dv != null) {
0764:                                dv.visitEnd();
0765:                            }
0766:                        }
0767:                        for (j = 1; j >= 0; --j) {
0768:                            w = j == 0 ? ianns : anns;
0769:                            if (w != 0) {
0770:                                k = readUnsignedShort(w);
0771:                                w += 2;
0772:                                for (; k > 0; --k) {
0773:                                    w = readAnnotationValues(w + 2, c, true, mv
0774:                                            .visitAnnotation(readUTF8(w, c),
0775:                                                    j != 0));
0776:                                }
0777:                            }
0778:                        }
0779:                        if (mpanns != 0) {
0780:                            readParameterAnnotations(mpanns, c, true, mv);
0781:                        }
0782:                        if (impanns != 0) {
0783:                            readParameterAnnotations(impanns, c, false, mv);
0784:                        }
0785:                        while (cattrs != null) {
0786:                            attr = cattrs.next;
0787:                            cattrs.next = null;
0788:                            mv.visitAttribute(cattrs);
0789:                            cattrs = attr;
0790:                        }
0791:                    }
0792:
0793:                    if (mv != null && v != 0) {
0794:                        int maxStack = readUnsignedShort(v);
0795:                        int maxLocals = readUnsignedShort(v + 2);
0796:                        int codeLength = readInt(v + 4);
0797:                        v += 8;
0798:
0799:                        int codeStart = v;
0800:                        int codeEnd = v + codeLength;
0801:
0802:                        mv.visitCode();
0803:
0804:                        // 1st phase: finds the labels
0805:                        int label;
0806:                        Label[] labels = new Label[codeLength + 1];
0807:                        while (v < codeEnd) {
0808:                            int opcode = b[v] & 0xFF;
0809:                            switch (ClassWriter.TYPE[opcode]) {
0810:                            case ClassWriter.NOARG_INSN:
0811:                            case ClassWriter.IMPLVAR_INSN:
0812:                                v += 1;
0813:                                break;
0814:                            case ClassWriter.LABEL_INSN:
0815:                                label = v - codeStart + readShort(v + 1);
0816:                                if (labels[label] == null) {
0817:                                    labels[label] = new Label();
0818:                                }
0819:                                v += 3;
0820:                                break;
0821:                            case ClassWriter.LABELW_INSN:
0822:                                label = v - codeStart + readInt(v + 1);
0823:                                if (labels[label] == null) {
0824:                                    labels[label] = new Label();
0825:                                }
0826:                                v += 5;
0827:                                break;
0828:                            case ClassWriter.WIDE_INSN:
0829:                                opcode = b[v + 1] & 0xFF;
0830:                                if (opcode == Opcodes.IINC) {
0831:                                    v += 6;
0832:                                } else {
0833:                                    v += 4;
0834:                                }
0835:                                break;
0836:                            case ClassWriter.TABL_INSN:
0837:                                // skips 0 to 3 padding bytes
0838:                                w = v - codeStart;
0839:                                v = v + 4 - (w & 3);
0840:                                // reads instruction
0841:                                label = w + readInt(v);
0842:                                if (labels[label] == null) {
0843:                                    labels[label] = new Label();
0844:                                }
0845:                                j = readInt(v + 8) - readInt(v + 4) + 1;
0846:                                v += 12;
0847:                                for (; j > 0; --j) {
0848:                                    label = w + readInt(v);
0849:                                    v += 4;
0850:                                    if (labels[label] == null) {
0851:                                        labels[label] = new Label();
0852:                                    }
0853:                                }
0854:                                break;
0855:                            case ClassWriter.LOOK_INSN:
0856:                                // skips 0 to 3 padding bytes
0857:                                w = v - codeStart;
0858:                                v = v + 4 - (w & 3);
0859:                                // reads instruction
0860:                                label = w + readInt(v);
0861:                                if (labels[label] == null) {
0862:                                    labels[label] = new Label();
0863:                                }
0864:                                j = readInt(v + 4);
0865:                                v += 8;
0866:                                for (; j > 0; --j) {
0867:                                    label = w + readInt(v + 4);
0868:                                    v += 8;
0869:                                    if (labels[label] == null) {
0870:                                        labels[label] = new Label();
0871:                                    }
0872:                                }
0873:                                break;
0874:                            case ClassWriter.VAR_INSN:
0875:                            case ClassWriter.SBYTE_INSN:
0876:                            case ClassWriter.LDC_INSN:
0877:                                v += 2;
0878:                                break;
0879:                            case ClassWriter.SHORT_INSN:
0880:                            case ClassWriter.LDCW_INSN:
0881:                            case ClassWriter.FIELDORMETH_INSN:
0882:                            case ClassWriter.TYPE_INSN:
0883:                            case ClassWriter.IINC_INSN:
0884:                                v += 3;
0885:                                break;
0886:                            case ClassWriter.ITFMETH_INSN:
0887:                                v += 5;
0888:                                break;
0889:                            // case MANA_INSN:
0890:                            default:
0891:                                v += 4;
0892:                                break;
0893:                            }
0894:                        }
0895:                        // parses the try catch entries
0896:                        j = readUnsignedShort(v);
0897:                        v += 2;
0898:                        for (; j > 0; --j) {
0899:                            label = readUnsignedShort(v);
0900:                            Label start = labels[label];
0901:                            if (start == null) {
0902:                                labels[label] = start = new Label();
0903:                            }
0904:                            label = readUnsignedShort(v + 2);
0905:                            Label end = labels[label];
0906:                            if (end == null) {
0907:                                labels[label] = end = new Label();
0908:                            }
0909:                            label = readUnsignedShort(v + 4);
0910:                            Label handler = labels[label];
0911:                            if (handler == null) {
0912:                                labels[label] = handler = new Label();
0913:                            }
0914:                            int type = readUnsignedShort(v + 6);
0915:                            if (type == 0) {
0916:                                mv
0917:                                        .visitTryCatchBlock(start, end,
0918:                                                handler, null);
0919:                            } else {
0920:                                mv.visitTryCatchBlock(start, end, handler,
0921:                                        readUTF8(items[type], c));
0922:                            }
0923:                            v += 8;
0924:                        }
0925:                        // parses the local variable, line number tables, and code
0926:                        // attributes
0927:                        int varTable = 0;
0928:                        int varTypeTable = 0;
0929:                        int stackMap = 0;
0930:                        int frameCount = 0;
0931:                        int frameMode = 0;
0932:                        int frameOffset = 0;
0933:                        int frameLocalCount = 0;
0934:                        int frameLocalDiff = 0;
0935:                        int frameStackCount = 0;
0936:                        Object[] frameLocal = null;
0937:                        Object[] frameStack = null;
0938:                        boolean zip = true;
0939:                        cattrs = null;
0940:                        j = readUnsignedShort(v);
0941:                        v += 2;
0942:                        for (; j > 0; --j) {
0943:                            attrName = readUTF8(v, c);
0944:                            if (attrName.equals("LocalVariableTable")) {
0945:                                if (!skipDebug) {
0946:                                    varTable = v + 6;
0947:                                    k = readUnsignedShort(v + 6);
0948:                                    w = v + 8;
0949:                                    for (; k > 0; --k) {
0950:                                        label = readUnsignedShort(w);
0951:                                        if (labels[label] == null) {
0952:                                            labels[label] = new Label(true);
0953:                                        }
0954:                                        label += readUnsignedShort(w + 2);
0955:                                        if (labels[label] == null) {
0956:                                            labels[label] = new Label(true);
0957:                                        }
0958:                                        w += 10;
0959:                                    }
0960:                                }
0961:                            } else if (attrName
0962:                                    .equals("LocalVariableTypeTable")) {
0963:                                varTypeTable = v + 6;
0964:                            } else if (attrName.equals("LineNumberTable")) {
0965:                                if (!skipDebug) {
0966:                                    k = readUnsignedShort(v + 6);
0967:                                    w = v + 8;
0968:                                    for (; k > 0; --k) {
0969:                                        label = readUnsignedShort(w);
0970:                                        if (labels[label] == null) {
0971:                                            labels[label] = new Label(true);
0972:                                        }
0973:                                        labels[label].line = readUnsignedShort(w + 2);
0974:                                        w += 4;
0975:                                    }
0976:                                }
0977:                            } else if (attrName.equals("StackMapTable")) {
0978:                                if ((flags & SKIP_FRAMES) == 0) {
0979:                                    stackMap = v + 8;
0980:                                    frameCount = readUnsignedShort(v + 6);
0981:                                }
0982:                                /*
0983:                                 * here we do not extract the labels corresponding to
0984:                                 * the attribute content. This would require a full
0985:                                 * parsing of the attribute, which would need to be
0986:                                 * repeated in the second phase (see below). Instead the
0987:                                 * content of the attribute is read one frame at a time
0988:                                 * (i.e. after a frame has been visited, the next frame
0989:                                 * is read), and the labels it contains are also
0990:                                 * extracted one frame at a time. Thanks to the ordering
0991:                                 * of frames, having only a "one frame lookahead" is not
0992:                                 * a problem, i.e. it is not possible to see an offset
0993:                                 * smaller than the offset of the current insn and for
0994:                                 * which no Label exist.
0995:                                 */
0996:                                // TODO true for frame offsets,
0997:                                // but for UNINITIALIZED type offsets?
0998:                            } else if (attrName.equals("StackMap")) {
0999:                                if ((flags & SKIP_FRAMES) == 0) {
1000:                                    stackMap = v + 8;
1001:                                    frameCount = readUnsignedShort(v + 6);
1002:                                    zip = false;
1003:                                }
1004:                                /*
1005:                                 * IMPORTANT! here we assume that the frames are
1006:                                 * ordered, as in the StackMapTable attribute, although
1007:                                 * this is not guaranteed by the attribute format.
1008:                                 */
1009:                            } else {
1010:                                for (k = 0; k < attrs.length; ++k) {
1011:                                    if (attrs[k].type.equals(attrName)) {
1012:                                        attr = attrs[k].read(this , v + 6,
1013:                                                readInt(v + 2), c,
1014:                                                codeStart - 8, labels);
1015:                                        if (attr != null) {
1016:                                            attr.next = cattrs;
1017:                                            cattrs = attr;
1018:                                        }
1019:                                    }
1020:                                }
1021:                            }
1022:                            v += 6 + readInt(v + 2);
1023:                        }
1024:
1025:                        // 2nd phase: visits each instruction
1026:                        if (stackMap != 0) {
1027:                            // creates the very first (implicit) frame from the method
1028:                            // descriptor
1029:                            frameLocal = new Object[maxLocals];
1030:                            frameStack = new Object[maxStack];
1031:                            if (unzip) {
1032:                                int local = 0;
1033:                                if ((access & Opcodes.ACC_STATIC) == 0) {
1034:                                    if (name.equals("<init>")) {
1035:                                        frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
1036:                                    } else {
1037:                                        frameLocal[local++] = readClass(
1038:                                                header + 2, c);
1039:                                    }
1040:                                }
1041:                                j = 1;
1042:                                loop: while (true) {
1043:                                    k = j;
1044:                                    switch (desc.charAt(j++)) {
1045:                                    case 'Z':
1046:                                    case 'C':
1047:                                    case 'B':
1048:                                    case 'S':
1049:                                    case 'I':
1050:                                        frameLocal[local++] = Opcodes.INTEGER;
1051:                                        break;
1052:                                    case 'F':
1053:                                        frameLocal[local++] = Opcodes.FLOAT;
1054:                                        break;
1055:                                    case 'J':
1056:                                        frameLocal[local++] = Opcodes.LONG;
1057:                                        break;
1058:                                    case 'D':
1059:                                        frameLocal[local++] = Opcodes.DOUBLE;
1060:                                        break;
1061:                                    case '[':
1062:                                        while (desc.charAt(j) == '[') {
1063:                                            ++j;
1064:                                        }
1065:                                        if (desc.charAt(j) == 'L') {
1066:                                            ++j;
1067:                                            while (desc.charAt(j) != ';') {
1068:                                                ++j;
1069:                                            }
1070:                                        }
1071:                                        frameLocal[local++] = desc.substring(k,
1072:                                                ++j);
1073:                                        break;
1074:                                    case 'L':
1075:                                        while (desc.charAt(j) != ';') {
1076:                                            ++j;
1077:                                        }
1078:                                        frameLocal[local++] = desc.substring(
1079:                                                k + 1, j++);
1080:                                        break;
1081:                                    default:
1082:                                        break loop;
1083:                                    }
1084:                                }
1085:                                frameLocalCount = local;
1086:                            }
1087:                            /*
1088:                             * for the first explicit frame the offset is not
1089:                             * offset_delta + 1 but only offset_delta; setting the
1090:                             * implicit frame offset to -1 allow the use of the
1091:                             * "offset_delta + 1" rule in all cases
1092:                             */
1093:                            frameOffset = -1;
1094:                        }
1095:                        v = codeStart;
1096:                        Label l;
1097:                        while (v < codeEnd) {
1098:                            w = v - codeStart;
1099:
1100:                            l = labels[w];
1101:                            if (l != null) {
1102:                                mv.visitLabel(l);
1103:                                if (!skipDebug && l.line > 0) {
1104:                                    mv.visitLineNumber(l.line, l);
1105:                                }
1106:                            }
1107:
1108:                            while (frameLocal != null
1109:                                    && (frameOffset == w || frameOffset == -1)) {
1110:                                // if there is a frame for this offset,
1111:                                // makes the visitor visit it,
1112:                                // and reads the next frame if there is one.
1113:                                if (!zip || unzip) {
1114:                                    mv.visitFrame(Opcodes.F_NEW,
1115:                                            frameLocalCount, frameLocal,
1116:                                            frameStackCount, frameStack);
1117:                                } else if (frameOffset != -1) {
1118:                                    mv.visitFrame(frameMode, frameLocalDiff,
1119:                                            frameLocal, frameStackCount,
1120:                                            frameStack);
1121:                                }
1122:
1123:                                if (frameCount > 0) {
1124:                                    int tag, delta, n;
1125:                                    if (zip) {
1126:                                        tag = b[stackMap++] & 0xFF;
1127:                                    } else {
1128:                                        tag = MethodWriter.FULL_FRAME;
1129:                                        frameOffset = -1;
1130:                                    }
1131:                                    frameLocalDiff = 0;
1132:                                    if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) {
1133:                                        delta = tag;
1134:                                        frameMode = Opcodes.F_SAME;
1135:                                        frameStackCount = 0;
1136:                                    } else if (tag < MethodWriter.RESERVED) {
1137:                                        delta = tag
1138:                                                - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
1139:                                        stackMap = readFrameType(frameStack, 0,
1140:                                                stackMap, c, labels);
1141:                                        frameMode = Opcodes.F_SAME1;
1142:                                        frameStackCount = 1;
1143:                                    } else {
1144:                                        delta = readUnsignedShort(stackMap);
1145:                                        stackMap += 2;
1146:                                        if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
1147:                                            stackMap = readFrameType(
1148:                                                    frameStack, 0, stackMap, c,
1149:                                                    labels);
1150:                                            frameMode = Opcodes.F_SAME1;
1151:                                            frameStackCount = 1;
1152:                                        } else if (tag >= MethodWriter.CHOP_FRAME
1153:                                                && tag < MethodWriter.SAME_FRAME_EXTENDED) {
1154:                                            frameMode = Opcodes.F_CHOP;
1155:                                            frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
1156:                                                    - tag;
1157:                                            frameLocalCount -= frameLocalDiff;
1158:                                            frameStackCount = 0;
1159:                                        } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) {
1160:                                            frameMode = Opcodes.F_SAME;
1161:                                            frameStackCount = 0;
1162:                                        } else if (tag < MethodWriter.FULL_FRAME) {
1163:                                            j = unzip ? frameLocalCount : 0;
1164:                                            for (k = tag
1165:                                                    - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--) {
1166:                                                stackMap = readFrameType(
1167:                                                        frameLocal, j++,
1168:                                                        stackMap, c, labels);
1169:                                            }
1170:                                            frameMode = Opcodes.F_APPEND;
1171:                                            frameLocalDiff = tag
1172:                                                    - MethodWriter.SAME_FRAME_EXTENDED;
1173:                                            frameLocalCount += frameLocalDiff;
1174:                                            frameStackCount = 0;
1175:                                        } else { // if (tag == FULL_FRAME) {
1176:                                            frameMode = Opcodes.F_FULL;
1177:                                            n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
1178:                                            stackMap += 2;
1179:                                            for (j = 0; n > 0; n--) {
1180:                                                stackMap = readFrameType(
1181:                                                        frameLocal, j++,
1182:                                                        stackMap, c, labels);
1183:                                            }
1184:                                            n = frameStackCount = readUnsignedShort(stackMap);
1185:                                            stackMap += 2;
1186:                                            for (j = 0; n > 0; n--) {
1187:                                                stackMap = readFrameType(
1188:                                                        frameStack, j++,
1189:                                                        stackMap, c, labels);
1190:                                            }
1191:                                        }
1192:                                    }
1193:                                    frameOffset += delta + 1;
1194:                                    if (labels[frameOffset] == null) {
1195:                                        labels[frameOffset] = new Label();
1196:                                    }
1197:
1198:                                    --frameCount;
1199:                                } else {
1200:                                    frameLocal = null;
1201:                                }
1202:                            }
1203:
1204:                            int opcode = b[v] & 0xFF;
1205:                            switch (ClassWriter.TYPE[opcode]) {
1206:                            case ClassWriter.NOARG_INSN:
1207:                                mv.visitInsn(opcode);
1208:                                v += 1;
1209:                                break;
1210:                            case ClassWriter.IMPLVAR_INSN:
1211:                                if (opcode > Opcodes.ISTORE) {
1212:                                    opcode -= 59; // ISTORE_0
1213:                                    mv.visitVarInsn(Opcodes.ISTORE
1214:                                            + (opcode >> 2), opcode & 0x3);
1215:                                } else {
1216:                                    opcode -= 26; // ILOAD_0
1217:                                    mv.visitVarInsn(Opcodes.ILOAD
1218:                                            + (opcode >> 2), opcode & 0x3);
1219:                                }
1220:                                v += 1;
1221:                                break;
1222:                            case ClassWriter.LABEL_INSN:
1223:                                mv.visitJumpInsn(opcode, labels[w
1224:                                        + readShort(v + 1)]);
1225:                                v += 3;
1226:                                break;
1227:                            case ClassWriter.LABELW_INSN:
1228:                                mv.visitJumpInsn(opcode - 33, labels[w
1229:                                        + readInt(v + 1)]);
1230:                                v += 5;
1231:                                break;
1232:                            case ClassWriter.WIDE_INSN:
1233:                                opcode = b[v + 1] & 0xFF;
1234:                                if (opcode == Opcodes.IINC) {
1235:                                    mv.visitIincInsn(readUnsignedShort(v + 2),
1236:                                            readShort(v + 4));
1237:                                    v += 6;
1238:                                } else {
1239:                                    mv.visitVarInsn(opcode,
1240:                                            readUnsignedShort(v + 2));
1241:                                    v += 4;
1242:                                }
1243:                                break;
1244:                            case ClassWriter.TABL_INSN:
1245:                                // skips 0 to 3 padding bytes
1246:                                v = v + 4 - (w & 3);
1247:                                // reads instruction
1248:                                label = w + readInt(v);
1249:                                int min = readInt(v + 4);
1250:                                int max = readInt(v + 8);
1251:                                v += 12;
1252:                                Label[] table = new Label[max - min + 1];
1253:                                for (j = 0; j < table.length; ++j) {
1254:                                    table[j] = labels[w + readInt(v)];
1255:                                    v += 4;
1256:                                }
1257:                                mv.visitTableSwitchInsn(min, max,
1258:                                        labels[label], table);
1259:                                break;
1260:                            case ClassWriter.LOOK_INSN:
1261:                                // skips 0 to 3 padding bytes
1262:                                v = v + 4 - (w & 3);
1263:                                // reads instruction
1264:                                label = w + readInt(v);
1265:                                j = readInt(v + 4);
1266:                                v += 8;
1267:                                int[] keys = new int[j];
1268:                                Label[] values = new Label[j];
1269:                                for (j = 0; j < keys.length; ++j) {
1270:                                    keys[j] = readInt(v);
1271:                                    values[j] = labels[w + readInt(v + 4)];
1272:                                    v += 8;
1273:                                }
1274:                                mv.visitLookupSwitchInsn(labels[label], keys,
1275:                                        values);
1276:                                break;
1277:                            case ClassWriter.VAR_INSN:
1278:                                mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
1279:                                v += 2;
1280:                                break;
1281:                            case ClassWriter.SBYTE_INSN:
1282:                                mv.visitIntInsn(opcode, b[v + 1]);
1283:                                v += 2;
1284:                                break;
1285:                            case ClassWriter.SHORT_INSN:
1286:                                mv.visitIntInsn(opcode, readShort(v + 1));
1287:                                v += 3;
1288:                                break;
1289:                            case ClassWriter.LDC_INSN:
1290:                                mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
1291:                                v += 2;
1292:                                break;
1293:                            case ClassWriter.LDCW_INSN:
1294:                                mv.visitLdcInsn(readConst(
1295:                                        readUnsignedShort(v + 1), c));
1296:                                v += 3;
1297:                                break;
1298:                            case ClassWriter.FIELDORMETH_INSN:
1299:                            case ClassWriter.ITFMETH_INSN:
1300:                                int cpIndex = items[readUnsignedShort(v + 1)];
1301:                                String iowner = readClass(cpIndex, c);
1302:                                cpIndex = items[readUnsignedShort(cpIndex + 2)];
1303:                                String iname = readUTF8(cpIndex, c);
1304:                                String idesc = readUTF8(cpIndex + 2, c);
1305:                                if (opcode < Opcodes.INVOKEVIRTUAL) {
1306:                                    mv.visitFieldInsn(opcode, iowner, iname,
1307:                                            idesc);
1308:                                } else {
1309:                                    mv.visitMethodInsn(opcode, iowner, iname,
1310:                                            idesc);
1311:                                }
1312:                                if (opcode == Opcodes.INVOKEINTERFACE) {
1313:                                    v += 5;
1314:                                } else {
1315:                                    v += 3;
1316:                                }
1317:                                break;
1318:                            case ClassWriter.TYPE_INSN:
1319:                                mv.visitTypeInsn(opcode, readClass(v + 1, c));
1320:                                v += 3;
1321:                                break;
1322:                            case ClassWriter.IINC_INSN:
1323:                                mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
1324:                                v += 3;
1325:                                break;
1326:                            // case MANA_INSN:
1327:                            default:
1328:                                mv.visitMultiANewArrayInsn(readClass(v + 1, c),
1329:                                        b[v + 3] & 0xFF);
1330:                                v += 4;
1331:                                break;
1332:                            }
1333:                        }
1334:                        l = labels[codeEnd - codeStart];
1335:                        if (l != null) {
1336:                            mv.visitLabel(l);
1337:                        }
1338:                        // visits the local variable tables
1339:                        if (!skipDebug && varTable != 0) {
1340:                            int[] typeTable = null;
1341:                            if (varTypeTable != 0) {
1342:                                k = readUnsignedShort(varTypeTable) * 3;
1343:                                w = varTypeTable + 2;
1344:                                typeTable = new int[k];
1345:                                while (k > 0) {
1346:                                    typeTable[--k] = w + 6; // signature
1347:                                    typeTable[--k] = readUnsignedShort(w + 8); // index
1348:                                    typeTable[--k] = readUnsignedShort(w); // start
1349:                                    w += 10;
1350:                                }
1351:                            }
1352:                            k = readUnsignedShort(varTable);
1353:                            w = varTable + 2;
1354:                            for (; k > 0; --k) {
1355:                                int start = readUnsignedShort(w);
1356:                                int length = readUnsignedShort(w + 2);
1357:                                int index = readUnsignedShort(w + 8);
1358:                                String vsignature = null;
1359:                                if (typeTable != null) {
1360:                                    for (int a = 0; a < typeTable.length; a += 3) {
1361:                                        if (typeTable[a] == start
1362:                                                && typeTable[a + 1] == index) {
1363:                                            vsignature = readUTF8(
1364:                                                    typeTable[a + 2], c);
1365:                                            break;
1366:                                        }
1367:                                    }
1368:                                }
1369:                                mv.visitLocalVariable(readUTF8(w + 4, c),
1370:                                        readUTF8(w + 6, c), vsignature,
1371:                                        labels[start], labels[start + length],
1372:                                        index);
1373:                                w += 10;
1374:                            }
1375:                        }
1376:                        // visits the other attributes
1377:                        while (cattrs != null) {
1378:                            attr = cattrs.next;
1379:                            cattrs.next = null;
1380:                            mv.visitAttribute(cattrs);
1381:                            cattrs = attr;
1382:                        }
1383:                        // visits the max stack and max locals values
1384:                        mv.visitMaxs(maxStack, maxLocals);
1385:                    }
1386:
1387:                    if (mv != null) {
1388:                        mv.visitEnd();
1389:                    }
1390:                }
1391:
1392:                // visits the end of the class
1393:                classVisitor.visitEnd();
1394:            }
1395:
1396:            /**
1397:             * Reads parameter annotations and makes the given visitor visit them.
1398:             *
1399:             * @param v       start offset in {@link #b b} of the annotations to be read.
1400:             * @param buf     buffer to be used to call {@link #readUTF8 readUTF8},
1401:             *                {@link #readClass(int,char[]) readClass} or
1402:             *                {@link #readConst readConst}.
1403:             * @param visible <tt>true</tt> if the annotations to be read are visible
1404:             *                at runtime.
1405:             * @param mv      the visitor that must visit the annotations.
1406:             */
1407:            private void readParameterAnnotations(int v, final char[] buf,
1408:                    final boolean visible, final MethodVisitor mv) {
1409:                int n = b[v++] & 0xFF;
1410:                for (int i = 0; i < n; ++i) {
1411:                    int j = readUnsignedShort(v);
1412:                    v += 2;
1413:                    for (; j > 0; --j) {
1414:                        v = readAnnotationValues(v + 2, buf, true, mv
1415:                                .visitParameterAnnotation(i, readUTF8(v, buf),
1416:                                        visible));
1417:                    }
1418:                }
1419:            }
1420:
1421:            /**
1422:             * Reads the values of an annotation and makes the given visitor visit them.
1423:             *
1424:             * @param v     the start offset in {@link #b b} of the values to be read
1425:             *              (including the unsigned short that gives the number of values).
1426:             * @param buf   buffer to be used to call {@link #readUTF8 readUTF8},
1427:             *              {@link #readClass(int,char[]) readClass} or
1428:             *              {@link #readConst readConst}.
1429:             * @param named if the annotation values are named or not.
1430:             * @param av    the visitor that must visit the values.
1431:             * @return the end offset of the annotation values.
1432:             */
1433:            private int readAnnotationValues(int v, final char[] buf,
1434:                    final boolean named, final AnnotationVisitor av) {
1435:                int i = readUnsignedShort(v);
1436:                v += 2;
1437:                if (named) {
1438:                    for (; i > 0; --i) {
1439:                        v = readAnnotationValue(v + 2, buf, readUTF8(v, buf),
1440:                                av);
1441:                    }
1442:                } else {
1443:                    for (; i > 0; --i) {
1444:                        v = readAnnotationValue(v, buf, null, av);
1445:                    }
1446:                }
1447:                if (av != null) {
1448:                    av.visitEnd();
1449:                }
1450:                return v;
1451:            }
1452:
1453:            /**
1454:             * Reads a value of an annotation and makes the given visitor visit it.
1455:             *
1456:             * @param v    the start offset in {@link #b b} of the value to be read (<i>not
1457:             *             including the value name constant pool index</i>).
1458:             * @param buf  buffer to be used to call {@link #readUTF8 readUTF8},
1459:             *             {@link #readClass(int,char[]) readClass} or
1460:             *             {@link #readConst readConst}.
1461:             * @param name the name of the value to be read.
1462:             * @param av   the visitor that must visit the value.
1463:             * @return the end offset of the annotation value.
1464:             */
1465:            private int readAnnotationValue(int v, final char[] buf,
1466:                    final String name, final AnnotationVisitor av) {
1467:                int i;
1468:                if (av == null) {
1469:                    switch (b[v] & 0xFF) {
1470:                    case 'e': // enum_const_value
1471:                        return v + 5;
1472:                    case '@': // annotation_value
1473:                        return readAnnotationValues(v + 3, buf, true, null);
1474:                    case '[': // array_value
1475:                        return readAnnotationValues(v + 1, buf, false, null);
1476:                    default:
1477:                        return v + 3;
1478:                    }
1479:                }
1480:                switch (b[v++] & 0xFF) {
1481:                case 'I': // pointer to CONSTANT_Integer
1482:                case 'J': // pointer to CONSTANT_Long
1483:                case 'F': // pointer to CONSTANT_Float
1484:                case 'D': // pointer to CONSTANT_Double
1485:                    av.visit(name, readConst(readUnsignedShort(v), buf));
1486:                    v += 2;
1487:                    break;
1488:                case 'B': // pointer to CONSTANT_Byte
1489:                    av.visit(name, new Byte(
1490:                            (byte) readInt(items[readUnsignedShort(v)])));
1491:                    v += 2;
1492:                    break;
1493:                case 'Z': // pointer to CONSTANT_Boolean
1494:                    av
1495:                            .visit(
1496:                                    name,
1497:                                    readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE
1498:                                            : Boolean.TRUE);
1499:                    v += 2;
1500:                    break;
1501:                case 'S': // pointer to CONSTANT_Short
1502:                    av.visit(name, new Short(
1503:                            (short) readInt(items[readUnsignedShort(v)])));
1504:                    v += 2;
1505:                    break;
1506:                case 'C': // pointer to CONSTANT_Char
1507:                    av.visit(name, new Character(
1508:                            (char) readInt(items[readUnsignedShort(v)])));
1509:                    v += 2;
1510:                    break;
1511:                case 's': // pointer to CONSTANT_Utf8
1512:                    av.visit(name, readUTF8(v, buf));
1513:                    v += 2;
1514:                    break;
1515:                case 'e': // enum_const_value
1516:                    av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
1517:                    v += 4;
1518:                    break;
1519:                case 'c': // class_info
1520:                    av.visit(name, Type.getType(readUTF8(v, buf)));
1521:                    v += 2;
1522:                    break;
1523:                case '@': // annotation_value
1524:                    v = readAnnotationValues(v + 2, buf, true, av
1525:                            .visitAnnotation(name, readUTF8(v, buf)));
1526:                    break;
1527:                case '[': // array_value
1528:                    int size = readUnsignedShort(v);
1529:                    v += 2;
1530:                    if (size == 0) {
1531:                        return readAnnotationValues(v - 2, buf, false, av
1532:                                .visitArray(name));
1533:                    }
1534:                    switch (this .b[v++] & 0xFF) {
1535:                    case 'B':
1536:                        byte[] bv = new byte[size];
1537:                        for (i = 0; i < size; i++) {
1538:                            bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
1539:                            v += 3;
1540:                        }
1541:                        av.visit(name, bv);
1542:                        --v;
1543:                        break;
1544:                    case 'Z':
1545:                        boolean[] zv = new boolean[size];
1546:                        for (i = 0; i < size; i++) {
1547:                            zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
1548:                            v += 3;
1549:                        }
1550:                        av.visit(name, zv);
1551:                        --v;
1552:                        break;
1553:                    case 'S':
1554:                        short[] sv = new short[size];
1555:                        for (i = 0; i < size; i++) {
1556:                            sv[i] = (short) readInt(items[readUnsignedShort(v)]);
1557:                            v += 3;
1558:                        }
1559:                        av.visit(name, sv);
1560:                        --v;
1561:                        break;
1562:                    case 'C':
1563:                        char[] cv = new char[size];
1564:                        for (i = 0; i < size; i++) {
1565:                            cv[i] = (char) readInt(items[readUnsignedShort(v)]);
1566:                            v += 3;
1567:                        }
1568:                        av.visit(name, cv);
1569:                        --v;
1570:                        break;
1571:                    case 'I':
1572:                        int[] iv = new int[size];
1573:                        for (i = 0; i < size; i++) {
1574:                            iv[i] = readInt(items[readUnsignedShort(v)]);
1575:                            v += 3;
1576:                        }
1577:                        av.visit(name, iv);
1578:                        --v;
1579:                        break;
1580:                    case 'J':
1581:                        long[] lv = new long[size];
1582:                        for (i = 0; i < size; i++) {
1583:                            lv[i] = readLong(items[readUnsignedShort(v)]);
1584:                            v += 3;
1585:                        }
1586:                        av.visit(name, lv);
1587:                        --v;
1588:                        break;
1589:                    case 'F':
1590:                        float[] fv = new float[size];
1591:                        for (i = 0; i < size; i++) {
1592:                            fv[i] = Float
1593:                                    .intBitsToFloat(readInt(items[readUnsignedShort(v)]));
1594:                            v += 3;
1595:                        }
1596:                        av.visit(name, fv);
1597:                        --v;
1598:                        break;
1599:                    case 'D':
1600:                        double[] dv = new double[size];
1601:                        for (i = 0; i < size; i++) {
1602:                            dv[i] = Double
1603:                                    .longBitsToDouble(readLong(items[readUnsignedShort(v)]));
1604:                            v += 3;
1605:                        }
1606:                        av.visit(name, dv);
1607:                        --v;
1608:                        break;
1609:                    default:
1610:                        v = readAnnotationValues(v - 3, buf, false, av
1611:                                .visitArray(name));
1612:                    }
1613:                }
1614:                return v;
1615:            }
1616:
1617:            private int readFrameType(final Object[] frame, final int index,
1618:                    int v, final char[] buf, final Label[] labels) {
1619:                int type = b[v++] & 0xFF;
1620:                switch (type) {
1621:                case 0:
1622:                    frame[index] = Opcodes.TOP;
1623:                    break;
1624:                case 1:
1625:                    frame[index] = Opcodes.INTEGER;
1626:                    break;
1627:                case 2:
1628:                    frame[index] = Opcodes.FLOAT;
1629:                    break;
1630:                case 3:
1631:                    frame[index] = Opcodes.DOUBLE;
1632:                    break;
1633:                case 4:
1634:                    frame[index] = Opcodes.LONG;
1635:                    break;
1636:                case 5:
1637:                    frame[index] = Opcodes.NULL;
1638:                    break;
1639:                case 6:
1640:                    frame[index] = Opcodes.UNINITIALIZED_THIS;
1641:                    break;
1642:                case 7: // Object
1643:                    frame[index] = readClass(v, buf);
1644:                    v += 2;
1645:                    break;
1646:                default: // Uninitialized
1647:                    int offset = readUnsignedShort(v);
1648:                    if (labels[offset] == null) {
1649:                        labels[offset] = new Label();
1650:                    }
1651:                    frame[index] = labels[offset];
1652:                    v += 2;
1653:                }
1654:                return v;
1655:            }
1656:
1657:            /**
1658:             * Reads an attribute in {@link #b b}.
1659:             *
1660:             * @param attrs   prototypes of the attributes that must be parsed during the
1661:             *                visit of the class. Any attribute whose type is not equal to the
1662:             *                type of one the prototypes is ignored (i.e. an empty
1663:             *                {@link Attribute} instance is returned).
1664:             * @param type    the type of the attribute.
1665:             * @param off     index of the first byte of the attribute's content in
1666:             *                {@link #b b}. The 6 attribute header bytes, containing the type
1667:             *                and the length of the attribute, are not taken into account here
1668:             *                (they have already been read).
1669:             * @param len     the length of the attribute's content.
1670:             * @param buf     buffer to be used to call {@link #readUTF8 readUTF8},
1671:             *                {@link #readClass(int,char[]) readClass} or
1672:             *                {@link #readConst readConst}.
1673:             * @param codeOff index of the first byte of code's attribute content in
1674:             *                {@link #b b}, or -1 if the attribute to be read is not a code
1675:             *                attribute. The 6 attribute header bytes, containing the type and
1676:             *                the length of the attribute, are not taken into account here.
1677:             * @param labels  the labels of the method's code, or <tt>null</tt> if the
1678:             *                attribute to be read is not a code attribute.
1679:             * @return the attribute that has been read, or <tt>null</tt> to skip this
1680:             *         attribute.
1681:             */
1682:            private Attribute readAttribute(final Attribute[] attrs,
1683:                    final String type, final int off, final int len,
1684:                    final char[] buf, final int codeOff, final Label[] labels) {
1685:                for (int i = 0; i < attrs.length; ++i) {
1686:                    if (attrs[i].type.equals(type)) {
1687:                        return attrs[i].read(this , off, len, buf, codeOff,
1688:                                labels);
1689:                    }
1690:                }
1691:                return new Attribute(type).read(this , off, len, null, -1, null);
1692:            }
1693:
1694:            // ------------------------------------------------------------------------
1695:            // Utility methods: low level parsing
1696:            // ------------------------------------------------------------------------
1697:
1698:            /**
1699:             * Returns the start index of the constant pool item in {@link #b b}, plus
1700:             * one. <i>This method is intended for {@link Attribute} sub classes, and is
1701:             * normally not needed by class generators or adapters.</i>
1702:             *
1703:             * @param item the index a constant pool item.
1704:             * @return the start index of the constant pool item in {@link #b b}, plus
1705:             *         one.
1706:             */
1707:            public int getItem(final int item) {
1708:                return items[item];
1709:            }
1710:
1711:            /**
1712:             * Reads a byte value in {@link #b b}. <i>This method is intended for
1713:             * {@link Attribute} sub classes, and is normally not needed by class
1714:             * generators or adapters.</i>
1715:             *
1716:             * @param index the start index of the value to be read in {@link #b b}.
1717:             * @return the read value.
1718:             */
1719:            public int readByte(final int index) {
1720:                return b[index] & 0xFF;
1721:            }
1722:
1723:            /**
1724:             * Reads an unsigned short value in {@link #b b}. <i>This method is
1725:             * intended for {@link Attribute} sub classes, and is normally not needed by
1726:             * class generators or adapters.</i>
1727:             *
1728:             * @param index the start index of the value to be read in {@link #b b}.
1729:             * @return the read value.
1730:             */
1731:            public int readUnsignedShort(final int index) {
1732:                byte[] b = this .b;
1733:                return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
1734:            }
1735:
1736:            /**
1737:             * Reads a signed short value in {@link #b b}. <i>This method is intended
1738:             * for {@link Attribute} sub classes, and is normally not needed by class
1739:             * generators or adapters.</i>
1740:             *
1741:             * @param index the start index of the value to be read in {@link #b b}.
1742:             * @return the read value.
1743:             */
1744:            public short readShort(final int index) {
1745:                byte[] b = this .b;
1746:                return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
1747:            }
1748:
1749:            /**
1750:             * Reads a signed int value in {@link #b b}. <i>This method is intended for
1751:             * {@link Attribute} sub classes, and is normally not needed by class
1752:             * generators or adapters.</i>
1753:             *
1754:             * @param index the start index of the value to be read in {@link #b b}.
1755:             * @return the read value.
1756:             */
1757:            public int readInt(final int index) {
1758:                byte[] b = this .b;
1759:                return ((b[index] & 0xFF) << 24)
1760:                        | ((b[index + 1] & 0xFF) << 16)
1761:                        | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
1762:            }
1763:
1764:            /**
1765:             * Reads a signed long value in {@link #b b}. <i>This method is intended
1766:             * for {@link Attribute} sub classes, and is normally not needed by class
1767:             * generators or adapters.</i>
1768:             *
1769:             * @param index the start index of the value to be read in {@link #b b}.
1770:             * @return the read value.
1771:             */
1772:            public long readLong(final int index) {
1773:                long l1 = readInt(index);
1774:                long l0 = readInt(index + 4) & 0xFFFFFFFFL;
1775:                return (l1 << 32) | l0;
1776:            }
1777:
1778:            /**
1779:             * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
1780:             * is intended for {@link Attribute} sub classes, and is normally not needed
1781:             * by class generators or adapters.</i>
1782:             *
1783:             * @param index the start index of an unsigned short value in {@link #b b},
1784:             *              whose value is the index of an UTF8 constant pool item.
1785:             * @param buf   buffer to be used to read the item. This buffer must be
1786:             *              sufficiently large. It is not automatically resized.
1787:             * @return the String corresponding to the specified UTF8 item.
1788:             */
1789:            public String readUTF8(int index, final char[] buf) {
1790:                int item = readUnsignedShort(index);
1791:                String s = strings[item];
1792:                if (s != null) {
1793:                    return s;
1794:                }
1795:                index = items[item];
1796:                return strings[item] = readUTF(index + 2,
1797:                        readUnsignedShort(index), buf);
1798:            }
1799:
1800:            /**
1801:             * Reads UTF8 string in {@link #b b}.
1802:             *
1803:             * @param index  start offset of the UTF8 string to be read.
1804:             * @param utfLen length of the UTF8 string to be read.
1805:             * @param buf    buffer to be used to read the string. This buffer must be
1806:             *               sufficiently large. It is not automatically resized.
1807:             * @return the String corresponding to the specified UTF8 string.
1808:             */
1809:            private String readUTF(int index, final int utfLen, final char[] buf) {
1810:                int endIndex = index + utfLen;
1811:                byte[] b = this .b;
1812:                int strLen = 0;
1813:                int c, d, e;
1814:                while (index < endIndex) {
1815:                    c = b[index++] & 0xFF;
1816:                    switch (c >> 4) {
1817:                    case 0:
1818:                    case 1:
1819:                    case 2:
1820:                    case 3:
1821:                    case 4:
1822:                    case 5:
1823:                    case 6:
1824:                    case 7:
1825:                        // 0xxxxxxx
1826:                        buf[strLen++] = (char) c;
1827:                        break;
1828:                    case 12:
1829:                    case 13:
1830:                        // 110x xxxx 10xx xxxx
1831:                        d = b[index++];
1832:                        buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
1833:                        break;
1834:                    default:
1835:                        // 1110 xxxx 10xx xxxx 10xx xxxx
1836:                        d = b[index++];
1837:                        e = b[index++];
1838:                        buf[strLen++] = (char) (((c & 0x0F) << 12)
1839:                                | ((d & 0x3F) << 6) | (e & 0x3F));
1840:                        break;
1841:                    }
1842:                }
1843:                return new String(buf, 0, strLen);
1844:            }
1845:
1846:            /**
1847:             * Reads a class constant pool item in {@link #b b}. <i>This method is
1848:             * intended for {@link Attribute} sub classes, and is normally not needed by
1849:             * class generators or adapters.</i>
1850:             *
1851:             * @param index the start index of an unsigned short value in {@link #b b},
1852:             *              whose value is the index of a class constant pool item.
1853:             * @param buf   buffer to be used to read the item. This buffer must be
1854:             *              sufficiently large. It is not automatically resized.
1855:             * @return the String corresponding to the specified class item.
1856:             */
1857:            public String readClass(final int index, final char[] buf) {
1858:                // computes the start index of the CONSTANT_Class item in b
1859:                // and reads the CONSTANT_Utf8 item designated by
1860:                // the first two bytes of this CONSTANT_Class item
1861:                return readUTF8(items[readUnsignedShort(index)], buf);
1862:            }
1863:
1864:            /**
1865:             * Reads a numeric or string constant pool item in {@link #b b}. <i>This
1866:             * method is intended for {@link Attribute} sub classes, and is normally not
1867:             * needed by class generators or adapters.</i>
1868:             *
1869:             * @param item the index of a constant pool item.
1870:             * @param buf  buffer to be used to read the item. This buffer must be
1871:             *             sufficiently large. It is not automatically resized.
1872:             * @return the {@link Integer}, {@link Float}, {@link Long},
1873:             *         {@link Double}, {@link String} or {@link Type} corresponding to
1874:             *         the given constant pool item.
1875:             */
1876:            public Object readConst(final int item, final char[] buf) {
1877:                int index = items[item];
1878:                switch (b[index - 1]) {
1879:                case ClassWriter.INT:
1880:                    return new Integer(readInt(index));
1881:                case ClassWriter.FLOAT:
1882:                    return new Float(Float.intBitsToFloat(readInt(index)));
1883:                case ClassWriter.LONG:
1884:                    return new Long(readLong(index));
1885:                case ClassWriter.DOUBLE:
1886:                    return new Double(Double.longBitsToDouble(readLong(index)));
1887:                case ClassWriter.CLASS:
1888:                    String s = readUTF8(index, buf);
1889:                    return s.charAt(0) == '[' ? Type.getType(s) : Type
1890:                            .getObjectType(s);
1891:                    // case ClassWriter.STR:
1892:                default:
1893:                    return readUTF8(index, buf);
1894:                }
1895:            }
1896:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.