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