Source Code Cross Referenced for CheckMethodAdapter.java in  » IDE » tIDE » org » objectweb » 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 » IDE » tIDE » org.objectweb.asm.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * ASM: a very small and fast Java bytecode manipulation framework
003:         * Copyright (c) 2000-2005 INRIA, France Telecom
004:         * All rights reserved.
005:         *
006:         * Redistribution and use in source and binary forms, with or without
007:         * modification, are permitted provided that the following conditions
008:         * are met:
009:         * 1. Redistributions of source code must retain the above copyright
010:         *    notice, this list of conditions and the following disclaimer.
011:         * 2. Redistributions in binary form must reproduce the above copyright
012:         *    notice, this list of conditions and the following disclaimer in the
013:         *    documentation and/or other materials provided with the distribution.
014:         * 3. Neither the name of the copyright holders nor the names of its
015:         *    contributors may be used to endorse or promote products derived from
016:         *    this software without specific prior written permission.
017:         *
018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021:         * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022:         * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023:         * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024:         * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028:         * THE POSSIBILITY OF SUCH DAMAGE.
029:         */
030:        package org.objectweb.asm.util;
031:
032:        import org.objectweb.asm.AnnotationVisitor;
033:        import org.objectweb.asm.Label;
034:        import org.objectweb.asm.MethodAdapter;
035:        import org.objectweb.asm.MethodVisitor;
036:        import org.objectweb.asm.Opcodes;
037:        import org.objectweb.asm.Attribute;
038:        import org.objectweb.asm.Type;
039:
040:        import java.util.HashMap;
041:
042:        /**
043:         * A {@link MethodAdapter} that checks that its methods are properly used. More
044:         * precisely this code adapter checks each instruction individually (i.e., each
045:         * visit method checks some preconditions based <i>only</i> on its arguments -
046:         * such as the fact that the given opcode is correct for a given visit method),
047:         * but does <i>not</i> check the <i>sequence</i> of instructions. For example,
048:         * in a method whose signature is <tt>void m ()</tt>, the invalid instruction
049:         * IRETURN, or the invalid sequence IADD L2I will <i>not</i> be detected by
050:         * this code adapter.
051:         *
052:         * @author Eric Bruneton
053:         */
054:        @SuppressWarnings("unchecked")
055:        public class CheckMethodAdapter extends MethodAdapter {
056:
057:            /**
058:             * <tt>true</tt> if the visitCode method has been called.
059:             */
060:            private boolean startCode;
061:
062:            /**
063:             * <tt>true</tt> if the visitMaxs method has been called.
064:             */
065:            private boolean endCode;
066:
067:            /**
068:             * <tt>true</tt> if the visitEnd method has been called.
069:             */
070:            private boolean endMethod;
071:
072:            /**
073:             * The already visited labels. This map associate Integer values to Label
074:             * keys.
075:             */
076:            private HashMap labels;
077:
078:            /**
079:             * Code of the visit method to be used for each opcode.
080:             */
081:            private final static int[] TYPE;
082:
083:            static {
084:                String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
085:                        + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
086:                        + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
087:                        + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
088:                TYPE = new int[s.length()];
089:                for (int i = 0; i < TYPE.length; ++i) {
090:                    TYPE[i] = s.charAt(i) - 'A' - 1;
091:                }
092:            }
093:
094:            // code to generate the above string
095:            // public static void main (String[] args) {
096:            // int[] TYPE = new int[] {
097:            // 0, //NOP
098:            // 0, //ACONST_NULL
099:            // 0, //ICONST_M1
100:            // 0, //ICONST_0
101:            // 0, //ICONST_1
102:            // 0, //ICONST_2
103:            // 0, //ICONST_3
104:            // 0, //ICONST_4
105:            // 0, //ICONST_5
106:            // 0, //LCONST_0
107:            // 0, //LCONST_1
108:            // 0, //FCONST_0
109:            // 0, //FCONST_1
110:            // 0, //FCONST_2
111:            // 0, //DCONST_0
112:            // 0, //DCONST_1
113:            // 1, //BIPUSH
114:            // 1, //SIPUSH
115:            // 7, //LDC
116:            // -1, //LDC_W
117:            // -1, //LDC2_W
118:            // 2, //ILOAD
119:            // 2, //LLOAD
120:            // 2, //FLOAD
121:            // 2, //DLOAD
122:            // 2, //ALOAD
123:            // -1, //ILOAD_0
124:            // -1, //ILOAD_1
125:            // -1, //ILOAD_2
126:            // -1, //ILOAD_3
127:            // -1, //LLOAD_0
128:            // -1, //LLOAD_1
129:            // -1, //LLOAD_2
130:            // -1, //LLOAD_3
131:            // -1, //FLOAD_0
132:            // -1, //FLOAD_1
133:            // -1, //FLOAD_2
134:            // -1, //FLOAD_3
135:            // -1, //DLOAD_0
136:            // -1, //DLOAD_1
137:            // -1, //DLOAD_2
138:            // -1, //DLOAD_3
139:            // -1, //ALOAD_0
140:            // -1, //ALOAD_1
141:            // -1, //ALOAD_2
142:            // -1, //ALOAD_3
143:            // 0, //IALOAD
144:            // 0, //LALOAD
145:            // 0, //FALOAD
146:            // 0, //DALOAD
147:            // 0, //AALOAD
148:            // 0, //BALOAD
149:            // 0, //CALOAD
150:            // 0, //SALOAD
151:            // 2, //ISTORE
152:            // 2, //LSTORE
153:            // 2, //FSTORE
154:            // 2, //DSTORE
155:            // 2, //ASTORE
156:            // -1, //ISTORE_0
157:            // -1, //ISTORE_1
158:            // -1, //ISTORE_2
159:            // -1, //ISTORE_3
160:            // -1, //LSTORE_0
161:            // -1, //LSTORE_1
162:            // -1, //LSTORE_2
163:            // -1, //LSTORE_3
164:            // -1, //FSTORE_0
165:            // -1, //FSTORE_1
166:            // -1, //FSTORE_2
167:            // -1, //FSTORE_3
168:            // -1, //DSTORE_0
169:            // -1, //DSTORE_1
170:            // -1, //DSTORE_2
171:            // -1, //DSTORE_3
172:            // -1, //ASTORE_0
173:            // -1, //ASTORE_1
174:            // -1, //ASTORE_2
175:            // -1, //ASTORE_3
176:            // 0, //IASTORE
177:            // 0, //LASTORE
178:            // 0, //FASTORE
179:            // 0, //DASTORE
180:            // 0, //AASTORE
181:            // 0, //BASTORE
182:            // 0, //CASTORE
183:            // 0, //SASTORE
184:            // 0, //POP
185:            // 0, //POP2
186:            // 0, //DUP
187:            // 0, //DUP_X1
188:            // 0, //DUP_X2
189:            // 0, //DUP2
190:            // 0, //DUP2_X1
191:            // 0, //DUP2_X2
192:            // 0, //SWAP
193:            // 0, //IADD
194:            // 0, //LADD
195:            // 0, //FADD
196:            // 0, //DADD
197:            // 0, //ISUB
198:            // 0, //LSUB
199:            // 0, //FSUB
200:            // 0, //DSUB
201:            // 0, //IMUL
202:            // 0, //LMUL
203:            // 0, //FMUL
204:            // 0, //DMUL
205:            // 0, //IDIV
206:            // 0, //LDIV
207:            // 0, //FDIV
208:            // 0, //DDIV
209:            // 0, //IREM
210:            // 0, //LREM
211:            // 0, //FREM
212:            // 0, //DREM
213:            // 0, //INEG
214:            // 0, //LNEG
215:            // 0, //FNEG
216:            // 0, //DNEG
217:            // 0, //ISHL
218:            // 0, //LSHL
219:            // 0, //ISHR
220:            // 0, //LSHR
221:            // 0, //IUSHR
222:            // 0, //LUSHR
223:            // 0, //IAND
224:            // 0, //LAND
225:            // 0, //IOR
226:            // 0, //LOR
227:            // 0, //IXOR
228:            // 0, //LXOR
229:            // 8, //IINC
230:            // 0, //I2L
231:            // 0, //I2F
232:            // 0, //I2D
233:            // 0, //L2I
234:            // 0, //L2F
235:            // 0, //L2D
236:            // 0, //F2I
237:            // 0, //F2L
238:            // 0, //F2D
239:            // 0, //D2I
240:            // 0, //D2L
241:            // 0, //D2F
242:            // 0, //I2B
243:            // 0, //I2C
244:            // 0, //I2S
245:            // 0, //LCMP
246:            // 0, //FCMPL
247:            // 0, //FCMPG
248:            // 0, //DCMPL
249:            // 0, //DCMPG
250:            // 6, //IFEQ
251:            // 6, //IFNE
252:            // 6, //IFLT
253:            // 6, //IFGE
254:            // 6, //IFGT
255:            // 6, //IFLE
256:            // 6, //IF_ICMPEQ
257:            // 6, //IF_ICMPNE
258:            // 6, //IF_ICMPLT
259:            // 6, //IF_ICMPGE
260:            // 6, //IF_ICMPGT
261:            // 6, //IF_ICMPLE
262:            // 6, //IF_ACMPEQ
263:            // 6, //IF_ACMPNE
264:            // 6, //GOTO
265:            // 6, //JSR
266:            // 2, //RET
267:            // 9, //TABLESWITCH
268:            // 10, //LOOKUPSWITCH
269:            // 0, //IRETURN
270:            // 0, //LRETURN
271:            // 0, //FRETURN
272:            // 0, //DRETURN
273:            // 0, //ARETURN
274:            // 0, //RETURN
275:            // 4, //GETSTATIC
276:            // 4, //PUTSTATIC
277:            // 4, //GETFIELD
278:            // 4, //PUTFIELD
279:            // 5, //INVOKEVIRTUAL
280:            // 5, //INVOKESPECIAL
281:            // 5, //INVOKESTATIC
282:            // 5, //INVOKEINTERFACE
283:            // -1, //UNUSED
284:            // 3, //NEW
285:            // 1, //NEWARRAY
286:            // 3, //ANEWARRAY
287:            // 0, //ARRAYLENGTH
288:            // 0, //ATHROW
289:            // 3, //CHECKCAST
290:            // 3, //INSTANCEOF
291:            // 0, //MONITORENTER
292:            // 0, //MONITOREXIT
293:            // -1, //WIDE
294:            // 11, //MULTIANEWARRAY
295:            // 6, //IFNULL
296:            // 6, //IFNONNULL
297:            // -1, //GOTO_W
298:            // -1 //JSR_W
299:            // };
300:            // for (int i = 0; i < TYPE.length; ++i) {
301:            // System.out.print((char)(TYPE[i] + 1 + 'A'));
302:            // }
303:            // System.out.println();
304:            // }
305:
306:            /**
307:             * Constructs a new {@link CheckMethodAdapter} object.
308:             *
309:             * @param cv the code visitor to which this adapter must delegate calls.
310:             */
311:            public CheckMethodAdapter(final MethodVisitor cv) {
312:                super (cv);
313:                this .labels = new HashMap();
314:            }
315:
316:            public AnnotationVisitor visitAnnotation(final String desc,
317:                    final boolean visible) {
318:                checkEndMethod();
319:                checkDesc(desc, false);
320:                return new CheckAnnotationAdapter(mv.visitAnnotation(desc,
321:                        visible));
322:            }
323:
324:            public AnnotationVisitor visitAnnotationDefault() {
325:                checkEndMethod();
326:                return new CheckAnnotationAdapter(mv.visitAnnotationDefault(),
327:                        false);
328:            }
329:
330:            public AnnotationVisitor visitParameterAnnotation(
331:                    final int parameter, final String desc,
332:                    final boolean visible) {
333:                checkEndMethod();
334:                checkDesc(desc, false);
335:                return new CheckAnnotationAdapter(mv.visitParameterAnnotation(
336:                        parameter, desc, visible));
337:            }
338:
339:            public void visitAttribute(final Attribute attr) {
340:                checkEndMethod();
341:                if (attr == null) {
342:                    throw new IllegalArgumentException(
343:                            "Invalid attribute (must not be null)");
344:                }
345:                mv.visitAttribute(attr);
346:            }
347:
348:            public void visitCode() {
349:                startCode = true;
350:                mv.visitCode();
351:            }
352:
353:            public void visitFrame(final int type, final int nLocal,
354:                    final Object[] local, final int nStack, final Object[] stack) {
355:                int mLocal;
356:                int mStack;
357:                switch (type) {
358:                case Opcodes.F_NEW:
359:                case Opcodes.F_FULL:
360:                    mLocal = Integer.MAX_VALUE;
361:                    mStack = Integer.MAX_VALUE;
362:                    break;
363:
364:                case Opcodes.F_SAME:
365:                    mLocal = 0;
366:                    mStack = 0;
367:                    break;
368:
369:                case Opcodes.F_SAME1:
370:                    mLocal = 0;
371:                    mStack = 1;
372:                    break;
373:
374:                case Opcodes.F_APPEND:
375:                case Opcodes.F_CHOP:
376:                    mLocal = 3;
377:                    mStack = 0;
378:                    break;
379:
380:                default:
381:                    throw new IllegalArgumentException("Invalid frame type "
382:                            + type);
383:                }
384:
385:                if (nLocal > mLocal) {
386:                    throw new IllegalArgumentException("Invalid nLocal="
387:                            + nLocal + " for frame type " + type);
388:                }
389:                if (nStack > mStack) {
390:                    throw new IllegalArgumentException("Invalid nStack="
391:                            + nStack + " for frame type " + type);
392:                }
393:
394:                if (nLocal > 0 && (local == null || local.length < nLocal)) {
395:                    throw new IllegalArgumentException(
396:                            "Array local[] is shorter than nLocal");
397:                }
398:                if (nStack > 0 && (stack == null || stack.length < nStack)) {
399:                    throw new IllegalArgumentException(
400:                            "Array stack[] is shorter than nStack");
401:                }
402:
403:                /*
404:                 * TODO check values of the individual frames. Primitive types are
405:                 * represented by Opcodes.TOP, Opcodes.INTEGER, Opcodes.FLOAT,
406:                 * Opcodes.LONG, Opcodes.DOUBLE,Opcodes.NULL or
407:                 * Opcodes.UNINITIALIZED_THIS (long and double are represented by a
408:                 * single element). Reference types are represented by String objects,
409:                 * and uninitialized types by Label objects (this label designates the
410:                 * NEW instruction that created this uninitialized value).
411:                 */
412:
413:                mv.visitFrame(type, nLocal, local, nStack, stack);
414:            }
415:
416:            public void visitInsn(final int opcode) {
417:                checkStartCode();
418:                checkEndCode();
419:                checkOpcode(opcode, 0);
420:                mv.visitInsn(opcode);
421:            }
422:
423:            public void visitIntInsn(final int opcode, final int operand) {
424:                checkStartCode();
425:                checkEndCode();
426:                checkOpcode(opcode, 1);
427:                switch (opcode) {
428:                case Opcodes.BIPUSH:
429:                    checkSignedByte(operand, "Invalid operand");
430:                    break;
431:                case Opcodes.SIPUSH:
432:                    checkSignedShort(operand, "Invalid operand");
433:                    break;
434:                // case Constants.NEWARRAY:
435:                default:
436:                    if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
437:                        throw new IllegalArgumentException(
438:                                "Invalid operand (must be an array type code T_...): "
439:                                        + operand);
440:                    }
441:                }
442:                mv.visitIntInsn(opcode, operand);
443:            }
444:
445:            public void visitVarInsn(final int opcode, final int var) {
446:                checkStartCode();
447:                checkEndCode();
448:                checkOpcode(opcode, 2);
449:                checkUnsignedShort(var, "Invalid variable index");
450:                mv.visitVarInsn(opcode, var);
451:            }
452:
453:            public void visitTypeInsn(final int opcode, final String desc) {
454:                checkStartCode();
455:                checkEndCode();
456:                checkOpcode(opcode, 3);
457:                if (desc != null && desc.length() > 0 && desc.charAt(0) == '[') {
458:                    checkDesc(desc, false);
459:                } else {
460:                    checkInternalName(desc, "type");
461:                }
462:                if (opcode == Opcodes.NEW && desc.charAt(0) == '[') {
463:                    throw new IllegalArgumentException(
464:                            "NEW cannot be used to create arrays: " + desc);
465:                }
466:                mv.visitTypeInsn(opcode, desc);
467:            }
468:
469:            public void visitFieldInsn(final int opcode, final String owner,
470:                    final String name, final String desc) {
471:                checkStartCode();
472:                checkEndCode();
473:                checkOpcode(opcode, 4);
474:                checkInternalName(owner, "owner");
475:                checkIdentifier(name, "name");
476:                checkDesc(desc, false);
477:                mv.visitFieldInsn(opcode, owner, name, desc);
478:            }
479:
480:            public void visitMethodInsn(final int opcode, final String owner,
481:                    final String name, final String desc) {
482:                checkStartCode();
483:                checkEndCode();
484:                checkOpcode(opcode, 5);
485:                checkMethodIdentifier(name, "name");
486:                if (!name.equals("clone")) {
487:                    // In JDK1.5, clone method can be called on array class descriptors
488:                    checkInternalName(owner, "owner");
489:                }
490:                checkMethodDesc(desc);
491:                mv.visitMethodInsn(opcode, owner, name, desc);
492:            }
493:
494:            public void visitJumpInsn(final int opcode, final Label label) {
495:                checkStartCode();
496:                checkEndCode();
497:                checkOpcode(opcode, 6);
498:                checkLabel(label, false, "label");
499:                mv.visitJumpInsn(opcode, label);
500:            }
501:
502:            public void visitLabel(final Label label) {
503:                checkStartCode();
504:                checkEndCode();
505:                checkLabel(label, false, "label");
506:                if (labels.get(label) != null) {
507:                    throw new IllegalArgumentException("Already visited label");
508:                } else {
509:                    labels.put(label, new Integer(labels.size()));
510:                }
511:                mv.visitLabel(label);
512:            }
513:
514:            public void visitLdcInsn(final Object cst) {
515:                checkStartCode();
516:                checkEndCode();
517:                if (!(cst instanceof  Type)) {
518:                    checkConstant(cst);
519:                }
520:                mv.visitLdcInsn(cst);
521:            }
522:
523:            public void visitIincInsn(final int var, final int increment) {
524:                checkStartCode();
525:                checkEndCode();
526:                checkUnsignedShort(var, "Invalid variable index");
527:                checkSignedShort(increment, "Invalid increment");
528:                mv.visitIincInsn(var, increment);
529:            }
530:
531:            public void visitTableSwitchInsn(final int min, final int max,
532:                    final Label dflt, final Label labels[]) {
533:                checkStartCode();
534:                checkEndCode();
535:                if (max < min) {
536:                    throw new IllegalArgumentException("Max = " + max
537:                            + " must be greater than or equal to min = " + min);
538:                }
539:                checkLabel(dflt, false, "default label");
540:                if (labels == null || labels.length != max - min + 1) {
541:                    throw new IllegalArgumentException(
542:                            "There must be max - min + 1 labels");
543:                }
544:                for (int i = 0; i < labels.length; ++i) {
545:                    checkLabel(labels[i], false, "label at index " + i);
546:                }
547:                mv.visitTableSwitchInsn(min, max, dflt, labels);
548:            }
549:
550:            public void visitLookupSwitchInsn(final Label dflt,
551:                    final int keys[], final Label labels[]) {
552:                checkEndCode();
553:                checkStartCode();
554:                checkLabel(dflt, false, "default label");
555:                if (keys == null || labels == null
556:                        || keys.length != labels.length) {
557:                    throw new IllegalArgumentException(
558:                            "There must be the same number of keys and labels");
559:                }
560:                for (int i = 0; i < labels.length; ++i) {
561:                    checkLabel(labels[i], false, "label at index " + i);
562:                }
563:                mv.visitLookupSwitchInsn(dflt, keys, labels);
564:            }
565:
566:            public void visitMultiANewArrayInsn(final String desc,
567:                    final int dims) {
568:                checkStartCode();
569:                checkEndCode();
570:                checkDesc(desc, false);
571:                if (desc.charAt(0) != '[') {
572:                    throw new IllegalArgumentException(
573:                            "Invalid descriptor (must be an array type descriptor): "
574:                                    + desc);
575:                }
576:                if (dims < 1) {
577:                    throw new IllegalArgumentException(
578:                            "Invalid dimensions (must be greater than 0): "
579:                                    + dims);
580:                }
581:                if (dims > desc.lastIndexOf('[') + 1) {
582:                    throw new IllegalArgumentException(
583:                            "Invalid dimensions (must not be greater than dims(desc)): "
584:                                    + dims);
585:                }
586:                mv.visitMultiANewArrayInsn(desc, dims);
587:            }
588:
589:            public void visitTryCatchBlock(final Label start, final Label end,
590:                    final Label handler, final String type) {
591:                checkStartCode();
592:                checkEndCode();
593:                if (type != null) {
594:                    checkInternalName(type, "type");
595:                }
596:                mv.visitTryCatchBlock(start, end, handler, type);
597:            }
598:
599:            public void visitLocalVariable(final String name,
600:                    final String desc, final String signature,
601:                    final Label start, final Label end, final int index) {
602:                checkStartCode();
603:                checkEndCode();
604:                checkIdentifier(name, "name");
605:                checkDesc(desc, false);
606:                checkLabel(start, true, "start label");
607:                checkLabel(end, true, "end label");
608:                checkUnsignedShort(index, "Invalid variable index");
609:                int s = ((Integer) labels.get(start)).intValue();
610:                int e = ((Integer) labels.get(end)).intValue();
611:                if (e < s) {
612:                    throw new IllegalArgumentException(
613:                            "Invalid start and end labels (end must be greater than start)");
614:                }
615:                mv.visitLocalVariable(name, desc, signature, start, end, index);
616:            }
617:
618:            public void visitLineNumber(final int line, final Label start) {
619:                checkStartCode();
620:                checkEndCode();
621:                checkUnsignedShort(line, "Invalid line number");
622:                checkLabel(start, true, "start label");
623:                mv.visitLineNumber(line, start);
624:            }
625:
626:            public void visitMaxs(final int maxStack, final int maxLocals) {
627:                checkStartCode();
628:                checkEndCode();
629:                endCode = true;
630:                checkUnsignedShort(maxStack, "Invalid max stack");
631:                checkUnsignedShort(maxLocals, "Invalid max locals");
632:                mv.visitMaxs(maxStack, maxLocals);
633:            }
634:
635:            public void visitEnd() {
636:                checkEndMethod();
637:                endMethod = true;
638:                mv.visitEnd();
639:            }
640:
641:            // -------------------------------------------------------------------------
642:
643:            /**
644:             * Checks that the visitCode method has been called.
645:             */
646:            void checkStartCode() {
647:                if (!startCode) {
648:                    throw new IllegalStateException(
649:                            "Cannot visit instructions before visitCode has been called.");
650:                }
651:            }
652:
653:            /**
654:             * Checks that the visitMaxs method has not been called.
655:             */
656:            void checkEndCode() {
657:                if (endCode) {
658:                    throw new IllegalStateException(
659:                            "Cannot visit instructions after visitMaxs has been called.");
660:                }
661:            }
662:
663:            /**
664:             * Checks that the visitEnd method has not been called.
665:             */
666:            void checkEndMethod() {
667:                if (endMethod) {
668:                    throw new IllegalStateException(
669:                            "Cannot visit elements after visitEnd has been called.");
670:                }
671:            }
672:
673:            /**
674:             * Checks that the type of the given opcode is equal to the given type.
675:             *
676:             * @param opcode the opcode to be checked.
677:             * @param type the expected opcode type.
678:             */
679:            static void checkOpcode(final int opcode, final int type) {
680:                if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
681:                    throw new IllegalArgumentException("Invalid opcode: "
682:                            + opcode);
683:                }
684:            }
685:
686:            /**
687:             * Checks that the given value is a signed byte.
688:             *
689:             * @param value the value to be checked.
690:             * @param msg an message to be used in case of error.
691:             */
692:            static void checkSignedByte(final int value, final String msg) {
693:                if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
694:                    throw new IllegalArgumentException(msg
695:                            + " (must be a signed byte): " + value);
696:                }
697:            }
698:
699:            /**
700:             * Checks that the given value is a signed short.
701:             *
702:             * @param value the value to be checked.
703:             * @param msg an message to be used in case of error.
704:             */
705:            static void checkSignedShort(final int value, final String msg) {
706:                if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
707:                    throw new IllegalArgumentException(msg
708:                            + " (must be a signed short): " + value);
709:                }
710:            }
711:
712:            /**
713:             * Checks that the given value is an unsigned short.
714:             *
715:             * @param value the value to be checked.
716:             * @param msg an message to be used in case of error.
717:             */
718:            static void checkUnsignedShort(final int value, final String msg) {
719:                if (value < 0 || value > 65535) {
720:                    throw new IllegalArgumentException(msg
721:                            + " (must be an unsigned short): " + value);
722:                }
723:            }
724:
725:            /**
726:             * Checks that the given value is an {@link Integer}, a{@link Float}, a
727:             * {@link Long}, a {@link Double} or a {@link String}.
728:             *
729:             * @param cst the value to be checked.
730:             */
731:            static void checkConstant(final Object cst) {
732:                if (!(cst instanceof  Integer) && !(cst instanceof  Float)
733:                        && !(cst instanceof  Long) && !(cst instanceof  Double)
734:                        && !(cst instanceof  String)) {
735:                    throw new IllegalArgumentException("Invalid constant: "
736:                            + cst);
737:                }
738:            }
739:
740:            /**
741:             * Checks that the given string is a valid Java identifier.
742:             *
743:             * @param name the string to be checked.
744:             * @param msg a message to be used in case of error.
745:             */
746:            static void checkIdentifier(final String name, final String msg) {
747:                checkIdentifier(name, 0, -1, msg);
748:            }
749:
750:            /**
751:             * Checks that the given substring is a valid Java identifier.
752:             *
753:             * @param name the string to be checked.
754:             * @param start index of the first character of the identifier (inclusive).
755:             * @param end index of the last character of the identifier (exclusive). -1
756:             *        is equivalent to <tt>name.length()</tt> if name is not
757:             *        <tt>null</tt>.
758:             * @param msg a message to be used in case of error.
759:             */
760:            static void checkIdentifier(final String name, final int start,
761:                    final int end, final String msg) {
762:                if (name == null
763:                        || (end == -1 ? name.length() <= start : end <= start)) {
764:                    throw new IllegalArgumentException("Invalid " + msg
765:                            + " (must not be null or empty)");
766:                }
767:                if (!Character.isJavaIdentifierStart(name.charAt(start))) {
768:                    throw new IllegalArgumentException("Invalid " + msg
769:                            + " (must be a valid Java identifier): " + name);
770:                }
771:                int max = end == -1 ? name.length() : end;
772:                for (int i = start + 1; i < max; ++i) {
773:                    if (!Character.isJavaIdentifierPart(name.charAt(i))) {
774:                        throw new IllegalArgumentException("Invalid " + msg
775:                                + " (must be a valid Java identifier): " + name);
776:                    }
777:                }
778:            }
779:
780:            /**
781:             * Checks that the given string is a valid Java identifier or is equal to
782:             * '&lt;init&gt;' or '&lt;clinit&gt;'.
783:             *
784:             * @param name the string to be checked.
785:             * @param msg a message to be used in case of error.
786:             */
787:            static void checkMethodIdentifier(final String name,
788:                    final String msg) {
789:                if (name == null || name.length() == 0) {
790:                    throw new IllegalArgumentException("Invalid " + msg
791:                            + " (must not be null or empty)");
792:                }
793:                if (name.equals("<init>") || name.equals("<clinit>")) {
794:                    return;
795:                }
796:                if (!Character.isJavaIdentifierStart(name.charAt(0))) {
797:                    throw new IllegalArgumentException(
798:                            "Invalid "
799:                                    + msg
800:                                    + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
801:                                    + name);
802:                }
803:                for (int i = 1; i < name.length(); ++i) {
804:                    if (!Character.isJavaIdentifierPart(name.charAt(i))) {
805:                        throw new IllegalArgumentException(
806:                                "Invalid "
807:                                        + msg
808:                                        + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
809:                                        + name);
810:                    }
811:                }
812:            }
813:
814:            /**
815:             * Checks that the given string is a valid internal class name.
816:             *
817:             * @param name the string to be checked.
818:             * @param msg a message to be used in case of error.
819:             */
820:            static void checkInternalName(final String name, final String msg) {
821:                checkInternalName(name, 0, -1, msg);
822:            }
823:
824:            /**
825:             * Checks that the given substring is a valid internal class name.
826:             *
827:             * @param name the string to be checked.
828:             * @param start index of the first character of the identifier (inclusive).
829:             * @param end index of the last character of the identifier (exclusive). -1
830:             *        is equivalent to <tt>name.length()</tt> if name is not
831:             *        <tt>null</tt>.
832:             * @param msg a message to be used in case of error.
833:             */
834:            static void checkInternalName(final String name, final int start,
835:                    final int end, final String msg) {
836:                if (name == null || name.length() == 0) {
837:                    throw new IllegalArgumentException("Invalid " + msg
838:                            + " (must not be null or empty)");
839:                }
840:                int max = end == -1 ? name.length() : end;
841:                try {
842:                    int begin = start;
843:                    int slash;
844:                    do {
845:                        slash = name.indexOf('/', begin + 1);
846:                        if (slash == -1 || slash > max) {
847:                            slash = max;
848:                        }
849:                        checkIdentifier(name, begin, slash, null);
850:                        begin = slash + 1;
851:                    } while (slash != max);
852:                } catch (IllegalArgumentException _) {
853:                    throw new IllegalArgumentException(
854:                            "Invalid "
855:                                    + msg
856:                                    + " (must be a fully qualified class name in internal form): "
857:                                    + name);
858:                }
859:            }
860:
861:            /**
862:             * Checks that the given string is a valid type descriptor.
863:             *
864:             * @param desc the string to be checked.
865:             * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
866:             */
867:            static void checkDesc(final String desc, final boolean canBeVoid) {
868:                int end = checkDesc(desc, 0, canBeVoid);
869:                if (end != desc.length()) {
870:                    throw new IllegalArgumentException("Invalid descriptor: "
871:                            + desc);
872:                }
873:            }
874:
875:            /**
876:             * Checks that a the given substring is a valid type descriptor.
877:             *
878:             * @param desc the string to be checked.
879:             * @param start index of the first character of the identifier (inclusive).
880:             * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
881:             * @return the index of the last character of the type decriptor, plus one.
882:             */
883:            static int checkDesc(final String desc, final int start,
884:                    final boolean canBeVoid) {
885:                if (desc == null || start >= desc.length()) {
886:                    throw new IllegalArgumentException(
887:                            "Invalid type descriptor (must not be null or empty)");
888:                }
889:                int index;
890:                switch (desc.charAt(start)) {
891:                case 'V':
892:                    if (canBeVoid) {
893:                        return start + 1;
894:                    } else {
895:                        throw new IllegalArgumentException(
896:                                "Invalid descriptor: " + desc);
897:                    }
898:                case 'Z':
899:                case 'C':
900:                case 'B':
901:                case 'S':
902:                case 'I':
903:                case 'F':
904:                case 'J':
905:                case 'D':
906:                    return start + 1;
907:                case '[':
908:                    index = start + 1;
909:                    while (index < desc.length() && desc.charAt(index) == '[') {
910:                        ++index;
911:                    }
912:                    if (index < desc.length()) {
913:                        return checkDesc(desc, index, false);
914:                    } else {
915:                        throw new IllegalArgumentException(
916:                                "Invalid descriptor: " + desc);
917:                    }
918:                case 'L':
919:                    index = desc.indexOf(';', start);
920:                    if (index == -1 || index - start < 2) {
921:                        throw new IllegalArgumentException(
922:                                "Invalid descriptor: " + desc);
923:                    }
924:                    try {
925:                        checkInternalName(desc, start + 1, index, null);
926:                    } catch (IllegalArgumentException _) {
927:                        throw new IllegalArgumentException(
928:                                "Invalid descriptor: " + desc);
929:                    }
930:                    return index + 1;
931:                default:
932:                    throw new IllegalArgumentException("Invalid descriptor: "
933:                            + desc);
934:                }
935:            }
936:
937:            /**
938:             * Checks that the given string is a valid method descriptor.
939:             *
940:             * @param desc the string to be checked.
941:             */
942:            static void checkMethodDesc(final String desc) {
943:                if (desc == null || desc.length() == 0) {
944:                    throw new IllegalArgumentException(
945:                            "Invalid method descriptor (must not be null or empty)");
946:                }
947:                if (desc.charAt(0) != '(' || desc.length() < 3) {
948:                    throw new IllegalArgumentException("Invalid descriptor: "
949:                            + desc);
950:                }
951:                int start = 1;
952:                if (desc.charAt(start) != ')') {
953:                    do {
954:                        if (desc.charAt(start) == 'V') {
955:                            throw new IllegalArgumentException(
956:                                    "Invalid descriptor: " + desc);
957:                        }
958:                        start = checkDesc(desc, start, false);
959:                    } while (start < desc.length() && desc.charAt(start) != ')');
960:                }
961:                start = checkDesc(desc, start + 1, true);
962:                if (start != desc.length()) {
963:                    throw new IllegalArgumentException("Invalid descriptor: "
964:                            + desc);
965:                }
966:            }
967:
968:            /**
969:             * Checks that the given label is not null. This method can also check that
970:             * the label has been visited.
971:             *
972:             * @param label the label to be checked.
973:             * @param checkVisited <tt>true</tt> to check that the label has been
974:             *        visited.
975:             * @param msg a message to be used in case of error.
976:             */
977:            void checkLabel(final Label label, final boolean checkVisited,
978:                    final String msg) {
979:                if (label == null) {
980:                    throw new IllegalArgumentException("Invalid " + msg
981:                            + " (must not be null)");
982:                }
983:                if (checkVisited && labels.get(label) == null) {
984:                    throw new IllegalArgumentException("Invalid " + msg
985:                            + " (must be visited first)");
986:                }
987:            }
988:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.