Source Code Cross Referenced for CheckMethodAdapter.java in  » Net » Terracotta » com » tc » asm » util » 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 » Net » Terracotta » com.tc.asm.util 
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 com.tc.asm.util;
0030:
0031:        import com.tc.asm.AnnotationVisitor;
0032:        import com.tc.asm.Attribute;
0033:        import com.tc.asm.Label;
0034:        import com.tc.asm.MethodAdapter;
0035:        import com.tc.asm.MethodVisitor;
0036:        import com.tc.asm.Opcodes;
0037:        import com.tc.asm.Type;
0038:
0039:        import java.util.HashMap;
0040:
0041:        /**
0042:         * A {@link MethodAdapter} that checks that its methods are properly used. More
0043:         * precisely this code adapter checks each instruction individually (i.e., each
0044:         * visit method checks some preconditions based <i>only</i> on its arguments -
0045:         * such as the fact that the given opcode is correct for a given visit method),
0046:         * but does <i>not</i> check the <i>sequence</i> of instructions. For example,
0047:         * in a method whose signature is <tt>void m ()</tt>, the invalid instruction
0048:         * IRETURN, or the invalid sequence IADD L2I will <i>not</i> be detected by
0049:         * this code adapter.
0050:         * 
0051:         * @author Eric Bruneton
0052:         */
0053:        public class CheckMethodAdapter extends MethodAdapter {
0054:
0055:            /**
0056:             * <tt>true</tt> if the visitCode method has been called.
0057:             */
0058:            private boolean startCode;
0059:
0060:            /**
0061:             * <tt>true</tt> if the visitMaxs method has been called.
0062:             */
0063:            private boolean endCode;
0064:
0065:            /**
0066:             * <tt>true</tt> if the visitEnd method has been called.
0067:             */
0068:            private boolean endMethod;
0069:
0070:            /**
0071:             * The already visited labels. This map associate Integer values to Label
0072:             * keys.
0073:             */
0074:            private HashMap labels;
0075:
0076:            /**
0077:             * Code of the visit method to be used for each opcode.
0078:             */
0079:            private final static int[] TYPE;
0080:
0081:            static {
0082:                String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
0083:                        + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
0084:                        + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
0085:                        + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
0086:                TYPE = new int[s.length()];
0087:                for (int i = 0; i < TYPE.length; ++i) {
0088:                    TYPE[i] = s.charAt(i) - 'A' - 1;
0089:                }
0090:            }
0091:
0092:            // code to generate the above string
0093:            // public static void main (String[] args) {
0094:            // int[] TYPE = new int[] {
0095:            // 0, //NOP
0096:            // 0, //ACONST_NULL
0097:            // 0, //ICONST_M1
0098:            // 0, //ICONST_0
0099:            // 0, //ICONST_1
0100:            // 0, //ICONST_2
0101:            // 0, //ICONST_3
0102:            // 0, //ICONST_4
0103:            // 0, //ICONST_5
0104:            // 0, //LCONST_0
0105:            // 0, //LCONST_1
0106:            // 0, //FCONST_0
0107:            // 0, //FCONST_1
0108:            // 0, //FCONST_2
0109:            // 0, //DCONST_0
0110:            // 0, //DCONST_1
0111:            // 1, //BIPUSH
0112:            // 1, //SIPUSH
0113:            // 7, //LDC
0114:            // -1, //LDC_W
0115:            // -1, //LDC2_W
0116:            // 2, //ILOAD
0117:            // 2, //LLOAD
0118:            // 2, //FLOAD
0119:            // 2, //DLOAD
0120:            // 2, //ALOAD
0121:            // -1, //ILOAD_0
0122:            // -1, //ILOAD_1
0123:            // -1, //ILOAD_2
0124:            // -1, //ILOAD_3
0125:            // -1, //LLOAD_0
0126:            // -1, //LLOAD_1
0127:            // -1, //LLOAD_2
0128:            // -1, //LLOAD_3
0129:            // -1, //FLOAD_0
0130:            // -1, //FLOAD_1
0131:            // -1, //FLOAD_2
0132:            // -1, //FLOAD_3
0133:            // -1, //DLOAD_0
0134:            // -1, //DLOAD_1
0135:            // -1, //DLOAD_2
0136:            // -1, //DLOAD_3
0137:            // -1, //ALOAD_0
0138:            // -1, //ALOAD_1
0139:            // -1, //ALOAD_2
0140:            // -1, //ALOAD_3
0141:            // 0, //IALOAD
0142:            // 0, //LALOAD
0143:            // 0, //FALOAD
0144:            // 0, //DALOAD
0145:            // 0, //AALOAD
0146:            // 0, //BALOAD
0147:            // 0, //CALOAD
0148:            // 0, //SALOAD
0149:            // 2, //ISTORE
0150:            // 2, //LSTORE
0151:            // 2, //FSTORE
0152:            // 2, //DSTORE
0153:            // 2, //ASTORE
0154:            // -1, //ISTORE_0
0155:            // -1, //ISTORE_1
0156:            // -1, //ISTORE_2
0157:            // -1, //ISTORE_3
0158:            // -1, //LSTORE_0
0159:            // -1, //LSTORE_1
0160:            // -1, //LSTORE_2
0161:            // -1, //LSTORE_3
0162:            // -1, //FSTORE_0
0163:            // -1, //FSTORE_1
0164:            // -1, //FSTORE_2
0165:            // -1, //FSTORE_3
0166:            // -1, //DSTORE_0
0167:            // -1, //DSTORE_1
0168:            // -1, //DSTORE_2
0169:            // -1, //DSTORE_3
0170:            // -1, //ASTORE_0
0171:            // -1, //ASTORE_1
0172:            // -1, //ASTORE_2
0173:            // -1, //ASTORE_3
0174:            // 0, //IASTORE
0175:            // 0, //LASTORE
0176:            // 0, //FASTORE
0177:            // 0, //DASTORE
0178:            // 0, //AASTORE
0179:            // 0, //BASTORE
0180:            // 0, //CASTORE
0181:            // 0, //SASTORE
0182:            // 0, //POP
0183:            // 0, //POP2
0184:            // 0, //DUP
0185:            // 0, //DUP_X1
0186:            // 0, //DUP_X2
0187:            // 0, //DUP2
0188:            // 0, //DUP2_X1
0189:            // 0, //DUP2_X2
0190:            // 0, //SWAP
0191:            // 0, //IADD
0192:            // 0, //LADD
0193:            // 0, //FADD
0194:            // 0, //DADD
0195:            // 0, //ISUB
0196:            // 0, //LSUB
0197:            // 0, //FSUB
0198:            // 0, //DSUB
0199:            // 0, //IMUL
0200:            // 0, //LMUL
0201:            // 0, //FMUL
0202:            // 0, //DMUL
0203:            // 0, //IDIV
0204:            // 0, //LDIV
0205:            // 0, //FDIV
0206:            // 0, //DDIV
0207:            // 0, //IREM
0208:            // 0, //LREM
0209:            // 0, //FREM
0210:            // 0, //DREM
0211:            // 0, //INEG
0212:            // 0, //LNEG
0213:            // 0, //FNEG
0214:            // 0, //DNEG
0215:            // 0, //ISHL
0216:            // 0, //LSHL
0217:            // 0, //ISHR
0218:            // 0, //LSHR
0219:            // 0, //IUSHR
0220:            // 0, //LUSHR
0221:            // 0, //IAND
0222:            // 0, //LAND
0223:            // 0, //IOR
0224:            // 0, //LOR
0225:            // 0, //IXOR
0226:            // 0, //LXOR
0227:            // 8, //IINC
0228:            // 0, //I2L
0229:            // 0, //I2F
0230:            // 0, //I2D
0231:            // 0, //L2I
0232:            // 0, //L2F
0233:            // 0, //L2D
0234:            // 0, //F2I
0235:            // 0, //F2L
0236:            // 0, //F2D
0237:            // 0, //D2I
0238:            // 0, //D2L
0239:            // 0, //D2F
0240:            // 0, //I2B
0241:            // 0, //I2C
0242:            // 0, //I2S
0243:            // 0, //LCMP
0244:            // 0, //FCMPL
0245:            // 0, //FCMPG
0246:            // 0, //DCMPL
0247:            // 0, //DCMPG
0248:            // 6, //IFEQ
0249:            // 6, //IFNE
0250:            // 6, //IFLT
0251:            // 6, //IFGE
0252:            // 6, //IFGT
0253:            // 6, //IFLE
0254:            // 6, //IF_ICMPEQ
0255:            // 6, //IF_ICMPNE
0256:            // 6, //IF_ICMPLT
0257:            // 6, //IF_ICMPGE
0258:            // 6, //IF_ICMPGT
0259:            // 6, //IF_ICMPLE
0260:            // 6, //IF_ACMPEQ
0261:            // 6, //IF_ACMPNE
0262:            // 6, //GOTO
0263:            // 6, //JSR
0264:            // 2, //RET
0265:            // 9, //TABLESWITCH
0266:            // 10, //LOOKUPSWITCH
0267:            // 0, //IRETURN
0268:            // 0, //LRETURN
0269:            // 0, //FRETURN
0270:            // 0, //DRETURN
0271:            // 0, //ARETURN
0272:            // 0, //RETURN
0273:            // 4, //GETSTATIC
0274:            // 4, //PUTSTATIC
0275:            // 4, //GETFIELD
0276:            // 4, //PUTFIELD
0277:            // 5, //INVOKEVIRTUAL
0278:            // 5, //INVOKESPECIAL
0279:            // 5, //INVOKESTATIC
0280:            // 5, //INVOKEINTERFACE
0281:            // -1, //UNUSED
0282:            // 3, //NEW
0283:            // 1, //NEWARRAY
0284:            // 3, //ANEWARRAY
0285:            // 0, //ARRAYLENGTH
0286:            // 0, //ATHROW
0287:            // 3, //CHECKCAST
0288:            // 3, //INSTANCEOF
0289:            // 0, //MONITORENTER
0290:            // 0, //MONITOREXIT
0291:            // -1, //WIDE
0292:            // 11, //MULTIANEWARRAY
0293:            // 6, //IFNULL
0294:            // 6, //IFNONNULL
0295:            // -1, //GOTO_W
0296:            // -1 //JSR_W
0297:            // };
0298:            // for (int i = 0; i < TYPE.length; ++i) {
0299:            // System.out.print((char)(TYPE[i] + 1 + 'A'));
0300:            // }
0301:            // System.out.println();
0302:            // }
0303:
0304:            /**
0305:             * Constructs a new {@link CheckMethodAdapter} object.
0306:             * 
0307:             * @param cv the code visitor to which this adapter must delegate calls.
0308:             */
0309:            public CheckMethodAdapter(final MethodVisitor cv) {
0310:                super (cv);
0311:                this .labels = new HashMap();
0312:            }
0313:
0314:            public AnnotationVisitor visitAnnotation(final String desc,
0315:                    final boolean visible) {
0316:                checkEndMethod();
0317:                checkDesc(desc, false);
0318:                return new CheckAnnotationAdapter(mv.visitAnnotation(desc,
0319:                        visible));
0320:            }
0321:
0322:            public AnnotationVisitor visitAnnotationDefault() {
0323:                checkEndMethod();
0324:                return new CheckAnnotationAdapter(mv.visitAnnotationDefault(),
0325:                        false);
0326:            }
0327:
0328:            public AnnotationVisitor visitParameterAnnotation(
0329:                    final int parameter, final String desc,
0330:                    final boolean visible) {
0331:                checkEndMethod();
0332:                checkDesc(desc, false);
0333:                return new CheckAnnotationAdapter(mv.visitParameterAnnotation(
0334:                        parameter, desc, visible));
0335:            }
0336:
0337:            public void visitAttribute(final Attribute attr) {
0338:                checkEndMethod();
0339:                if (attr == null) {
0340:                    throw new IllegalArgumentException(
0341:                            "Invalid attribute (must not be null)");
0342:                }
0343:                mv.visitAttribute(attr);
0344:            }
0345:
0346:            public void visitCode() {
0347:                startCode = true;
0348:                mv.visitCode();
0349:            }
0350:
0351:            public void visitFrame(final int type, final int nLocal,
0352:                    final Object[] local, final int nStack, final Object[] stack) {
0353:                int mLocal;
0354:                int mStack;
0355:                switch (type) {
0356:                case Opcodes.F_NEW:
0357:                case Opcodes.F_FULL:
0358:                    mLocal = Integer.MAX_VALUE;
0359:                    mStack = Integer.MAX_VALUE;
0360:                    break;
0361:
0362:                case Opcodes.F_SAME:
0363:                    mLocal = 0;
0364:                    mStack = 0;
0365:                    break;
0366:
0367:                case Opcodes.F_SAME1:
0368:                    mLocal = 0;
0369:                    mStack = 1;
0370:                    break;
0371:
0372:                case Opcodes.F_APPEND:
0373:                case Opcodes.F_CHOP:
0374:                    mLocal = 3;
0375:                    mStack = 0;
0376:                    break;
0377:
0378:                default:
0379:                    throw new IllegalArgumentException("Invalid frame type "
0380:                            + type);
0381:                }
0382:
0383:                if (nLocal > mLocal) {
0384:                    throw new IllegalArgumentException("Invalid nLocal="
0385:                            + nLocal + " for frame type " + type);
0386:                }
0387:                if (nStack > mStack) {
0388:                    throw new IllegalArgumentException("Invalid nStack="
0389:                            + nStack + " for frame type " + type);
0390:                }
0391:
0392:                if (type != Opcodes.F_CHOP) {
0393:                    if (nLocal > 0 && (local == null || local.length < nLocal)) {
0394:                        throw new IllegalArgumentException(
0395:                                "Array local[] is shorter than nLocal");
0396:                    }
0397:                    for (int i = 0; i < nLocal; ++i) {
0398:                        checkFrameValue(local[i]);
0399:                    }
0400:                }
0401:                if (nStack > 0 && (stack == null || stack.length < nStack)) {
0402:                    throw new IllegalArgumentException(
0403:                            "Array stack[] is shorter than nStack");
0404:                }
0405:                for (int i = 0; i < nStack; ++i) {
0406:                    checkFrameValue(stack[i]);
0407:                }
0408:
0409:                mv.visitFrame(type, nLocal, local, nStack, stack);
0410:            }
0411:
0412:            public void visitInsn(final int opcode) {
0413:                checkStartCode();
0414:                checkEndCode();
0415:                checkOpcode(opcode, 0);
0416:                mv.visitInsn(opcode);
0417:            }
0418:
0419:            public void visitIntInsn(final int opcode, final int operand) {
0420:                checkStartCode();
0421:                checkEndCode();
0422:                checkOpcode(opcode, 1);
0423:                switch (opcode) {
0424:                case Opcodes.BIPUSH:
0425:                    checkSignedByte(operand, "Invalid operand");
0426:                    break;
0427:                case Opcodes.SIPUSH:
0428:                    checkSignedShort(operand, "Invalid operand");
0429:                    break;
0430:                // case Constants.NEWARRAY:
0431:                default:
0432:                    if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
0433:                        throw new IllegalArgumentException(
0434:                                "Invalid operand (must be an array type code T_...): "
0435:                                        + operand);
0436:                    }
0437:                }
0438:                mv.visitIntInsn(opcode, operand);
0439:            }
0440:
0441:            public void visitVarInsn(final int opcode, final int var) {
0442:                checkStartCode();
0443:                checkEndCode();
0444:                checkOpcode(opcode, 2);
0445:                checkUnsignedShort(var, "Invalid variable index");
0446:                mv.visitVarInsn(opcode, var);
0447:            }
0448:
0449:            public void visitTypeInsn(final int opcode, final String type) {
0450:                checkStartCode();
0451:                checkEndCode();
0452:                checkOpcode(opcode, 3);
0453:                checkInternalName(type, "type");
0454:                if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
0455:                    throw new IllegalArgumentException(
0456:                            "NEW cannot be used to create arrays: " + type);
0457:                }
0458:                mv.visitTypeInsn(opcode, type);
0459:            }
0460:
0461:            public void visitFieldInsn(final int opcode, final String owner,
0462:                    final String name, final String desc) {
0463:                checkStartCode();
0464:                checkEndCode();
0465:                checkOpcode(opcode, 4);
0466:                checkInternalName(owner, "owner");
0467:                checkIdentifier(name, "name");
0468:                checkDesc(desc, false);
0469:                mv.visitFieldInsn(opcode, owner, name, desc);
0470:            }
0471:
0472:            public void visitMethodInsn(final int opcode, final String owner,
0473:                    final String name, final String desc) {
0474:                checkStartCode();
0475:                checkEndCode();
0476:                checkOpcode(opcode, 5);
0477:                checkMethodIdentifier(name, "name");
0478:                checkInternalName(owner, "owner");
0479:                checkMethodDesc(desc);
0480:                mv.visitMethodInsn(opcode, owner, name, desc);
0481:            }
0482:
0483:            public void visitJumpInsn(final int opcode, final Label label) {
0484:                checkStartCode();
0485:                checkEndCode();
0486:                checkOpcode(opcode, 6);
0487:                checkLabel(label, false, "label");
0488:                mv.visitJumpInsn(opcode, label);
0489:            }
0490:
0491:            public void visitLabel(final Label label) {
0492:                checkStartCode();
0493:                checkEndCode();
0494:                checkLabel(label, false, "label");
0495:                if (labels.get(label) != null) {
0496:                    throw new IllegalArgumentException("Already visited label");
0497:                } else {
0498:                    labels.put(label, new Integer(labels.size()));
0499:                }
0500:                mv.visitLabel(label);
0501:            }
0502:
0503:            public void visitLdcInsn(final Object cst) {
0504:                checkStartCode();
0505:                checkEndCode();
0506:                if (!(cst instanceof  Type)) {
0507:                    checkConstant(cst);
0508:                }
0509:                mv.visitLdcInsn(cst);
0510:            }
0511:
0512:            public void visitIincInsn(final int var, final int increment) {
0513:                checkStartCode();
0514:                checkEndCode();
0515:                checkUnsignedShort(var, "Invalid variable index");
0516:                checkSignedShort(increment, "Invalid increment");
0517:                mv.visitIincInsn(var, increment);
0518:            }
0519:
0520:            public void visitTableSwitchInsn(final int min, final int max,
0521:                    final Label dflt, final Label labels[]) {
0522:                checkStartCode();
0523:                checkEndCode();
0524:                if (max < min) {
0525:                    throw new IllegalArgumentException("Max = " + max
0526:                            + " must be greater than or equal to min = " + min);
0527:                }
0528:                checkLabel(dflt, false, "default label");
0529:                if (labels == null || labels.length != max - min + 1) {
0530:                    throw new IllegalArgumentException(
0531:                            "There must be max - min + 1 labels");
0532:                }
0533:                for (int i = 0; i < labels.length; ++i) {
0534:                    checkLabel(labels[i], false, "label at index " + i);
0535:                }
0536:                mv.visitTableSwitchInsn(min, max, dflt, labels);
0537:            }
0538:
0539:            public void visitLookupSwitchInsn(final Label dflt,
0540:                    final int keys[], final Label labels[]) {
0541:                checkEndCode();
0542:                checkStartCode();
0543:                checkLabel(dflt, false, "default label");
0544:                if (keys == null || labels == null
0545:                        || keys.length != labels.length) {
0546:                    throw new IllegalArgumentException(
0547:                            "There must be the same number of keys and labels");
0548:                }
0549:                for (int i = 0; i < labels.length; ++i) {
0550:                    checkLabel(labels[i], false, "label at index " + i);
0551:                }
0552:                mv.visitLookupSwitchInsn(dflt, keys, labels);
0553:            }
0554:
0555:            public void visitMultiANewArrayInsn(final String desc,
0556:                    final int dims) {
0557:                checkStartCode();
0558:                checkEndCode();
0559:                checkDesc(desc, false);
0560:                if (desc.charAt(0) != '[') {
0561:                    throw new IllegalArgumentException(
0562:                            "Invalid descriptor (must be an array type descriptor): "
0563:                                    + desc);
0564:                }
0565:                if (dims < 1) {
0566:                    throw new IllegalArgumentException(
0567:                            "Invalid dimensions (must be greater than 0): "
0568:                                    + dims);
0569:                }
0570:                if (dims > desc.lastIndexOf('[') + 1) {
0571:                    throw new IllegalArgumentException(
0572:                            "Invalid dimensions (must not be greater than dims(desc)): "
0573:                                    + dims);
0574:                }
0575:                mv.visitMultiANewArrayInsn(desc, dims);
0576:            }
0577:
0578:            public void visitTryCatchBlock(final Label start, final Label end,
0579:                    final Label handler, final String type) {
0580:                checkStartCode();
0581:                checkEndCode();
0582:                if (type != null) {
0583:                    checkInternalName(type, "type");
0584:                }
0585:                mv.visitTryCatchBlock(start, end, handler, type);
0586:            }
0587:
0588:            public void visitLocalVariable(final String name,
0589:                    final String desc, final String signature,
0590:                    final Label start, final Label end, final int index) {
0591:                checkStartCode();
0592:                checkEndCode();
0593:                checkIdentifier(name, "name");
0594:                checkDesc(desc, false);
0595:                checkLabel(start, true, "start label");
0596:                checkLabel(end, true, "end label");
0597:                checkUnsignedShort(index, "Invalid variable index");
0598:                int s = ((Integer) labels.get(start)).intValue();
0599:                int e = ((Integer) labels.get(end)).intValue();
0600:                if (e < s) {
0601:                    throw new IllegalArgumentException(
0602:                            "Invalid start and end labels (end must be greater than start)");
0603:                }
0604:                mv.visitLocalVariable(name, desc, signature, start, end, index);
0605:            }
0606:
0607:            public void visitLineNumber(final int line, final Label start) {
0608:                checkStartCode();
0609:                checkEndCode();
0610:                checkUnsignedShort(line, "Invalid line number");
0611:                checkLabel(start, true, "start label");
0612:                mv.visitLineNumber(line, start);
0613:            }
0614:
0615:            public void visitMaxs(final int maxStack, final int maxLocals) {
0616:                checkStartCode();
0617:                checkEndCode();
0618:                endCode = true;
0619:                checkUnsignedShort(maxStack, "Invalid max stack");
0620:                checkUnsignedShort(maxLocals, "Invalid max locals");
0621:                mv.visitMaxs(maxStack, maxLocals);
0622:            }
0623:
0624:            public void visitEnd() {
0625:                checkEndMethod();
0626:                endMethod = true;
0627:                mv.visitEnd();
0628:            }
0629:
0630:            // -------------------------------------------------------------------------
0631:
0632:            /**
0633:             * Checks that the visitCode method has been called.
0634:             */
0635:            void checkStartCode() {
0636:                if (!startCode) {
0637:                    throw new IllegalStateException(
0638:                            "Cannot visit instructions before visitCode has been called.");
0639:                }
0640:            }
0641:
0642:            /**
0643:             * Checks that the visitMaxs method has not been called.
0644:             */
0645:            void checkEndCode() {
0646:                if (endCode) {
0647:                    throw new IllegalStateException(
0648:                            "Cannot visit instructions after visitMaxs has been called.");
0649:                }
0650:            }
0651:
0652:            /**
0653:             * Checks that the visitEnd method has not been called.
0654:             */
0655:            void checkEndMethod() {
0656:                if (endMethod) {
0657:                    throw new IllegalStateException(
0658:                            "Cannot visit elements after visitEnd has been called.");
0659:                }
0660:            }
0661:
0662:            /**
0663:             * Checks a stack frame value.
0664:             * 
0665:             * @param value the value to be checked.
0666:             */
0667:            static void checkFrameValue(final Object value) {
0668:                if (value == Opcodes.TOP || value == Opcodes.INTEGER
0669:                        || value == Opcodes.FLOAT || value == Opcodes.LONG
0670:                        || value == Opcodes.DOUBLE || value == Opcodes.NULL
0671:                        || value == Opcodes.UNINITIALIZED_THIS) {
0672:                    return;
0673:                }
0674:                if (value instanceof  String) {
0675:                    checkInternalName((String) value,
0676:                            "Invalid stack frame value");
0677:                    return;
0678:                }
0679:                if (!(value instanceof  Label)) {
0680:                    throw new IllegalArgumentException(
0681:                            "Invalid stack frame value: " + value);
0682:                }
0683:            }
0684:
0685:            /**
0686:             * Checks that the type of the given opcode is equal to the given type.
0687:             * 
0688:             * @param opcode the opcode to be checked.
0689:             * @param type the expected opcode type.
0690:             */
0691:            static void checkOpcode(final int opcode, final int type) {
0692:                if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
0693:                    throw new IllegalArgumentException("Invalid opcode: "
0694:                            + opcode);
0695:                }
0696:            }
0697:
0698:            /**
0699:             * Checks that the given value is a signed byte.
0700:             * 
0701:             * @param value the value to be checked.
0702:             * @param msg an message to be used in case of error.
0703:             */
0704:            static void checkSignedByte(final int value, final String msg) {
0705:                if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
0706:                    throw new IllegalArgumentException(msg
0707:                            + " (must be a signed byte): " + value);
0708:                }
0709:            }
0710:
0711:            /**
0712:             * Checks that the given value is a signed short.
0713:             * 
0714:             * @param value the value to be checked.
0715:             * @param msg an message to be used in case of error.
0716:             */
0717:            static void checkSignedShort(final int value, final String msg) {
0718:                if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
0719:                    throw new IllegalArgumentException(msg
0720:                            + " (must be a signed short): " + value);
0721:                }
0722:            }
0723:
0724:            /**
0725:             * Checks that the given value is an unsigned short.
0726:             * 
0727:             * @param value the value to be checked.
0728:             * @param msg an message to be used in case of error.
0729:             */
0730:            static void checkUnsignedShort(final int value, final String msg) {
0731:                if (value < 0 || value > 65535) {
0732:                    throw new IllegalArgumentException(msg
0733:                            + " (must be an unsigned short): " + value);
0734:                }
0735:            }
0736:
0737:            /**
0738:             * Checks that the given value is an {@link Integer}, a{@link Float}, a
0739:             * {@link Long}, a {@link Double} or a {@link String}.
0740:             * 
0741:             * @param cst the value to be checked.
0742:             */
0743:            static void checkConstant(final Object cst) {
0744:                if (!(cst instanceof  Integer) && !(cst instanceof  Float)
0745:                        && !(cst instanceof  Long) && !(cst instanceof  Double)
0746:                        && !(cst instanceof  String)) {
0747:                    throw new IllegalArgumentException("Invalid constant: "
0748:                            + cst);
0749:                }
0750:            }
0751:
0752:            /**
0753:             * Checks that the given string is a valid Java identifier.
0754:             * 
0755:             * @param name the string to be checked.
0756:             * @param msg a message to be used in case of error.
0757:             */
0758:            static void checkIdentifier(final String name, final String msg) {
0759:                checkIdentifier(name, 0, -1, msg);
0760:            }
0761:
0762:            /**
0763:             * Checks that the given substring is a valid Java identifier.
0764:             * 
0765:             * @param name the string to be checked.
0766:             * @param start index of the first character of the identifier (inclusive).
0767:             * @param end index of the last character of the identifier (exclusive). -1
0768:             *        is equivalent to <tt>name.length()</tt> if name is not
0769:             *        <tt>null</tt>.
0770:             * @param msg a message to be used in case of error.
0771:             */
0772:            static void checkIdentifier(final String name, final int start,
0773:                    final int end, final String msg) {
0774:                if (name == null
0775:                        || (end == -1 ? name.length() <= start : end <= start)) {
0776:                    throw new IllegalArgumentException("Invalid " + msg
0777:                            + " (must not be null or empty)");
0778:                }
0779:                if (!Character.isJavaIdentifierStart(name.charAt(start))) {
0780:                    throw new IllegalArgumentException("Invalid " + msg
0781:                            + " (must be a valid Java identifier): " + name);
0782:                }
0783:                int max = end == -1 ? name.length() : end;
0784:                for (int i = start + 1; i < max; ++i) {
0785:                    if (!Character.isJavaIdentifierPart(name.charAt(i))) {
0786:                        throw new IllegalArgumentException("Invalid " + msg
0787:                                + " (must be a valid Java identifier): " + name);
0788:                    }
0789:                }
0790:            }
0791:
0792:            /**
0793:             * Checks that the given string is a valid Java identifier or is equal to
0794:             * '&lt;init&gt;' or '&lt;clinit&gt;'.
0795:             * 
0796:             * @param name the string to be checked.
0797:             * @param msg a message to be used in case of error.
0798:             */
0799:            static void checkMethodIdentifier(final String name,
0800:                    final String msg) {
0801:                if (name == null || name.length() == 0) {
0802:                    throw new IllegalArgumentException("Invalid " + msg
0803:                            + " (must not be null or empty)");
0804:                }
0805:                if (name.equals("<init>") || name.equals("<clinit>")) {
0806:                    return;
0807:                }
0808:                if (!Character.isJavaIdentifierStart(name.charAt(0))) {
0809:                    throw new IllegalArgumentException(
0810:                            "Invalid "
0811:                                    + msg
0812:                                    + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
0813:                                    + name);
0814:                }
0815:                for (int i = 1; i < name.length(); ++i) {
0816:                    if (!Character.isJavaIdentifierPart(name.charAt(i))) {
0817:                        throw new IllegalArgumentException(
0818:                                "Invalid "
0819:                                        + msg
0820:                                        + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
0821:                                        + name);
0822:                    }
0823:                }
0824:            }
0825:
0826:            /**
0827:             * Checks that the given string is a valid internal class name.
0828:             * 
0829:             * @param name the string to be checked.
0830:             * @param msg a message to be used in case of error.
0831:             */
0832:            static void checkInternalName(final String name, final String msg) {
0833:                if (name == null || name.length() == 0) {
0834:                    throw new IllegalArgumentException("Invalid " + msg
0835:                            + " (must not be null or empty)");
0836:                }
0837:                if (name.charAt(0) == '[') {
0838:                    checkDesc(name, false);
0839:                } else {
0840:                    checkInternalName(name, 0, -1, msg);
0841:                }
0842:            }
0843:
0844:            /**
0845:             * Checks that the given substring is a valid internal class name.
0846:             * 
0847:             * @param name the string to be checked.
0848:             * @param start index of the first character of the identifier (inclusive).
0849:             * @param end index of the last character of the identifier (exclusive). -1
0850:             *        is equivalent to <tt>name.length()</tt> if name is not
0851:             *        <tt>null</tt>.
0852:             * @param msg a message to be used in case of error.
0853:             */
0854:            static void checkInternalName(final String name, final int start,
0855:                    final int end, final String msg) {
0856:                int max = end == -1 ? name.length() : end;
0857:                try {
0858:                    int begin = start;
0859:                    int slash;
0860:                    do {
0861:                        slash = name.indexOf('/', begin + 1);
0862:                        if (slash == -1 || slash > max) {
0863:                            slash = max;
0864:                        }
0865:                        checkIdentifier(name, begin, slash, null);
0866:                        begin = slash + 1;
0867:                    } while (slash != max);
0868:                } catch (IllegalArgumentException _) {
0869:                    throw new IllegalArgumentException(
0870:                            "Invalid "
0871:                                    + msg
0872:                                    + " (must be a fully qualified class name in internal form): "
0873:                                    + name);
0874:                }
0875:            }
0876:
0877:            /**
0878:             * Checks that the given string is a valid type descriptor.
0879:             * 
0880:             * @param desc the string to be checked.
0881:             * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
0882:             */
0883:            static void checkDesc(final String desc, final boolean canBeVoid) {
0884:                int end = checkDesc(desc, 0, canBeVoid);
0885:                if (end != desc.length()) {
0886:                    throw new IllegalArgumentException("Invalid descriptor: "
0887:                            + desc);
0888:                }
0889:            }
0890:
0891:            /**
0892:             * Checks that a the given substring is a valid type descriptor.
0893:             * 
0894:             * @param desc the string to be checked.
0895:             * @param start index of the first character of the identifier (inclusive).
0896:             * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
0897:             * @return the index of the last character of the type decriptor, plus one.
0898:             */
0899:            static int checkDesc(final String desc, final int start,
0900:                    final boolean canBeVoid) {
0901:                if (desc == null || start >= desc.length()) {
0902:                    throw new IllegalArgumentException(
0903:                            "Invalid type descriptor (must not be null or empty)");
0904:                }
0905:                int index;
0906:                switch (desc.charAt(start)) {
0907:                case 'V':
0908:                    if (canBeVoid) {
0909:                        return start + 1;
0910:                    } else {
0911:                        throw new IllegalArgumentException(
0912:                                "Invalid descriptor: " + desc);
0913:                    }
0914:                case 'Z':
0915:                case 'C':
0916:                case 'B':
0917:                case 'S':
0918:                case 'I':
0919:                case 'F':
0920:                case 'J':
0921:                case 'D':
0922:                    return start + 1;
0923:                case '[':
0924:                    index = start + 1;
0925:                    while (index < desc.length() && desc.charAt(index) == '[') {
0926:                        ++index;
0927:                    }
0928:                    if (index < desc.length()) {
0929:                        return checkDesc(desc, index, false);
0930:                    } else {
0931:                        throw new IllegalArgumentException(
0932:                                "Invalid descriptor: " + desc);
0933:                    }
0934:                case 'L':
0935:                    index = desc.indexOf(';', start);
0936:                    if (index == -1 || index - start < 2) {
0937:                        throw new IllegalArgumentException(
0938:                                "Invalid descriptor: " + desc);
0939:                    }
0940:                    try {
0941:                        checkInternalName(desc, start + 1, index, null);
0942:                    } catch (IllegalArgumentException _) {
0943:                        throw new IllegalArgumentException(
0944:                                "Invalid descriptor: " + desc);
0945:                    }
0946:                    return index + 1;
0947:                default:
0948:                    throw new IllegalArgumentException("Invalid descriptor: "
0949:                            + desc);
0950:                }
0951:            }
0952:
0953:            /**
0954:             * Checks that the given string is a valid method descriptor.
0955:             * 
0956:             * @param desc the string to be checked.
0957:             */
0958:            static void checkMethodDesc(final String desc) {
0959:                if (desc == null || desc.length() == 0) {
0960:                    throw new IllegalArgumentException(
0961:                            "Invalid method descriptor (must not be null or empty)");
0962:                }
0963:                if (desc.charAt(0) != '(' || desc.length() < 3) {
0964:                    throw new IllegalArgumentException("Invalid descriptor: "
0965:                            + desc);
0966:                }
0967:                int start = 1;
0968:                if (desc.charAt(start) != ')') {
0969:                    do {
0970:                        if (desc.charAt(start) == 'V') {
0971:                            throw new IllegalArgumentException(
0972:                                    "Invalid descriptor: " + desc);
0973:                        }
0974:                        start = checkDesc(desc, start, false);
0975:                    } while (start < desc.length() && desc.charAt(start) != ')');
0976:                }
0977:                start = checkDesc(desc, start + 1, true);
0978:                if (start != desc.length()) {
0979:                    throw new IllegalArgumentException("Invalid descriptor: "
0980:                            + desc);
0981:                }
0982:            }
0983:
0984:            /**
0985:             * Checks a class signature.
0986:             * 
0987:             * @param signature a string containing the signature that must be checked.
0988:             */
0989:            static void checkClassSignature(final String signature) {
0990:                // ClassSignature:
0991:                // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
0992:
0993:                int pos = 0;
0994:                if (getChar(signature, 0) == '<') {
0995:                    pos = checkFormalTypeParameters(signature, pos);
0996:                }
0997:                pos = checkClassTypeSignature(signature, pos);
0998:                while (getChar(signature, pos) == 'L') {
0999:                    pos = checkClassTypeSignature(signature, pos);
1000:                }
1001:                if (pos != signature.length()) {
1002:                    throw new IllegalArgumentException(signature
1003:                            + ": error at index " + pos);
1004:                }
1005:            }
1006:
1007:            /**
1008:             * Checks a method signature.
1009:             * 
1010:             * @param signature a string containing the signature that must be checked.
1011:             */
1012:            static void checkMethodSignature(final String signature) {
1013:                // MethodTypeSignature:
1014:                // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
1015:                // ^ClassTypeSignature | ^TypeVariableSignature )*
1016:
1017:                int pos = 0;
1018:                if (getChar(signature, 0) == '<') {
1019:                    pos = checkFormalTypeParameters(signature, pos);
1020:                }
1021:                pos = checkChar('(', signature, pos);
1022:                while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
1023:                    pos = checkTypeSignature(signature, pos);
1024:                }
1025:                pos = checkChar(')', signature, pos);
1026:                if (getChar(signature, pos) == 'V') {
1027:                    ++pos;
1028:                } else {
1029:                    pos = checkTypeSignature(signature, pos);
1030:                }
1031:                while (getChar(signature, pos) == '^') {
1032:                    ++pos;
1033:                    if (getChar(signature, pos) == 'L') {
1034:                        pos = checkClassTypeSignature(signature, pos);
1035:                    } else {
1036:                        pos = checkTypeVariableSignature(signature, pos);
1037:                    }
1038:                }
1039:                if (pos != signature.length()) {
1040:                    throw new IllegalArgumentException(signature
1041:                            + ": error at index " + pos);
1042:                }
1043:            }
1044:
1045:            /**
1046:             * Checks a field signature.
1047:             * 
1048:             * @param signature a string containing the signature that must be checked.
1049:             */
1050:            static void checkFieldSignature(final String signature) {
1051:                int pos = checkFieldTypeSignature(signature, 0);
1052:                if (pos != signature.length()) {
1053:                    throw new IllegalArgumentException(signature
1054:                            + ": error at index " + pos);
1055:                }
1056:            }
1057:
1058:            /**
1059:             * Checks the formal type parameters of a class or method signature.
1060:             * 
1061:             * @param signature a string containing the signature that must be checked.
1062:             * @param pos index of first character to be checked.
1063:             * @return the index of the first character after the checked part.
1064:             */
1065:            private static int checkFormalTypeParameters(
1066:                    final String signature, int pos) {
1067:                // FormalTypeParameters:
1068:                // < FormalTypeParameter+ >
1069:
1070:                pos = checkChar('<', signature, pos);
1071:                pos = checkFormalTypeParameter(signature, pos);
1072:                while (getChar(signature, pos) != '>') {
1073:                    pos = checkFormalTypeParameter(signature, pos);
1074:                }
1075:                return pos + 1;
1076:            }
1077:
1078:            /**
1079:             * Checks a formal type parameter of a class or method signature.
1080:             * 
1081:             * @param signature a string containing the signature that must be checked.
1082:             * @param pos index of first character to be checked.
1083:             * @return the index of the first character after the checked part.
1084:             */
1085:            private static int checkFormalTypeParameter(final String signature,
1086:                    int pos) {
1087:                // FormalTypeParameter:
1088:                // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
1089:
1090:                pos = checkIdentifier(signature, pos);
1091:                pos = checkChar(':', signature, pos);
1092:                if ("L[T".indexOf(getChar(signature, pos)) != -1) {
1093:                    pos = checkFieldTypeSignature(signature, pos);
1094:                }
1095:                while (getChar(signature, pos) == ':') {
1096:                    pos = checkFieldTypeSignature(signature, pos + 1);
1097:                }
1098:                return pos;
1099:            }
1100:
1101:            /**
1102:             * Checks a field type signature.
1103:             * 
1104:             * @param signature a string containing the signature that must be checked.
1105:             * @param pos index of first character to be checked.
1106:             * @return the index of the first character after the checked part.
1107:             */
1108:            private static int checkFieldTypeSignature(final String signature,
1109:                    int pos) {
1110:                // FieldTypeSignature:
1111:                // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
1112:                //
1113:                // ArrayTypeSignature:
1114:                // [ TypeSignature
1115:
1116:                switch (getChar(signature, pos)) {
1117:                case 'L':
1118:                    return checkClassTypeSignature(signature, pos);
1119:                case '[':
1120:                    return checkTypeSignature(signature, pos + 1);
1121:                default:
1122:                    return checkTypeVariableSignature(signature, pos);
1123:                }
1124:            }
1125:
1126:            /**
1127:             * Checks a class type signature.
1128:             * 
1129:             * @param signature a string containing the signature that must be checked.
1130:             * @param pos index of first character to be checked.
1131:             * @return the index of the first character after the checked part.
1132:             */
1133:            private static int checkClassTypeSignature(final String signature,
1134:                    int pos) {
1135:                // ClassTypeSignature:
1136:                // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
1137:                // TypeArguments? )* ;
1138:
1139:                pos = checkChar('L', signature, pos);
1140:                pos = checkIdentifier(signature, pos);
1141:                while (getChar(signature, pos) == '/') {
1142:                    pos = checkIdentifier(signature, pos + 1);
1143:                }
1144:                if (getChar(signature, pos) == '<') {
1145:                    pos = checkTypeArguments(signature, pos);
1146:                }
1147:                while (getChar(signature, pos) == '.') {
1148:                    pos = checkIdentifier(signature, pos + 1);
1149:                    if (getChar(signature, pos) == '<') {
1150:                        pos = checkTypeArguments(signature, pos);
1151:                    }
1152:                }
1153:                return checkChar(';', signature, pos);
1154:            }
1155:
1156:            /**
1157:             * Checks the type arguments in a class type signature.
1158:             * 
1159:             * @param signature a string containing the signature that must be checked.
1160:             * @param pos index of first character to be checked.
1161:             * @return the index of the first character after the checked part.
1162:             */
1163:            private static int checkTypeArguments(final String signature,
1164:                    int pos) {
1165:                // TypeArguments:
1166:                // < TypeArgument+ >
1167:
1168:                pos = checkChar('<', signature, pos);
1169:                pos = checkTypeArgument(signature, pos);
1170:                while (getChar(signature, pos) != '>') {
1171:                    pos = checkTypeArgument(signature, pos);
1172:                }
1173:                return pos + 1;
1174:            }
1175:
1176:            /**
1177:             * Checks a type argument in a class type signature.
1178:             * 
1179:             * @param signature a string containing the signature that must be checked.
1180:             * @param pos index of first character to be checked.
1181:             * @return the index of the first character after the checked part.
1182:             */
1183:            private static int checkTypeArgument(final String signature, int pos) {
1184:                // TypeArgument:
1185:                // * | ( ( + | - )? FieldTypeSignature )
1186:
1187:                char c = getChar(signature, pos);
1188:                if (c == '*') {
1189:                    return pos + 1;
1190:                } else if (c == '+' || c == '-') {
1191:                    pos = pos + 1;
1192:                }
1193:                return checkFieldTypeSignature(signature, pos);
1194:            }
1195:
1196:            /**
1197:             * Checks a type variable signature.
1198:             * 
1199:             * @param signature a string containing the signature that must be checked.
1200:             * @param pos index of first character to be checked.
1201:             * @return the index of the first character after the checked part.
1202:             */
1203:            private static int checkTypeVariableSignature(
1204:                    final String signature, int pos) {
1205:                // TypeVariableSignature:
1206:                // T Identifier ;
1207:
1208:                pos = checkChar('T', signature, pos);
1209:                pos = checkIdentifier(signature, pos);
1210:                return checkChar(';', signature, pos);
1211:            }
1212:
1213:            /**
1214:             * Checks a type signature.
1215:             * 
1216:             * @param signature a string containing the signature that must be checked.
1217:             * @param pos index of first character to be checked.
1218:             * @return the index of the first character after the checked part.
1219:             */
1220:            private static int checkTypeSignature(final String signature,
1221:                    int pos) {
1222:                // TypeSignature:
1223:                // Z | C | B | S | I | F | J | D | FieldTypeSignature
1224:
1225:                switch (getChar(signature, pos)) {
1226:                case 'Z':
1227:                case 'C':
1228:                case 'B':
1229:                case 'S':
1230:                case 'I':
1231:                case 'F':
1232:                case 'J':
1233:                case 'D':
1234:                    return pos + 1;
1235:                default:
1236:                    return checkFieldTypeSignature(signature, pos);
1237:                }
1238:            }
1239:
1240:            /**
1241:             * Checks an identifier.
1242:             * 
1243:             * @param signature a string containing the signature that must be checked.
1244:             * @param pos index of first character to be checked.
1245:             * @return the index of the first character after the checked part.
1246:             */
1247:            private static int checkIdentifier(final String signature, int pos) {
1248:                if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
1249:                    throw new IllegalArgumentException(signature
1250:                            + ": identifier expected at index " + pos);
1251:                }
1252:                ++pos;
1253:                while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
1254:                    ++pos;
1255:                }
1256:                return pos;
1257:            }
1258:
1259:            /**
1260:             * Checks a single character.
1261:             * 
1262:             * @param signature a string containing the signature that must be checked.
1263:             * @param pos index of first character to be checked.
1264:             * @return the index of the first character after the checked part.
1265:             */
1266:            private static int checkChar(final char c, final String signature,
1267:                    int pos) {
1268:                if (getChar(signature, pos) == c) {
1269:                    return pos + 1;
1270:                }
1271:                throw new IllegalArgumentException(signature + ": '" + c
1272:                        + "' expected at index " + pos);
1273:            }
1274:
1275:            /**
1276:             * Returns the signature car at the given index.
1277:             * 
1278:             * @param signature a signature.
1279:             * @param pos an index in signature.
1280:             * @return the character at the given index, or 0 if there is no such
1281:             *         character.
1282:             */
1283:            private static char getChar(final String signature, int pos) {
1284:                return pos < signature.length() ? signature.charAt(pos)
1285:                        : (char) 0;
1286:            }
1287:
1288:            /**
1289:             * Checks that the given label is not null. This method can also check that
1290:             * the label has been visited.
1291:             * 
1292:             * @param label the label to be checked.
1293:             * @param checkVisited <tt>true</tt> to check that the label has been
1294:             *        visited.
1295:             * @param msg a message to be used in case of error.
1296:             */
1297:            void checkLabel(final Label label, final boolean checkVisited,
1298:                    final String msg) {
1299:                if (label == null) {
1300:                    throw new IllegalArgumentException("Invalid " + msg
1301:                            + " (must not be null)");
1302:                }
1303:                if (checkVisited && labels.get(label) == null) {
1304:                    throw new IllegalArgumentException("Invalid " + msg
1305:                            + " (must be visited first)");
1306:                }
1307:            }
1308:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.