Source Code Cross Referenced for ClassReader.java in  » Rule-Engine » drolls-Rule-Engine » org » drools » 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 » Rule Engine » drolls Rule Engine » org.drools.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.drools.asm;
0030:
0031:        import java.io.IOException;
0032:        import java.io.InputStream;
0033:
0034:        /**
0035:         * A Java class parser to make a {@link ClassVisitor} visit an existing class.
0036:         * This class parses a byte array conforming to the Java class file format and
0037:         * calls the appropriate visit methods of a given class visitor for each field,
0038:         * method and bytecode instruction encountered.
0039:         * 
0040:         * @author Eric Bruneton
0041:         * @author Eugene Kuleshov
0042:         */
0043:        public class ClassReader {
0044:
0045:            /**
0046:             * The class to be parsed. <i>The content of this array must not be
0047:             * modified. This field is intended for {@link Attribute} sub classes, and
0048:             * is normally not needed by class generators or adapters.</i>
0049:             */
0050:            public final byte[] b;
0051:
0052:            /**
0053:             * The start index of each constant pool item in {@link #b b}, plus one.
0054:             * The one byte offset skips the constant pool item tag that indicates its
0055:             * type.
0056:             */
0057:            private int[] items;
0058:
0059:            /**
0060:             * The String objects corresponding to the CONSTANT_Utf8 items. This cache
0061:             * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
0062:             * which GREATLY improves performances (by a factor 2 to 3). This caching
0063:             * strategy could be extended to all constant pool items, but its benefit
0064:             * would not be so great for these items (because they are much less
0065:             * expensive to parse than CONSTANT_Utf8 items).
0066:             */
0067:            private String[] strings;
0068:
0069:            /**
0070:             * Maximum length of the strings contained in the constant pool of the
0071:             * class.
0072:             */
0073:            private int maxStringLength;
0074:
0075:            /**
0076:             * Start index of the class header information (access, name...) in
0077:             * {@link #b b}.
0078:             */
0079:            public final int header;
0080:
0081:            // ------------------------------------------------------------------------
0082:            // Constructors
0083:            // ------------------------------------------------------------------------
0084:
0085:            /**
0086:             * Constructs a new {@link ClassReader} object.
0087:             * 
0088:             * @param b the bytecode of the class to be read.
0089:             */
0090:            public ClassReader(final byte[] b) {
0091:                this (b, 0, b.length);
0092:            }
0093:
0094:            /**
0095:             * Constructs a new {@link ClassReader} object.
0096:             * 
0097:             * @param b the bytecode of the class to be read.
0098:             * @param off the start offset of the class data.
0099:             * @param len the length of the class data.
0100:             */
0101:            public ClassReader(final byte[] b, final int off, final int len) {
0102:                this .b = b;
0103:                // parses the constant pool
0104:                this .items = new int[readUnsignedShort(off + 8)];
0105:                final int ll = this .items.length;
0106:                this .strings = new String[ll];
0107:                int max = 0;
0108:                int index = off + 10;
0109:                for (int i = 1; i < ll; ++i) {
0110:                    this .items[i] = index + 1;
0111:                    final int tag = b[index];
0112:                    int size;
0113:                    switch (tag) {
0114:                    case ClassWriter.FIELD:
0115:                    case ClassWriter.METH:
0116:                    case ClassWriter.IMETH:
0117:                    case ClassWriter.INT:
0118:                    case ClassWriter.FLOAT:
0119:                    case ClassWriter.NAME_TYPE:
0120:                        size = 5;
0121:                        break;
0122:                    case ClassWriter.LONG:
0123:                    case ClassWriter.DOUBLE:
0124:                        size = 9;
0125:                        ++i;
0126:                        break;
0127:                    case ClassWriter.UTF8:
0128:                        size = 3 + readUnsignedShort(index + 1);
0129:                        if (size > max) {
0130:                            max = size;
0131:                        }
0132:                        break;
0133:                    // case ClassWriter.CLASS:
0134:                    // case ClassWriter.STR:
0135:                    default:
0136:                        size = 3;
0137:                        break;
0138:                    }
0139:                    index += size;
0140:                }
0141:                this .maxStringLength = max;
0142:                // the class header information starts just after the constant pool
0143:                this .header = index;
0144:            }
0145:
0146:            /**
0147:             * Copies the constant pool data into the given {@link ClassWriter}. Should
0148:             * be called before the {@link #accept(ClassVisitor,boolean)} method.
0149:             * 
0150:             * @param classWriter the {@link ClassWriter} to copy constant pool into.
0151:             */
0152:            void copyPool(final ClassWriter classWriter) {
0153:                final char[] buf = new char[this .maxStringLength];
0154:                final int ll = this .items.length;
0155:                final Item[] items2 = new Item[ll];
0156:                for (int i = 1; i < ll; i++) {
0157:                    int index = this .items[i];
0158:                    final int tag = this .b[index - 1];
0159:                    final Item item = new Item(i);
0160:                    int nameType;
0161:                    switch (tag) {
0162:                    case ClassWriter.FIELD:
0163:                    case ClassWriter.METH:
0164:                    case ClassWriter.IMETH:
0165:                        nameType = this .items[readUnsignedShort(index + 2)];
0166:                        item.set(tag, readClass(index, buf), readUTF8(nameType,
0167:                                buf), readUTF8(nameType + 2, buf));
0168:                        break;
0169:
0170:                    case ClassWriter.INT:
0171:                        item.set(readInt(index));
0172:                        break;
0173:
0174:                    case ClassWriter.FLOAT:
0175:                        item.set(Float.intBitsToFloat(readInt(index)));
0176:                        break;
0177:
0178:                    case ClassWriter.NAME_TYPE:
0179:                        item.set(tag, readUTF8(index, buf), readUTF8(index + 2,
0180:                                buf), null);
0181:                        break;
0182:
0183:                    case ClassWriter.LONG:
0184:                        item.set(readLong(index));
0185:                        ++i;
0186:                        break;
0187:
0188:                    case ClassWriter.DOUBLE:
0189:                        item.set(Double.longBitsToDouble(readLong(index)));
0190:                        ++i;
0191:                        break;
0192:
0193:                    case ClassWriter.UTF8: {
0194:                        String s = this .strings[i];
0195:                        if (s == null) {
0196:                            index = this .items[i];
0197:                            s = this .strings[i] = readUTF(index + 2,
0198:                                    readUnsignedShort(index), buf);
0199:                        }
0200:                        item.set(tag, s, null, null);
0201:                    }
0202:                        break;
0203:
0204:                    // case ClassWriter.STR:
0205:                    // case ClassWriter.CLASS:
0206:                    default:
0207:                        item.set(tag, readUTF8(index, buf), null, null);
0208:                        break;
0209:                    }
0210:
0211:                    final int index2 = item.hashCode % items2.length;
0212:                    item.next = items2[index2];
0213:                    items2[index2] = item;
0214:                }
0215:
0216:                final int off = this .items[1] - 1;
0217:                classWriter.pool.putByteArray(this .b, off, this .header - off);
0218:                classWriter.items = items2;
0219:                classWriter.threshold = (int) (0.75d * ll);
0220:                classWriter.index = ll;
0221:            }
0222:
0223:            /**
0224:             * Constructs a new {@link ClassReader} object.
0225:             * 
0226:             * @param is an input stream from which to read the class.
0227:             * @throws IOException if a problem occurs during reading.
0228:             */
0229:            public ClassReader(final InputStream is) throws IOException {
0230:                this (readClass(is));
0231:            }
0232:
0233:            /**
0234:             * Constructs a new {@link ClassReader} object.
0235:             * 
0236:             * @param name the fully qualified name of the class to be read.
0237:             * @throws IOException if an exception occurs during reading.
0238:             */
0239:            public ClassReader(final String name) throws IOException {
0240:                this (ClassLoader.getSystemResourceAsStream(name.replace('.',
0241:                        '/')
0242:                        + ".class"));
0243:            }
0244:
0245:            /**
0246:             * Reads the bytecode of a class.
0247:             * 
0248:             * @param is an input stream from which to read the class.
0249:             * @return the bytecode read from the given input stream.
0250:             * @throws IOException if a problem occurs during reading.
0251:             */
0252:            private static byte[] readClass(final InputStream is)
0253:                    throws IOException {
0254:                if (is == null) {
0255:                    throw new IOException("Class not found");
0256:                }
0257:                byte[] b = new byte[is.available()];
0258:                int len = 0;
0259:                while (true) {
0260:                    final int n = is.read(b, len, b.length - len);
0261:                    if (n == -1) {
0262:                        if (len < b.length) {
0263:                            final byte[] c = new byte[len];
0264:                            System.arraycopy(b, 0, c, 0, len);
0265:                            b = c;
0266:                        }
0267:                        return b;
0268:                    }
0269:                    len += n;
0270:                    if (len == b.length) {
0271:                        final byte[] c = new byte[b.length + 1000];
0272:                        System.arraycopy(b, 0, c, 0, len);
0273:                        b = c;
0274:                    }
0275:                }
0276:            }
0277:
0278:            // ------------------------------------------------------------------------
0279:            // Public methods
0280:            // ------------------------------------------------------------------------
0281:
0282:            /**
0283:             * Makes the given visitor visit the Java class of this {@link ClassReader}.
0284:             * This class is the one specified in the constructor (see
0285:             * {@link #ClassReader(byte[]) ClassReader}).
0286:             * 
0287:             * @param classVisitor the visitor that must visit this class.
0288:             * @param skipDebug <tt>true</tt> if the debug information of the class
0289:             *        must not be visited. In this case the
0290:             *        {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
0291:             *        {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
0292:             *        not be called.
0293:             */
0294:            public void accept(final ClassVisitor classVisitor,
0295:                    final boolean skipDebug) {
0296:                accept(classVisitor, new Attribute[0], skipDebug);
0297:            }
0298:
0299:            /**
0300:             * Makes the given visitor visit the Java class of this {@link ClassReader}.
0301:             * This class is the one specified in the constructor (see
0302:             * {@link #ClassReader(byte[]) ClassReader}).
0303:             * 
0304:             * @param classVisitor the visitor that must visit this class.
0305:             * @param attrs prototypes of the attributes that must be parsed during the
0306:             *        visit of the class. Any attribute whose type is not equal to the
0307:             *        type of one the prototypes will be ignored.
0308:             * @param skipDebug <tt>true</tt> if the debug information of the class
0309:             *        must not be visited. In this case the
0310:             *        {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
0311:             *        {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
0312:             *        not be called.
0313:             */
0314:            public void accept(final ClassVisitor classVisitor,
0315:                    final Attribute[] attrs, final boolean skipDebug) {
0316:                final byte[] b = this .b; // the bytecode array
0317:                final char[] c = new char[this .maxStringLength]; // buffer used to read strings
0318:                int i, j, k; // loop variables
0319:                int u, v, w; // indexes in b
0320:                Attribute attr;
0321:
0322:                int access;
0323:                String name;
0324:                String desc;
0325:                String attrName;
0326:                String signature;
0327:                int anns = 0;
0328:                int ianns = 0;
0329:                Attribute cattrs = null;
0330:
0331:                // visits the header
0332:                u = this .header;
0333:                access = readUnsignedShort(u);
0334:                name = readClass(u + 2, c);
0335:                v = this .items[readUnsignedShort(u + 4)];
0336:                final String super ClassName = v == 0 ? null : readUTF8(v, c);
0337:                final String[] implementedItfs = new String[readUnsignedShort(u + 6)];
0338:                w = 0;
0339:                u += 8;
0340:                for (i = 0; i < implementedItfs.length; ++i) {
0341:                    implementedItfs[i] = readClass(u, c);
0342:                    u += 2;
0343:                }
0344:
0345:                // skips fields and methods
0346:                v = u;
0347:                i = readUnsignedShort(v);
0348:                v += 2;
0349:                for (; i > 0; --i) {
0350:                    j = readUnsignedShort(v + 6);
0351:                    v += 8;
0352:                    for (; j > 0; --j) {
0353:                        v += 6 + readInt(v + 2);
0354:                    }
0355:                }
0356:                i = readUnsignedShort(v);
0357:                v += 2;
0358:                for (; i > 0; --i) {
0359:                    j = readUnsignedShort(v + 6);
0360:                    v += 8;
0361:                    for (; j > 0; --j) {
0362:                        v += 6 + readInt(v + 2);
0363:                    }
0364:                }
0365:                // reads the class's attributes
0366:                signature = null;
0367:                String sourceFile = null;
0368:                String sourceDebug = null;
0369:                String enclosingOwner = null;
0370:                String enclosingName = null;
0371:                String enclosingDesc = null;
0372:
0373:                i = readUnsignedShort(v);
0374:                v += 2;
0375:                for (; i > 0; --i) {
0376:                    attrName = readUTF8(v, c);
0377:                    if (attrName.equals("SourceFile")) {
0378:                        sourceFile = readUTF8(v + 6, c);
0379:                    } else if (attrName.equals("Deprecated")) {
0380:                        access |= Opcodes.ACC_DEPRECATED;
0381:                    } else if (attrName.equals("Synthetic")) {
0382:                        access |= Opcodes.ACC_SYNTHETIC;
0383:                    } else if (attrName.equals("Annotation")) {
0384:                        access |= Opcodes.ACC_ANNOTATION;
0385:                    } else if (attrName.equals("Enum")) {
0386:                        access |= Opcodes.ACC_ENUM;
0387:                    } else if (attrName.equals("InnerClasses")) {
0388:                        w = v + 6;
0389:                    } else if (attrName.equals("Signature")) {
0390:                        signature = readUTF8(v + 6, c);
0391:                    } else if (attrName.equals("SourceDebugExtension")) {
0392:                        final int len = readInt(v + 2);
0393:                        sourceDebug = readUTF(v + 6, len, new char[len]);
0394:                    } else if (attrName.equals("EnclosingMethod")) {
0395:                        enclosingOwner = readClass(v + 6, c);
0396:                        final int item = readUnsignedShort(v + 8);
0397:                        if (item != 0) {
0398:                            enclosingName = readUTF8(this .items[item], c);
0399:                            enclosingDesc = readUTF8(this .items[item] + 2, c);
0400:                        }
0401:                    } else if (attrName.equals("RuntimeVisibleAnnotations")) {
0402:                        anns = v + 6;
0403:                    } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
0404:                        ianns = v + 6;
0405:                    } else {
0406:                        attr = readAttribute(attrs, attrName, v + 6,
0407:                                readInt(v + 2), c, -1, null);
0408:                        if (attr != null) {
0409:                            attr.next = cattrs;
0410:                            cattrs = attr;
0411:                        }
0412:                    }
0413:                    v += 6 + readInt(v + 2);
0414:                }
0415:                // calls the visit method
0416:                classVisitor.visit(readInt(4), access, name, signature,
0417:                        super ClassName, implementedItfs);
0418:
0419:                // calls the visitSource method
0420:                if (sourceFile != null || sourceDebug != null) {
0421:                    classVisitor.visitSource(sourceFile, sourceDebug);
0422:                }
0423:
0424:                // calls the visitOuterClass method
0425:                if (enclosingOwner != null) {
0426:                    classVisitor.visitOuterClass(enclosingOwner, enclosingName,
0427:                            enclosingDesc);
0428:                }
0429:
0430:                // visits the class annotations
0431:                for (i = 1; i >= 0; --i) {
0432:                    v = i == 0 ? ianns : anns;
0433:                    if (v != 0) {
0434:                        j = readUnsignedShort(v);
0435:                        v += 2;
0436:                        for (; j > 0; --j) {
0437:                            desc = readUTF8(v, c);
0438:                            v += 2;
0439:                            v = readAnnotationValues(v, c, classVisitor
0440:                                    .visitAnnotation(desc, i != 0));
0441:                        }
0442:                    }
0443:                }
0444:
0445:                // visits the class attributes
0446:                while (cattrs != null) {
0447:                    attr = cattrs.next;
0448:                    cattrs.next = null;
0449:                    classVisitor.visitAttribute(cattrs);
0450:                    cattrs = attr;
0451:                }
0452:
0453:                // class the visitInnerClass method
0454:                if (w != 0) {
0455:                    i = readUnsignedShort(w);
0456:                    w += 2;
0457:                    for (; i > 0; --i) {
0458:                        classVisitor.visitInnerClass(
0459:                                readUnsignedShort(w) == 0 ? null : readClass(w,
0460:                                        c),
0461:                                readUnsignedShort(w + 2) == 0 ? null
0462:                                        : readClass(w + 2, c),
0463:                                readUnsignedShort(w + 4) == 0 ? null
0464:                                        : readUTF8(w + 4, c),
0465:                                readUnsignedShort(w + 6));
0466:                        w += 8;
0467:                    }
0468:                }
0469:
0470:                // visits the fields
0471:                i = readUnsignedShort(u);
0472:                u += 2;
0473:                for (; i > 0; --i) {
0474:                    access = readUnsignedShort(u);
0475:                    name = readUTF8(u + 2, c);
0476:                    desc = readUTF8(u + 4, c);
0477:                    // visits the field's attributes and looks for a ConstantValue
0478:                    // attribute
0479:                    int fieldValueItem = 0;
0480:                    signature = null;
0481:                    anns = 0;
0482:                    ianns = 0;
0483:                    cattrs = null;
0484:
0485:                    j = readUnsignedShort(u + 6);
0486:                    u += 8;
0487:                    for (; j > 0; --j) {
0488:                        attrName = readUTF8(u, c);
0489:                        if (attrName.equals("ConstantValue")) {
0490:                            fieldValueItem = readUnsignedShort(u + 6);
0491:                        } else if (attrName.equals("Synthetic")) {
0492:                            access |= Opcodes.ACC_SYNTHETIC;
0493:                        } else if (attrName.equals("Deprecated")) {
0494:                            access |= Opcodes.ACC_DEPRECATED;
0495:                        } else if (attrName.equals("Enum")) {
0496:                            access |= Opcodes.ACC_ENUM;
0497:                        } else if (attrName.equals("Signature")) {
0498:                            signature = readUTF8(u + 6, c);
0499:                        } else if (attrName.equals("RuntimeVisibleAnnotations")) {
0500:                            anns = u + 6;
0501:                        } else if (attrName
0502:                                .equals("RuntimeInvisibleAnnotations")) {
0503:                            ianns = u + 6;
0504:                        } else {
0505:                            attr = readAttribute(attrs, attrName, u + 6,
0506:                                    readInt(u + 2), c, -1, null);
0507:                            if (attr != null) {
0508:                                attr.next = cattrs;
0509:                                cattrs = attr;
0510:                            }
0511:                        }
0512:                        u += 6 + readInt(u + 2);
0513:                    }
0514:                    // reads the field's value, if any
0515:                    final Object value = (fieldValueItem == 0 ? null
0516:                            : readConst(fieldValueItem, c));
0517:                    // visits the field
0518:                    final FieldVisitor fv = classVisitor.visitField(access,
0519:                            name, desc, signature, value);
0520:                    // visits the field annotations and attributes
0521:                    if (fv != null) {
0522:                        for (j = 1; j >= 0; --j) {
0523:                            v = j == 0 ? ianns : anns;
0524:                            if (v != 0) {
0525:                                k = readUnsignedShort(v);
0526:                                v += 2;
0527:                                for (; k > 0; --k) {
0528:                                    desc = readUTF8(v, c);
0529:                                    v += 2;
0530:                                    v = readAnnotationValues(v, c, fv
0531:                                            .visitAnnotation(desc, j != 0));
0532:                                }
0533:                            }
0534:                        }
0535:                        while (cattrs != null) {
0536:                            attr = cattrs.next;
0537:                            cattrs.next = null;
0538:                            fv.visitAttribute(cattrs);
0539:                            cattrs = attr;
0540:                        }
0541:                        fv.visitEnd();
0542:                    }
0543:                }
0544:
0545:                // visits the methods
0546:                i = readUnsignedShort(u);
0547:                u += 2;
0548:                for (; i > 0; --i) {
0549:                    final int u0 = u + 6;
0550:                    access = readUnsignedShort(u);
0551:                    name = readUTF8(u + 2, c);
0552:                    desc = readUTF8(u + 4, c);
0553:                    signature = null;
0554:                    anns = 0;
0555:                    ianns = 0;
0556:                    int dann = 0;
0557:                    int mpanns = 0;
0558:                    int impanns = 0;
0559:                    cattrs = null;
0560:                    v = 0;
0561:                    w = 0;
0562:
0563:                    // looks for Code and Exceptions attributes
0564:                    j = readUnsignedShort(u + 6);
0565:                    u += 8;
0566:                    for (; j > 0; --j) {
0567:                        attrName = readUTF8(u, c);
0568:                        u += 2;
0569:                        final int attrSize = readInt(u);
0570:                        u += 4;
0571:                        if (attrName.equals("Code")) {
0572:                            v = u;
0573:                        } else if (attrName.equals("Exceptions")) {
0574:                            w = u;
0575:                        } else if (attrName.equals("Synthetic")) {
0576:                            access |= Opcodes.ACC_SYNTHETIC;
0577:                        } else if (attrName.equals("Varargs")) {
0578:                            access |= Opcodes.ACC_VARARGS;
0579:                        } else if (attrName.equals("Bridge")) {
0580:                            access |= Opcodes.ACC_BRIDGE;
0581:                        } else if (attrName.equals("Deprecated")) {
0582:                            access |= Opcodes.ACC_DEPRECATED;
0583:                        } else if (attrName.equals("Signature")) {
0584:                            signature = readUTF8(u, c);
0585:                        } else if (attrName.equals("AnnotationDefault")) {
0586:                            dann = u;
0587:                        } else if (attrName.equals("RuntimeVisibleAnnotations")) {
0588:                            anns = u;
0589:                        } else if (attrName
0590:                                .equals("RuntimeInvisibleAnnotations")) {
0591:                            ianns = u;
0592:                        } else if (attrName
0593:                                .equals("RuntimeVisibleParameterAnnotations")) {
0594:                            mpanns = u;
0595:                        } else if (attrName
0596:                                .equals("RuntimeInvisibleParameterAnnotations")) {
0597:                            impanns = u;
0598:                        } else {
0599:                            attr = readAttribute(attrs, attrName, u, attrSize,
0600:                                    c, -1, null);
0601:                            if (attr != null) {
0602:                                attr.next = cattrs;
0603:                                cattrs = attr;
0604:                            }
0605:                        }
0606:                        u += attrSize;
0607:                    }
0608:                    // reads declared exceptions
0609:                    String[] exceptions;
0610:                    if (w == 0) {
0611:                        exceptions = null;
0612:                    } else {
0613:                        exceptions = new String[readUnsignedShort(w)];
0614:                        w += 2;
0615:                        for (j = 0; j < exceptions.length; ++j) {
0616:                            exceptions[j] = readClass(w, c);
0617:                            w += 2;
0618:                        }
0619:                    }
0620:
0621:                    // visits the method's code, if any
0622:                    final MethodVisitor mv = classVisitor.visitMethod(access,
0623:                            name, desc, signature, exceptions);
0624:
0625:                    if (mv != null) {
0626:                        /*
0627:                         * if the returned MethodVisitor is in fact a MethodWriter, it
0628:                         * means there is no method adapter between the reader and the
0629:                         * writer. If, in addition, the writer's constant pool was
0630:                         * copied from this reader (mw.cw.cr == this), and the signature
0631:                         * and exceptions of the method have not been changed, then it
0632:                         * is possible to skip all visit events and just copy the
0633:                         * original code of the method to the writer (the access, name
0634:                         * and descriptor can have been changed, this is not important
0635:                         * since they are not copied as is from the reader).
0636:                         */
0637:                        if (mv instanceof  MethodWriter) {
0638:                            final MethodWriter mw = (MethodWriter) mv;
0639:                            if (mw.cw.cr == this ) {
0640:                                if (signature == mw.signature) {
0641:                                    boolean sameExceptions = false;
0642:                                    if (exceptions == null) {
0643:                                        sameExceptions = mw.exceptionCount == 0;
0644:                                    } else {
0645:                                        if (exceptions.length == mw.exceptionCount) {
0646:                                            sameExceptions = true;
0647:                                            for (j = exceptions.length - 1; j >= 0; --j) {
0648:                                                w -= 2;
0649:                                                if (mw.exceptions[j] != readUnsignedShort(w)) {
0650:                                                    sameExceptions = false;
0651:                                                    break;
0652:                                                }
0653:                                            }
0654:                                        }
0655:                                    }
0656:                                    if (sameExceptions) {
0657:                                        /*
0658:                                         * we do not copy directly the code into
0659:                                         * MethodWriter to save a byte array copy
0660:                                         * operation. The real copy will be done in
0661:                                         * ClassWriter.toByteArray().
0662:                                         */
0663:                                        mw.classReaderOffset = u0;
0664:                                        mw.classReaderLength = u - u0;
0665:                                        continue;
0666:                                    }
0667:                                }
0668:                            }
0669:                        }
0670:                        if (dann != 0) {
0671:                            final AnnotationVisitor dv = mv
0672:                                    .visitAnnotationDefault();
0673:                            readAnnotationValue(dann, c, null, dv);
0674:                            dv.visitEnd();
0675:                        }
0676:                        for (j = 1; j >= 0; --j) {
0677:                            w = j == 0 ? ianns : anns;
0678:                            if (w != 0) {
0679:                                k = readUnsignedShort(w);
0680:                                w += 2;
0681:                                for (; k > 0; --k) {
0682:                                    desc = readUTF8(w, c);
0683:                                    w += 2;
0684:                                    w = readAnnotationValues(w, c, mv
0685:                                            .visitAnnotation(desc, j != 0));
0686:                                }
0687:                            }
0688:                        }
0689:                        if (mpanns != 0) {
0690:                            readParameterAnnotations(mpanns, c, true, mv);
0691:                        }
0692:                        if (impanns != 0) {
0693:                            readParameterAnnotations(impanns, c, false, mv);
0694:                        }
0695:                        while (cattrs != null) {
0696:                            attr = cattrs.next;
0697:                            cattrs.next = null;
0698:                            mv.visitAttribute(cattrs);
0699:                            cattrs = attr;
0700:                        }
0701:                    }
0702:
0703:                    if (mv != null && v != 0) {
0704:                        final int maxStack = readUnsignedShort(v);
0705:                        final int maxLocals = readUnsignedShort(v + 2);
0706:                        final int codeLength = readInt(v + 4);
0707:                        v += 8;
0708:
0709:                        final int codeStart = v;
0710:                        final int codeEnd = v + codeLength;
0711:
0712:                        mv.visitCode();
0713:
0714:                        // 1st phase: finds the labels
0715:                        int label;
0716:                        final Label[] labels = new Label[codeLength + 1];
0717:                        while (v < codeEnd) {
0718:                            int opcode = b[v] & 0xFF;
0719:                            switch (ClassWriter.TYPE[opcode]) {
0720:                            case ClassWriter.NOARG_INSN:
0721:                            case ClassWriter.IMPLVAR_INSN:
0722:                                v += 1;
0723:                                break;
0724:                            case ClassWriter.LABEL_INSN:
0725:                                label = v - codeStart + readShort(v + 1);
0726:                                if (labels[label] == null) {
0727:                                    labels[label] = new Label();
0728:                                }
0729:                                v += 3;
0730:                                break;
0731:                            case ClassWriter.LABELW_INSN:
0732:                                label = v - codeStart + readInt(v + 1);
0733:                                if (labels[label] == null) {
0734:                                    labels[label] = new Label();
0735:                                }
0736:                                v += 5;
0737:                                break;
0738:                            case ClassWriter.WIDE_INSN:
0739:                                opcode = b[v + 1] & 0xFF;
0740:                                if (opcode == Opcodes.IINC) {
0741:                                    v += 6;
0742:                                } else {
0743:                                    v += 4;
0744:                                }
0745:                                break;
0746:                            case ClassWriter.TABL_INSN:
0747:                                // skips 0 to 3 padding bytes
0748:                                w = v - codeStart;
0749:                                v = v + 4 - (w & 3);
0750:                                // reads instruction
0751:                                label = w + readInt(v);
0752:                                v += 4;
0753:                                if (labels[label] == null) {
0754:                                    labels[label] = new Label();
0755:                                }
0756:                                j = readInt(v);
0757:                                v += 4;
0758:                                j = readInt(v) - j + 1;
0759:                                v += 4;
0760:                                for (; j > 0; --j) {
0761:                                    label = w + readInt(v);
0762:                                    v += 4;
0763:                                    if (labels[label] == null) {
0764:                                        labels[label] = new Label();
0765:                                    }
0766:                                }
0767:                                break;
0768:                            case ClassWriter.LOOK_INSN:
0769:                                // skips 0 to 3 padding bytes
0770:                                w = v - codeStart;
0771:                                v = v + 4 - (w & 3);
0772:                                // reads instruction
0773:                                label = w + readInt(v);
0774:                                v += 4;
0775:                                if (labels[label] == null) {
0776:                                    labels[label] = new Label();
0777:                                }
0778:                                j = readInt(v);
0779:                                v += 4;
0780:                                for (; j > 0; --j) {
0781:                                    v += 4; // skips key
0782:                                    label = w + readInt(v);
0783:                                    v += 4;
0784:                                    if (labels[label] == null) {
0785:                                        labels[label] = new Label();
0786:                                    }
0787:                                }
0788:                                break;
0789:                            case ClassWriter.VAR_INSN:
0790:                            case ClassWriter.SBYTE_INSN:
0791:                            case ClassWriter.LDC_INSN:
0792:                                v += 2;
0793:                                break;
0794:                            case ClassWriter.SHORT_INSN:
0795:                            case ClassWriter.LDCW_INSN:
0796:                            case ClassWriter.FIELDORMETH_INSN:
0797:                            case ClassWriter.TYPE_INSN:
0798:                            case ClassWriter.IINC_INSN:
0799:                                v += 3;
0800:                                break;
0801:                            case ClassWriter.ITFMETH_INSN:
0802:                                v += 5;
0803:                                break;
0804:                            // case MANA_INSN:
0805:                            default:
0806:                                v += 4;
0807:                                break;
0808:                            }
0809:                        }
0810:                        // parses the try catch entries
0811:                        j = readUnsignedShort(v);
0812:                        v += 2;
0813:                        for (; j > 0; --j) {
0814:                            label = readUnsignedShort(v);
0815:                            Label start = labels[label];
0816:                            if (start == null) {
0817:                                labels[label] = start = new Label();
0818:                            }
0819:                            label = readUnsignedShort(v + 2);
0820:                            Label end = labels[label];
0821:                            if (end == null) {
0822:                                labels[label] = end = new Label();
0823:                            }
0824:                            label = readUnsignedShort(v + 4);
0825:                            Label handler = labels[label];
0826:                            if (handler == null) {
0827:                                labels[label] = handler = new Label();
0828:                            }
0829:
0830:                            final int type = readUnsignedShort(v + 6);
0831:                            if (type == 0) {
0832:                                mv
0833:                                        .visitTryCatchBlock(start, end,
0834:                                                handler, null);
0835:                            } else {
0836:                                mv.visitTryCatchBlock(start, end, handler,
0837:                                        readUTF8(this .items[type], c));
0838:                            }
0839:                            v += 8;
0840:                        }
0841:                        // parses the local variable, line number tables, and code
0842:                        // attributes
0843:                        int varTable = 0;
0844:                        int varTypeTable = 0;
0845:                        cattrs = null;
0846:                        j = readUnsignedShort(v);
0847:                        v += 2;
0848:                        for (; j > 0; --j) {
0849:                            attrName = readUTF8(v, c);
0850:                            if (attrName.equals("LocalVariableTable")) {
0851:                                if (!skipDebug) {
0852:                                    varTable = v + 6;
0853:                                    k = readUnsignedShort(v + 6);
0854:                                    w = v + 8;
0855:                                    for (; k > 0; --k) {
0856:                                        label = readUnsignedShort(w);
0857:                                        if (labels[label] == null) {
0858:                                            labels[label] = new Label();
0859:                                        }
0860:                                        label += readUnsignedShort(w + 2);
0861:                                        if (labels[label] == null) {
0862:                                            labels[label] = new Label();
0863:                                        }
0864:                                        w += 10;
0865:                                    }
0866:                                }
0867:                            } else if (attrName
0868:                                    .equals("LocalVariableTypeTable")) {
0869:                                varTypeTable = v + 6;
0870:                            } else if (attrName.equals("LineNumberTable")) {
0871:                                if (!skipDebug) {
0872:                                    k = readUnsignedShort(v + 6);
0873:                                    w = v + 8;
0874:                                    for (; k > 0; --k) {
0875:                                        label = readUnsignedShort(w);
0876:                                        if (labels[label] == null) {
0877:                                            labels[label] = new Label();
0878:                                        }
0879:                                        labels[label].line = readUnsignedShort(w + 2);
0880:                                        w += 4;
0881:                                    }
0882:                                }
0883:                            } else {
0884:                                for (k = 0; k < attrs.length; ++k) {
0885:                                    if (attrs[k].type.equals(attrName)) {
0886:                                        attr = attrs[k].read(this , v + 6,
0887:                                                readInt(v + 2), c,
0888:                                                codeStart - 8, labels);
0889:                                        if (attr != null) {
0890:                                            attr.next = cattrs;
0891:                                            cattrs = attr;
0892:                                        }
0893:                                    }
0894:                                }
0895:                            }
0896:                            v += 6 + readInt(v + 2);
0897:                        }
0898:
0899:                        // 2nd phase: visits each instruction
0900:                        v = codeStart;
0901:                        Label l;
0902:                        while (v < codeEnd) {
0903:                            w = v - codeStart;
0904:                            l = labels[w];
0905:                            if (l != null) {
0906:                                mv.visitLabel(l);
0907:                                if (!skipDebug && l.line > 0) {
0908:                                    mv.visitLineNumber(l.line, l);
0909:                                }
0910:                            }
0911:                            int opcode = b[v] & 0xFF;
0912:                            switch (ClassWriter.TYPE[opcode]) {
0913:                            case ClassWriter.NOARG_INSN:
0914:                                mv.visitInsn(opcode);
0915:                                v += 1;
0916:                                break;
0917:                            case ClassWriter.IMPLVAR_INSN:
0918:                                if (opcode > Opcodes.ISTORE) {
0919:                                    opcode -= 59; // ISTORE_0
0920:                                    mv.visitVarInsn(Opcodes.ISTORE
0921:                                            + (opcode >> 2), opcode & 0x3);
0922:                                } else {
0923:                                    opcode -= 26; // ILOAD_0
0924:                                    mv.visitVarInsn(Opcodes.ILOAD
0925:                                            + (opcode >> 2), opcode & 0x3);
0926:                                }
0927:                                v += 1;
0928:                                break;
0929:                            case ClassWriter.LABEL_INSN:
0930:                                mv.visitJumpInsn(opcode, labels[w
0931:                                        + readShort(v + 1)]);
0932:                                v += 3;
0933:                                break;
0934:                            case ClassWriter.LABELW_INSN:
0935:                                mv.visitJumpInsn(opcode - 33, labels[w
0936:                                        + readInt(v + 1)]);
0937:                                v += 5;
0938:                                break;
0939:                            case ClassWriter.WIDE_INSN:
0940:                                opcode = b[v + 1] & 0xFF;
0941:                                if (opcode == Opcodes.IINC) {
0942:                                    mv.visitIincInsn(readUnsignedShort(v + 2),
0943:                                            readShort(v + 4));
0944:                                    v += 6;
0945:                                } else {
0946:                                    mv.visitVarInsn(opcode,
0947:                                            readUnsignedShort(v + 2));
0948:                                    v += 4;
0949:                                }
0950:                                break;
0951:                            case ClassWriter.TABL_INSN:
0952:                                // skips 0 to 3 padding bytes
0953:                                v = v + 4 - (w & 3);
0954:                                // reads instruction
0955:                                label = w + readInt(v);
0956:                                v += 4;
0957:                                final int min = readInt(v);
0958:                                v += 4;
0959:                                final int max = readInt(v);
0960:                                v += 4;
0961:                                final Label[] table = new Label[max - min + 1];
0962:                                for (j = 0; j < table.length; ++j) {
0963:                                    table[j] = labels[w + readInt(v)];
0964:                                    v += 4;
0965:                                }
0966:                                mv.visitTableSwitchInsn(min, max,
0967:                                        labels[label], table);
0968:                                break;
0969:                            case ClassWriter.LOOK_INSN:
0970:                                // skips 0 to 3 padding bytes
0971:                                v = v + 4 - (w & 3);
0972:                                // reads instruction
0973:                                label = w + readInt(v);
0974:                                v += 4;
0975:                                j = readInt(v);
0976:                                v += 4;
0977:                                final int[] keys = new int[j];
0978:                                final Label[] values = new Label[j];
0979:                                for (j = 0; j < keys.length; ++j) {
0980:                                    keys[j] = readInt(v);
0981:                                    v += 4;
0982:                                    values[j] = labels[w + readInt(v)];
0983:                                    v += 4;
0984:                                }
0985:                                mv.visitLookupSwitchInsn(labels[label], keys,
0986:                                        values);
0987:                                break;
0988:                            case ClassWriter.VAR_INSN:
0989:                                mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
0990:                                v += 2;
0991:                                break;
0992:                            case ClassWriter.SBYTE_INSN:
0993:                                mv.visitIntInsn(opcode, b[v + 1]);
0994:                                v += 2;
0995:                                break;
0996:                            case ClassWriter.SHORT_INSN:
0997:                                mv.visitIntInsn(opcode, readShort(v + 1));
0998:                                v += 3;
0999:                                break;
1000:                            case ClassWriter.LDC_INSN:
1001:                                mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
1002:                                v += 2;
1003:                                break;
1004:                            case ClassWriter.LDCW_INSN:
1005:                                mv.visitLdcInsn(readConst(
1006:                                        readUnsignedShort(v + 1), c));
1007:                                v += 3;
1008:                                break;
1009:                            case ClassWriter.FIELDORMETH_INSN:
1010:                            case ClassWriter.ITFMETH_INSN:
1011:                                int cpIndex = this .items[readUnsignedShort(v + 1)];
1012:                                final String iowner = readClass(cpIndex, c);
1013:                                cpIndex = this .items[readUnsignedShort(cpIndex + 2)];
1014:                                final String iname = readUTF8(cpIndex, c);
1015:                                final String idesc = readUTF8(cpIndex + 2, c);
1016:                                if (opcode < Opcodes.INVOKEVIRTUAL) {
1017:                                    mv.visitFieldInsn(opcode, iowner, iname,
1018:                                            idesc);
1019:                                } else {
1020:                                    mv.visitMethodInsn(opcode, iowner, iname,
1021:                                            idesc);
1022:                                }
1023:                                if (opcode == Opcodes.INVOKEINTERFACE) {
1024:                                    v += 5;
1025:                                } else {
1026:                                    v += 3;
1027:                                }
1028:                                break;
1029:                            case ClassWriter.TYPE_INSN:
1030:                                mv.visitTypeInsn(opcode, readClass(v + 1, c));
1031:                                v += 3;
1032:                                break;
1033:                            case ClassWriter.IINC_INSN:
1034:                                mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
1035:                                v += 3;
1036:                                break;
1037:                            // case MANA_INSN:
1038:                            default:
1039:                                mv.visitMultiANewArrayInsn(readClass(v + 1, c),
1040:                                        b[v + 3] & 0xFF);
1041:                                v += 4;
1042:                                break;
1043:                            }
1044:                        }
1045:                        l = labels[codeEnd - codeStart];
1046:                        if (l != null) {
1047:                            mv.visitLabel(l);
1048:                        }
1049:
1050:                        // visits the local variable tables
1051:                        if (!skipDebug && varTable != 0) {
1052:                            int[] typeTable = null;
1053:                            if (varTypeTable != 0) {
1054:                                w = varTypeTable;
1055:                                k = readUnsignedShort(w) * 3;
1056:                                w += 2;
1057:                                typeTable = new int[k];
1058:                                while (k > 0) {
1059:                                    typeTable[--k] = w + 6; // signature
1060:                                    typeTable[--k] = readUnsignedShort(w + 8); // index
1061:                                    typeTable[--k] = readUnsignedShort(w); // start
1062:                                    w += 10;
1063:                                }
1064:                            }
1065:                            w = varTable;
1066:                            k = readUnsignedShort(w);
1067:                            w += 2;
1068:                            for (; k > 0; --k) {
1069:                                final int start = readUnsignedShort(w);
1070:                                final int length = readUnsignedShort(w + 2);
1071:                                final int index = readUnsignedShort(w + 8);
1072:                                String vsignature = null;
1073:                                if (typeTable != null) {
1074:                                    for (int a = 0; a < typeTable.length; a += 3) {
1075:                                        if (typeTable[a] == start
1076:                                                && typeTable[a + 1] == index) {
1077:                                            vsignature = readUTF8(
1078:                                                    typeTable[a + 2], c);
1079:                                            break;
1080:                                        }
1081:                                    }
1082:                                }
1083:                                mv.visitLocalVariable(readUTF8(w + 4, c),
1084:                                        readUTF8(w + 6, c), vsignature,
1085:                                        labels[start], labels[start + length],
1086:                                        index);
1087:                                w += 10;
1088:                            }
1089:                        }
1090:                        // visits the other attributes
1091:                        while (cattrs != null) {
1092:                            attr = cattrs.next;
1093:                            cattrs.next = null;
1094:                            mv.visitAttribute(cattrs);
1095:                            cattrs = attr;
1096:                        }
1097:                        // visits the min stack and min locals values
1098:                        mv.visitMaxs(maxStack, maxLocals);
1099:                    }
1100:
1101:                    if (mv != null) {
1102:                        mv.visitEnd();
1103:                    }
1104:                }
1105:
1106:                // visits the end of the class
1107:                classVisitor.visitEnd();
1108:            }
1109:
1110:            /**
1111:             * Reads parameter annotations and makes the given visitor visit them.
1112:             * 
1113:             * @param v start offset in {@link #b b} of the annotations to be read.
1114:             * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1115:             *        {@link #readClass(int,char[]) readClass} or
1116:             *        {@link #readConst readConst}.
1117:             * @param visible <tt>true</tt> if the annotations to be read are visible
1118:             *        at runtime.
1119:             * @param mv the visitor that must visit the annotations.
1120:             */
1121:            private void readParameterAnnotations(int v, final char[] buf,
1122:                    final boolean visible, final MethodVisitor mv) {
1123:                final int n = this .b[v++] & 0xFF;
1124:                for (int i = 0; i < n; ++i) {
1125:                    int j = readUnsignedShort(v);
1126:                    v += 2;
1127:                    for (; j > 0; --j) {
1128:                        final String desc = readUTF8(v, buf);
1129:                        v += 2;
1130:                        final AnnotationVisitor av = mv
1131:                                .visitParameterAnnotation(i, desc, visible);
1132:                        v = readAnnotationValues(v, buf, av);
1133:                    }
1134:                }
1135:            }
1136:
1137:            /**
1138:             * Reads the values of an annotation and makes the given visitor visit them.
1139:             * 
1140:             * @param v the start offset in {@link #b b} of the values to be read
1141:             *        (including the unsigned short that gives the number of values).
1142:             * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1143:             *        {@link #readClass(int,char[]) readClass} or
1144:             *        {@link #readConst readConst}.
1145:             * @param av the visitor that must visit the values.
1146:             * @return the end offset of the annotations values.
1147:             */
1148:            private int readAnnotationValues(int v, final char[] buf,
1149:                    final AnnotationVisitor av) {
1150:                int i = readUnsignedShort(v);
1151:                v += 2;
1152:                for (; i > 0; --i) {
1153:                    final String name = readUTF8(v, buf);
1154:                    v += 2;
1155:                    v = readAnnotationValue(v, buf, name, av);
1156:                }
1157:                av.visitEnd();
1158:                return v;
1159:            }
1160:
1161:            /**
1162:             * Reads a value of an annotation and makes the given visitor visit it.
1163:             * 
1164:             * @param v the start offset in {@link #b b} of the value to be read (<i>not
1165:             *        including the value name constant pool index</i>).
1166:             * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1167:             *        {@link #readClass(int,char[]) readClass} or
1168:             *        {@link #readConst readConst}.
1169:             * @param name the name of the value to be read.
1170:             * @param av the visitor that must visit the value.
1171:             * @return the end offset of the annotation value.
1172:             */
1173:            private int readAnnotationValue(int v, final char[] buf,
1174:                    final String name, final AnnotationVisitor av) {
1175:                int i;
1176:                switch (readByte(v++)) {
1177:                case 'I': // pointer to CONSTANT_Integer
1178:                case 'J': // pointer to CONSTANT_Long
1179:                case 'F': // pointer to CONSTANT_Float
1180:                case 'D': // pointer to CONSTANT_Double
1181:                    av.visit(name, readConst(readUnsignedShort(v), buf));
1182:                    v += 2;
1183:                    break;
1184:                case 'B': // pointer to CONSTANT_Byte
1185:                    av.visit(name, new Byte(
1186:                            (byte) readInt(this .items[readUnsignedShort(v)])));
1187:                    v += 2;
1188:                    break;
1189:                case 'Z': // pointer to CONSTANT_Boolean
1190:                    final boolean b = readInt(this .items[readUnsignedShort(v)]) == 0;
1191:                    av.visit(name, b ? Boolean.FALSE : Boolean.TRUE);
1192:                    v += 2;
1193:                    break;
1194:                case 'S': // pointer to CONSTANT_Short
1195:                    av.visit(name, new Short(
1196:                            (short) readInt(this .items[readUnsignedShort(v)])));
1197:                    v += 2;
1198:                    break;
1199:                case 'C': // pointer to CONSTANT_Char
1200:                    av.visit(name, new Character(
1201:                            (char) readInt(this .items[readUnsignedShort(v)])));
1202:                    v += 2;
1203:                    break;
1204:                case 's': // pointer to CONSTANT_Utf8
1205:                    av.visit(name, readUTF8(v, buf));
1206:                    v += 2;
1207:                    break;
1208:                case 'e': // enum_const_value
1209:                    av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
1210:                    v += 4;
1211:                    break;
1212:                case 'c': // class_info
1213:                    av.visit(name, Type.getType(readUTF8(v, buf)));
1214:                    v += 2;
1215:                    break;
1216:                case '@': // annotation_value
1217:                    final String desc = readUTF8(v, buf);
1218:                    v += 2;
1219:                    v = readAnnotationValues(v, buf, av.visitAnnotation(name,
1220:                            desc));
1221:                    break;
1222:                case '[': // array_value
1223:                    final int size = readUnsignedShort(v);
1224:                    v += 2;
1225:                    if (size == 0) {
1226:                        av.visitArray(name).visitEnd();
1227:                        return v;
1228:                    }
1229:                    switch (readByte(v++)) {
1230:                    case 'B':
1231:                        final byte[] bv = new byte[size];
1232:                        for (i = 0; i < size; i++) {
1233:                            bv[i] = (byte) readInt(this .items[readUnsignedShort(v)]);
1234:                            v += 3;
1235:                        }
1236:                        av.visit(name, bv);
1237:                        --v;
1238:                        break;
1239:                    case 'Z':
1240:                        final boolean[] zv = new boolean[size];
1241:                        for (i = 0; i < size; i++) {
1242:                            zv[i] = readInt(this .items[readUnsignedShort(v)]) != 0;
1243:                            v += 3;
1244:                        }
1245:                        av.visit(name, zv);
1246:                        --v;
1247:                        break;
1248:                    case 'S':
1249:                        final short[] sv = new short[size];
1250:                        for (i = 0; i < size; i++) {
1251:                            sv[i] = (short) readInt(this .items[readUnsignedShort(v)]);
1252:                            v += 3;
1253:                        }
1254:                        av.visit(name, sv);
1255:                        --v;
1256:                        break;
1257:                    case 'C':
1258:                        final char[] cv = new char[size];
1259:                        for (i = 0; i < size; i++) {
1260:                            cv[i] = (char) readInt(this .items[readUnsignedShort(v)]);
1261:                            v += 3;
1262:                        }
1263:                        av.visit(name, cv);
1264:                        --v;
1265:                        break;
1266:                    case 'I':
1267:                        final int[] iv = new int[size];
1268:                        for (i = 0; i < size; i++) {
1269:                            iv[i] = readInt(this .items[readUnsignedShort(v)]);
1270:                            v += 3;
1271:                        }
1272:                        av.visit(name, iv);
1273:                        --v;
1274:                        break;
1275:                    case 'J':
1276:                        final long[] lv = new long[size];
1277:                        for (i = 0; i < size; i++) {
1278:                            lv[i] = readLong(this .items[readUnsignedShort(v)]);
1279:                            v += 3;
1280:                        }
1281:                        av.visit(name, lv);
1282:                        --v;
1283:                        break;
1284:                    case 'F':
1285:                        final float[] fv = new float[size];
1286:                        for (i = 0; i < size; i++) {
1287:                            fv[i] = Float
1288:                                    .intBitsToFloat(readInt(this .items[readUnsignedShort(v)]));
1289:                            v += 3;
1290:                        }
1291:                        av.visit(name, fv);
1292:                        --v;
1293:                        break;
1294:                    case 'D':
1295:                        final double[] dv = new double[size];
1296:                        for (i = 0; i < size; i++) {
1297:                            dv[i] = Double
1298:                                    .longBitsToDouble(readLong(this .items[readUnsignedShort(v)]));
1299:                            v += 3;
1300:                        }
1301:                        av.visit(name, dv);
1302:                        --v;
1303:                        break;
1304:                    default:
1305:                        v--;
1306:                        final AnnotationVisitor aav = av.visitArray(name);
1307:                        for (i = size; i > 0; --i) {
1308:                            v = readAnnotationValue(v, buf, null, aav);
1309:                        }
1310:                        aav.visitEnd();
1311:                    }
1312:                }
1313:                return v;
1314:            }
1315:
1316:            /**
1317:             * Reads an attribute in {@link #b b}.
1318:             * 
1319:             * @param attrs prototypes of the attributes that must be parsed during the
1320:             *        visit of the class. Any attribute whose type is not equal to the
1321:             *        type of one the prototypes is ignored (i.e. an empty
1322:             *        {@link Attribute} instance is returned).
1323:             * @param type the type of the attribute.
1324:             * @param off index of the first byte of the attribute's content in
1325:             *        {@link #b b}. The 6 attribute header bytes, containing the type
1326:             *        and the length of the attribute, are not taken into account here
1327:             *        (they have already been read).
1328:             * @param len the length of the attribute's content.
1329:             * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1330:             *        {@link #readClass(int,char[]) readClass} or
1331:             *        {@link #readConst readConst}.
1332:             * @param codeOff index of the first byte of code's attribute content in
1333:             *        {@link #b b}, or -1 if the attribute to be read is not a code
1334:             *        attribute. The 6 attribute header bytes, containing the type and
1335:             *        the length of the attribute, are not taken into account here.
1336:             * @param labels the labels of the method's code, or <tt>null</tt> if the
1337:             *        attribute to be read is not a code attribute.
1338:             * @return the attribute that has been read, or <tt>null</tt> to skip this
1339:             *         attribute.
1340:             */
1341:            private Attribute readAttribute(final Attribute[] attrs,
1342:                    final String type, final int off, final int len,
1343:                    final char[] buf, final int codeOff, final Label[] labels) {
1344:                for (int i = 0; i < attrs.length; ++i) {
1345:                    if (attrs[i].type.equals(type)) {
1346:                        return attrs[i].read(this , off, len, buf, codeOff,
1347:                                labels);
1348:                    }
1349:                }
1350:                return new Attribute(type).read(this , off, len, null, -1, null);
1351:            }
1352:
1353:            // ------------------------------------------------------------------------
1354:            // Utility methods: low level parsing
1355:            // ------------------------------------------------------------------------
1356:
1357:            /**
1358:             * Returns the start index of the constant pool item in {@link #b b}, plus
1359:             * one. <i>This method is intended for {@link Attribute} sub classes, and is
1360:             * normally not needed by class generators or adapters.</i>
1361:             * 
1362:             * @param item the index a constant pool item.
1363:             * @return the start index of the constant pool item in {@link #b b}, plus
1364:             *         one.
1365:             */
1366:            public int getItem(final int item) {
1367:                return this .items[item];
1368:            }
1369:
1370:            /**
1371:             * Reads a byte value in {@link #b b}. <i>This method is intended for
1372:             * {@link Attribute} sub classes, and is normally not needed by class
1373:             * generators or adapters.</i>
1374:             * 
1375:             * @param index the start index of the value to be read in {@link #b b}.
1376:             * @return the read value.
1377:             */
1378:            public int readByte(final int index) {
1379:                return this .b[index] & 0xFF;
1380:            }
1381:
1382:            /**
1383:             * Reads an unsigned short value in {@link #b b}. <i>This method is
1384:             * intended for {@link Attribute} sub classes, and is normally not needed by
1385:             * class generators or adapters.</i>
1386:             * 
1387:             * @param index the start index of the value to be read in {@link #b b}.
1388:             * @return the read value.
1389:             */
1390:            public int readUnsignedShort(final int index) {
1391:                final byte[] b = this .b;
1392:                return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
1393:            }
1394:
1395:            /**
1396:             * Reads a signed short value in {@link #b b}. <i>This method is intended
1397:             * for {@link Attribute} sub classes, and is normally not needed by class
1398:             * generators or adapters.</i>
1399:             * 
1400:             * @param index the start index of the value to be read in {@link #b b}.
1401:             * @return the read value.
1402:             */
1403:            public short readShort(final int index) {
1404:                final byte[] b = this .b;
1405:                return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
1406:            }
1407:
1408:            /**
1409:             * Reads a signed int value in {@link #b b}. <i>This method is intended for
1410:             * {@link Attribute} sub classes, and is normally not needed by class
1411:             * generators or adapters.</i>
1412:             * 
1413:             * @param index the start index of the value to be read in {@link #b b}.
1414:             * @return the read value.
1415:             */
1416:            public int readInt(final int index) {
1417:                final byte[] b = this .b;
1418:                return ((b[index] & 0xFF) << 24)
1419:                        | ((b[index + 1] & 0xFF) << 16)
1420:                        | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
1421:            }
1422:
1423:            /**
1424:             * Reads a signed long value in {@link #b b}. <i>This method is intended
1425:             * for {@link Attribute} sub classes, and is normally not needed by class
1426:             * generators or adapters.</i>
1427:             * 
1428:             * @param index the start index of the value to be read in {@link #b b}.
1429:             * @return the read value.
1430:             */
1431:            public long readLong(final int index) {
1432:                final long l1 = readInt(index);
1433:                final long l0 = readInt(index + 4) & 0xFFFFFFFFL;
1434:                return (l1 << 32) | l0;
1435:            }
1436:
1437:            /**
1438:             * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
1439:             * is intended for {@link Attribute} sub classes, and is normally not needed
1440:             * by class generators or adapters.</i>
1441:             * 
1442:             * @param index the start index of an unsigned short value in {@link #b b},
1443:             *        whose value is the index of an UTF8 constant pool item.
1444:             * @param buf buffer to be used to read the item. This buffer must be
1445:             *        sufficiently large. It is not automatically resized.
1446:             * @return the String corresponding to the specified UTF8 item.
1447:             */
1448:            public String readUTF8(int index, final char[] buf) {
1449:                final int item = readUnsignedShort(index);
1450:                final String s = this .strings[item];
1451:                if (s != null) {
1452:                    return s;
1453:                }
1454:                index = this .items[item];
1455:                return this .strings[item] = readUTF(index + 2,
1456:                        readUnsignedShort(index), buf);
1457:            }
1458:
1459:            /**
1460:             * Reads UTF8 string in {@link #b b}.
1461:             * 
1462:             * @param index start offset of the UTF8 string to be read.
1463:             * @param utfLen length of the UTF8 string to be read.
1464:             * @param buf buffer to be used to read the string. This buffer must be
1465:             *        sufficiently large. It is not automatically resized.
1466:             * @return the String corresponding to the specified UTF8 string.
1467:             */
1468:            private String readUTF(int index, final int utfLen, final char[] buf) {
1469:                final int endIndex = index + utfLen;
1470:                final byte[] b = this .b;
1471:                int strLen = 0;
1472:                int c, d, e;
1473:                while (index < endIndex) {
1474:                    c = b[index++] & 0xFF;
1475:                    switch (c >> 4) {
1476:                    case 0:
1477:                    case 1:
1478:                    case 2:
1479:                    case 3:
1480:                    case 4:
1481:                    case 5:
1482:                    case 6:
1483:                    case 7:
1484:                        // 0xxxxxxx
1485:                        buf[strLen++] = (char) c;
1486:                        break;
1487:                    case 12:
1488:                    case 13:
1489:                        // 110x xxxx 10xx xxxx
1490:                        d = b[index++];
1491:                        buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
1492:                        break;
1493:                    default:
1494:                        // 1110 xxxx 10xx xxxx 10xx xxxx
1495:                        d = b[index++];
1496:                        e = b[index++];
1497:                        buf[strLen++] = (char) (((c & 0x0F) << 12)
1498:                                | ((d & 0x3F) << 6) | (e & 0x3F));
1499:                        break;
1500:                    }
1501:                }
1502:                return new String(buf, 0, strLen);
1503:            }
1504:
1505:            /**
1506:             * Reads a class constant pool item in {@link #b b}. <i>This method is
1507:             * intended for {@link Attribute} sub classes, and is normally not needed by
1508:             * class generators or adapters.</i>
1509:             * 
1510:             * @param index the start index of an unsigned short value in {@link #b b},
1511:             *        whose value is the index of a class constant pool item.
1512:             * @param buf buffer to be used to read the item. This buffer must be
1513:             *        sufficiently large. It is not automatically resized.
1514:             * @return the String corresponding to the specified class item.
1515:             */
1516:            public String readClass(final int index, final char[] buf) {
1517:                // computes the start index of the CONSTANT_Class item in b
1518:                // and reads the CONSTANT_Utf8 item designated by
1519:                // the first two bytes of this CONSTANT_Class item
1520:                return readUTF8(this .items[readUnsignedShort(index)], buf);
1521:            }
1522:
1523:            /**
1524:             * Reads a numeric or string constant pool item in {@link #b b}. <i>This
1525:             * method is intended for {@link Attribute} sub classes, and is normally not
1526:             * needed by class generators or adapters.</i>
1527:             * 
1528:             * @param item the index of a constant pool item.
1529:             * @param buf buffer to be used to read the item. This buffer must be
1530:             *        sufficiently large. It is not automatically resized.
1531:             * @return the {@link Integer}, {@link Float}, {@link Long},
1532:             *         {@link Double}, {@link String} or {@link Type} corresponding to
1533:             *         the given constant pool item.
1534:             */
1535:            public Object readConst(final int item, final char[] buf) {
1536:                final int index = this .items[item];
1537:                switch (this .b[index - 1]) {
1538:                case ClassWriter.INT:
1539:                    return new Integer(readInt(index));
1540:                case ClassWriter.FLOAT:
1541:                    return new Float(Float.intBitsToFloat(readInt(index)));
1542:                case ClassWriter.LONG:
1543:                    return new Long(readLong(index));
1544:                case ClassWriter.DOUBLE:
1545:                    return new Double(Double.longBitsToDouble(readLong(index)));
1546:                case ClassWriter.CLASS:
1547:                    final String s = readUTF8(index, buf);
1548:                    return Type.getType(s.charAt(0) == '[' ? s : "L" + s + ";");
1549:                    // case ClassWriter.STR:
1550:                default:
1551:                    return readUTF8(index, buf);
1552:                }
1553:            }
1554:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.