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