Source Code Cross Referenced for ByteCodeUtil.java in  » Net » Terracotta » com » tc » object » bytecode » 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.object.bytecode 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003:         * notice. All rights reserved.
004:         */
005:        package com.tc.object.bytecode;
006:
007:        import com.tc.asm.MethodVisitor;
008:        import com.tc.asm.Opcodes;
009:        import com.tc.asm.Type;
010:        import com.tc.object.ObjectID;
011:        import com.tc.util.Assert;
012:
013:        import java.io.ByteArrayOutputStream;
014:        import java.io.IOException;
015:        import java.io.InputStream;
016:        import java.lang.reflect.Modifier;
017:        import java.util.ArrayList;
018:        import java.util.Arrays;
019:        import java.util.Collections;
020:        import java.util.HashSet;
021:        import java.util.List;
022:        import java.util.Set;
023:
024:        /**
025:         * Utility methods for working with byte code.
026:         */
027:        public class ByteCodeUtil implements  Opcodes {
028:            private static final String AUTOLOCK_PREFIX = "@";
029:            private static final String NAMED_LOCK_PREFIX = "^";
030:            private static final String LITERAL_LOCK_PREFIX = "#";
031:
032:            public static final String TC_FIELD_PREFIX = "$__tc_";
033:            public static final String TC_METHOD_PREFIX = "__tc_";
034:            public static final String METHOD_RENAME_PREFIX = TC_METHOD_PREFIX
035:                    + "wrapped_";
036:            public static final String SYNC_METHOD_RENAME_PREFIX = ByteCodeUtil.METHOD_RENAME_PREFIX
037:                    + "sync_";
038:            public static final String DMI_METHOD_RENAME_PREFIX = TC_METHOD_PREFIX
039:                    + "dmi_";
040:
041:            public static final String VALUES_GETTER = TC_METHOD_PREFIX
042:                    + "getallfields";
043:            public static final String VALUES_GETTER_DESCRIPTION = "(Ljava/util/Map;)V";
044:            public static final String VALUES_SETTER = TC_METHOD_PREFIX
045:                    + "setfield";
046:            public static final String VALUES_SETTER_DESCRIPTION = "(Ljava/lang/String;Ljava/lang/Object;)V";
047:            public static final String MANAGED_VALUES_GETTER = TC_METHOD_PREFIX
048:                    + "getmanagedfield";
049:            public static final String MANAGED_VALUES_GETTER_DESCRIPTION = "(Ljava/lang/String;)Ljava/lang/Object;";
050:            public static final String MANAGED_VALUES_SETTER = TC_METHOD_PREFIX
051:                    + "setmanagedfield";
052:
053:            public static final String MANAGEABLE_CLASS = "com/tc/object/bytecode/Manageable";
054:            public static final String MANAGEABLE_TYPE = "L" + MANAGEABLE_CLASS
055:                    + ";";
056:
057:            public static final String TRANSPARENT_ACCESS_CLASS = "com/tc/object/bytecode/TransparentAccess";
058:            public static final String TRANSPARENT_ACCESS_TYPE = "L"
059:                    + TRANSPARENT_ACCESS_CLASS + ";";
060:
061:            public static final String NAMEDCLASSLOADER_CLASS = "com/tc/object/loaders/NamedClassLoader";
062:            public static final String NAMEDCLASSLOADER_TYPE = "L"
063:                    + NAMEDCLASSLOADER_CLASS + ";";
064:
065:            public static final String WEBAPPCONFIG_CLASS = "com/terracotta/session/WebAppConfig";
066:            public static final String WEBAPPCONFIG_TYPE = "L"
067:                    + WEBAPPCONFIG_CLASS + ";";
068:
069:            /**
070:             * Given a set of existing interfaces, add some more (without duplicates)
071:             * @param existing The existing interfaces
072:             * @param toAdd The interfaces to add
073:             * @return A set of interfaces containing all of existing and toAdd with no dups
074:             */
075:            public static String[] addInterfaces(String[] existing,
076:                    String[] toAdd) {
077:                if (existing == null) {
078:                    return toAdd;
079:                }
080:                if (toAdd == null) {
081:                    return existing;
082:                }
083:
084:                List newList = new ArrayList(Arrays.asList(existing));
085:                Set existingAsSet = Collections.unmodifiableSet(new HashSet(
086:                        newList));
087:
088:                for (int i = 0, n = toAdd.length; i < n; i++) {
089:                    if (!existingAsSet.contains(toAdd[i])) {
090:                        newList.add(toAdd[i]);
091:                    }
092:                }
093:
094:                return (String[]) newList.toArray(new String[newList.size()]);
095:            }
096:
097:            /**
098:             * Check whether the type is a primitve
099:             * @param t The ASM type
100:             * @return True if primitive
101:             */
102:            public static boolean isPrimitive(Type t) {
103:                final int sort = t.getSort();
104:                switch (sort) {
105:                case Type.BOOLEAN:
106:                case Type.BYTE:
107:                case Type.CHAR:
108:                case Type.DOUBLE:
109:                case Type.FLOAT:
110:                case Type.INT:
111:                case Type.LONG:
112:                case Type.SHORT:
113:                    return true;
114:                default:
115:                    return false;
116:                }
117:
118:                // unreachable
119:            }
120:
121:            /**
122:             * Map from primite type to wrapper class type
123:             * @param sort Kind of primitve type as in {@link com.tc.asm.Type#getSort()}
124:             * @return Wrapper class name, like "java/lang/Boolean"
125:             */
126:            public static String sortToWrapperName(int sort) {
127:                switch (sort) {
128:                case Type.BOOLEAN: // '\001'
129:                    return "java/lang/Boolean";
130:
131:                case Type.CHAR: // '\002'
132:                    return "java/lang/Character";
133:
134:                case Type.BYTE: // '\003'
135:                    return "java/lang/Byte";
136:
137:                case Type.SHORT: // '\004'
138:                    return "java/lang/Short";
139:
140:                case Type.INT: // '\005'
141:                    return "java/lang/Integer";
142:
143:                case Type.FLOAT: // '\006'
144:                    return "java/lang/Float";
145:
146:                case Type.LONG: // '\007'
147:                    return "java/lang/Long";
148:
149:                case Type.DOUBLE: // '\b'
150:                    return "java/lang/Double";
151:                default:
152:                    throw new AssertionError();
153:                }
154:
155:            }
156:
157:            /**
158:             * Translate type code to type name
159:             * @param typeCode Code from bytecode like B, C, etc
160:             * @return Primitive type name: "byte", "char", etc
161:             */
162:            public static String codeToName(String typeCode) {
163:                if ((typeCode == null) || (typeCode.length() != 1)) {
164:                    throw new IllegalArgumentException("invalid type code: "
165:                            + typeCode);
166:                }
167:                char code = typeCode.charAt(0);
168:
169:                switch (code) {
170:                case 'B': {
171:                    return "byte";
172:                }
173:                case 'C': {
174:                    return "char";
175:                }
176:                case 'D': {
177:                    return "double";
178:                }
179:                case 'F': {
180:                    return "float";
181:                }
182:                case 'I': {
183:                    return "int";
184:                }
185:                case 'J': {
186:                    return "long";
187:                }
188:                case 'S': {
189:                    return "short";
190:                }
191:                case 'Z': {
192:                    return "boolean";
193:                }
194:                default: {
195:                    throw new IllegalArgumentException("unknown code: " + code);
196:                }
197:
198:                    // unreachable
199:                }
200:            }
201:
202:            /**
203:             * Determine whether a lock is an autolock based on its name
204:             * @param lockName The lock name
205:             * @return True if an autolock
206:             */
207:            public static boolean isAutolockName(String lockName) {
208:                return lockName == null ? false : lockName
209:                        .startsWith(AUTOLOCK_PREFIX);
210:            }
211:
212:            /**
213:             * Get lock ID from autolock name
214:             * @param lockName The lock name
215:             * @return Lock ID
216:             * @throws IllegalArgumentException If not an autolock
217:             */
218:            public static long objectIdFromLockName(String lockName) {
219:                if (lockName == null || (!lockName.startsWith(AUTOLOCK_PREFIX))) {
220:                    // make formatter sane
221:                    throw new IllegalArgumentException("not an autolock name: "
222:                            + lockName);
223:                }
224:                return Long.valueOf(
225:                        lockName.substring(AUTOLOCK_PREFIX.length()))
226:                        .longValue();
227:
228:            }
229:
230:            /**
231:             * Determine whether a field is synthetic
232:             * @param fieldName The field name
233:             * @return True if synthetic
234:             */
235:            public static boolean isSynthetic(String fieldName) {
236:                return fieldName.indexOf("$") >= 0;
237:            }
238:
239:            /**
240:             * Determine whether a field is synthetic and was added by Terracotta
241:             * @param fieldName The field name
242:             * @return True if synthetic and added by Terracotta
243:             */
244:            public static boolean isTCSynthetic(String fieldName) {
245:                return fieldName.startsWith(TC_FIELD_PREFIX)
246:                        || isParent(fieldName);
247:            }
248:
249:            /** 
250:             * Determine whether an access modifier code indicates synthetic
251:             * @param access Access modifier code
252:             * @return True if synthetic flag is set
253:             */
254:            public static boolean isSynthetic(int access) {
255:                return (ACC_SYNTHETIC & access) > 0;
256:            }
257:
258:            /**
259:             * Check whether the field name indicates that this is an inner classes synthetic
260:             * field referring to the parent "this" reference.  
261:             * @param fieldName The field name
262:             * @return True if this field refers to the parent this
263:             */
264:            public static boolean isParent(String fieldName) {
265:                return fieldName.matches("^this\\$\\d+$");
266:
267:                // return SERIALIZATION_UTIL.isParent(fieldName);
268:            }
269:
270:            /**
271:             * Add instruction to retrieve "this" from the local vars and load onto the stack
272:             * @param c The current method visitor
273:             */
274:            public static void pushThis(MethodVisitor c) {
275:                c.visitVarInsn(ALOAD, 0);
276:            }
277:
278:            /**
279:             * Add instruction to retrieve specified field in the object on the stack and replace
280:             * with the field value.
281:             * @param c Current method visitor
282:             * @param className The field class
283:             * @param fieldName The field name
284:             * @param description The field type
285:             */
286:            public static void pushInstanceVariable(MethodVisitor c,
287:                    String className, String fieldName, String description) {
288:                c.visitFieldInsn(GETFIELD, className, fieldName, description);
289:            }
290:
291:            /**
292:             * Add instructions to convert the local variables typed with parameters into an array 
293:             * assuming values start at local variable offset of 1
294:             * @param c Method visitor
295:             * @param parameters Paramater to convert
296:             */
297:            public static void createParametersToArrayByteCode(MethodVisitor c,
298:                    Type[] parameters) {
299:                createParametersToArrayByteCode(c, parameters, 1);
300:            }
301:
302:            /**
303:             * Add instructions to convert the parameters into an array
304:             * @param c Method visitor
305:             * @param parameters Paramater types to convert
306:             * @param offset Offset into local variables for values
307:             */
308:            public static void createParametersToArrayByteCode(MethodVisitor c,
309:                    Type[] parameters, int offset) {
310:                c.visitLdcInsn(new Integer(parameters.length));
311:                c.visitTypeInsn(ANEWARRAY, "java/lang/Object");
312:                for (int i = 0; i < parameters.length; i++) {
313:                    c.visitInsn(DUP);
314:                    c.visitLdcInsn(new Integer(i));
315:                    addTypeSpecificParameterLoad(c, parameters[i], offset);
316:                    c.visitInsn(AASTORE);
317:                    offset += parameters[i].getSize();
318:                }
319:            }
320:
321:            /**
322:             * Add instructions to load type-specific value from local variable onto stack.  Primitve
323:             * values are wrapped into their wrapper object.
324:             * @param c Method visitor
325:             * @param type The type of the variable
326:             * @param offset The local variable offset
327:             */
328:            public static void addTypeSpecificParameterLoad(MethodVisitor c,
329:                    Type type, int offset) {
330:
331:                switch (type.getSort()) {
332:                case Type.ARRAY:
333:                case Type.OBJECT:
334:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
335:                    break;
336:                case Type.BOOLEAN:
337:                    c.visitTypeInsn(NEW, "java/lang/Boolean");
338:                    c.visitInsn(DUP);
339:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
340:                    c.visitMethodInsn(INVOKESPECIAL, "java/lang/Boolean",
341:                            "<init>", "(Z)V");
342:                    break;
343:                case Type.BYTE:
344:                    c.visitTypeInsn(NEW, "java/lang/Byte");
345:                    c.visitInsn(DUP);
346:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
347:                    c.visitMethodInsn(INVOKESPECIAL, "java/lang/Byte",
348:                            "<init>", "(B)V");
349:                    break;
350:                case Type.CHAR:
351:                    c.visitTypeInsn(NEW, "java/lang/Character");
352:                    c.visitInsn(DUP);
353:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
354:                    c.visitMethodInsn(INVOKESPECIAL, "java/lang/Character",
355:                            "<init>", "(C)V");
356:                    break;
357:                case Type.DOUBLE:
358:                    c.visitTypeInsn(NEW, "java/lang/Double");
359:                    c.visitInsn(DUP);
360:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
361:                    c.visitMethodInsn(INVOKESPECIAL, "java/lang/Double",
362:                            "<init>", "(D)V");
363:                    break;
364:                case Type.FLOAT:
365:                    c.visitTypeInsn(NEW, "java/lang/Float");
366:                    c.visitInsn(DUP);
367:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
368:                    c.visitMethodInsn(INVOKESPECIAL, "java/lang/Float",
369:                            "<init>", "(F)V");
370:                    break;
371:                case Type.INT:
372:                    c.visitTypeInsn(NEW, "java/lang/Integer");
373:                    c.visitInsn(DUP);
374:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
375:                    c.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer",
376:                            "<init>", "(I)V");
377:                    break;
378:                case Type.LONG:
379:                    c.visitTypeInsn(NEW, "java/lang/Long");
380:                    c.visitInsn(DUP);
381:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
382:                    c.visitMethodInsn(INVOKESPECIAL, "java/lang/Long",
383:                            "<init>", "(J)V");
384:                    break;
385:                case Type.SHORT:
386:                    c.visitTypeInsn(NEW, "java/lang/Short");
387:                    c.visitInsn(DUP);
388:                    c.visitVarInsn(type.getOpcode(ILOAD), offset);
389:                    c.visitMethodInsn(INVOKESPECIAL, "java/lang/Short",
390:                            "<init>", "(S)V");
391:                    break;
392:                default:
393:                    throw new AssertionError("can't happen:" + type);
394:                }
395:            }
396:
397:            /**
398:             * Add instructions to load method args into the stack
399:             * @param callingMethodModifier Calling method modifier
400:             * @param desc Method descriptor
401:             * @param c Current method visitor
402:             */
403:            public static void pushMethodArguments(int callingMethodModifier,
404:                    String desc, MethodVisitor c) {
405:                int localVariableOffset = getLocalVariableOffset(callingMethodModifier);
406:                Type[] args = Type.getArgumentTypes(desc);
407:
408:                int pos = 0;
409:                for (int i = 0; i < args.length; i++) {
410:                    c.visitVarInsn(args[i].getOpcode(ILOAD), pos
411:                            + localVariableOffset);
412:                    pos += args[i].getSize();
413:                }
414:            }
415:
416:            /**
417:             * Get offset of first local variable after method args
418:             * @param callingMethodModifier Calling method modifier
419:             * @param desc Method descriptor
420:             * @return First local variable offset
421:             */
422:            public static int getFirstLocalVariableOffset(
423:                    int callingMethodModifier, String desc) {
424:                int localVariableOffset = getLocalVariableOffset(callingMethodModifier);
425:                Type[] args = Type.getArgumentTypes(desc);
426:                for (int i = 0; i < args.length; i++) {
427:                    localVariableOffset += args[i].getSize();
428:                }
429:                return localVariableOffset;
430:            }
431:
432:            /**
433:             * Push this (if not static) and all method args onto stack
434:             * @param callingMethodModifier Calling method modifier
435:             * @param desc Method descriptor
436:             * @param c Calling method visitor
437:             */
438:            public static void prepareStackForMethodCall(
439:                    int callingMethodModifier, String desc, MethodVisitor c) {
440:                if (!Modifier.isStatic(callingMethodModifier)) {
441:                    pushThis(c);
442:                }
443:                pushMethodArguments(callingMethodModifier, desc, c);
444:            }
445:
446:            /**
447:             * Returns 0 if the method is static. 1 If the method is not.
448:             * @param methodModifier
449:             * @return 0 if static, 1 if not
450:             */
451:            public static int getLocalVariableOffset(int methodModifier) {
452:                return Modifier.isStatic(methodModifier) ? 0 : 1;
453:            }
454:
455:            /**
456:             * Get volatile lock name
457:             * @param id Object identifier
458:             * @param field Volatile field
459:             * @return Lock name
460:             */
461:            public static String generateVolatileLockName(ObjectID id,
462:                    String fieldName) {
463:                Assert.assertNotNull(id);
464:                return AUTOLOCK_PREFIX + id.toLong() + fieldName;
465:            }
466:
467:            /**
468:             * Get auto lock name for object identifier
469:             * @param id Identifier
470:             * @return Auto lock name
471:             */
472:            public static String generateAutolockName(ObjectID id) {
473:                Assert.assertNotNull(id);
474:                return generateAutolockName(id.toLong());
475:            }
476:
477:            /**
478:             * Get named lock name for the lock object
479:             * @param obj Lock object
480:             * @return Named lock name
481:             */
482:            public static String generateNamedLockName(Object obj) {
483:                Assert.assertNotNull(obj);
484:                return NAMED_LOCK_PREFIX + obj;
485:            }
486:
487:            /**
488:             * The first argument should be "(new LiteralValues()).valueFor(obj)", but I didn't want to slurp in a whole mess of
489:             * classes into the boot jar by including LiteralValues. It's gross, but ManagerImpl just makes the call itself.
490:             * @param literalValuesValueFor Literal value code
491:             * @param obj The lock object
492:             */
493:            public static String generateLiteralLockName(
494:                    int literalValuesValueFor, Object obj) {
495:                Assert.assertNotNull(obj);
496:                return literalValuesValueFor + LITERAL_LOCK_PREFIX + obj;
497:            }
498:
499:            private static String generateAutolockName(long objectId) {
500:                return AUTOLOCK_PREFIX + objectId;
501:            }
502:
503:            /**
504:             * Strip generated lock header from lock name
505:             * @param lockName Lock name
506:             * @return Real lock name
507:             */
508:            public static String stripGeneratedLockHeader(String lockName) {
509:                int index = lockName.indexOf(LITERAL_LOCK_PREFIX);
510:                index = index < 0 ? 1 : index;
511:                return lockName.substring(index);
512:            }
513:
514:            /**
515:             * Convert from {@link com.tc.asm.Type#getSort()} to a primitive method
516:             * name like "booleanValue".
517:             * @param Type kind
518:             * @return Primitive method name
519:             */
520:            public static String sortToPrimitiveMethodName(int sort) {
521:                switch (sort) {
522:                case Type.BOOLEAN: // '\001'
523:                    return "booleanValue";
524:
525:                case Type.CHAR: // '\002'
526:                    return "charValue";
527:
528:                case Type.BYTE: // '\003'
529:                    return "byteValue";
530:
531:                case Type.SHORT: // '\004'
532:                    return "shortValue";
533:
534:                case Type.INT: // '\005'
535:                    return "intValue";
536:
537:                case Type.FLOAT: // '\006'
538:                    return "floatValue";
539:
540:                case Type.LONG: // '\007'
541:                    return "longValue";
542:
543:                case Type.DOUBLE: // '\b'
544:                    return "doubleValue";
545:                default:
546:                    throw new AssertionError();
547:                }
548:            }
549:
550:            /**
551:             * Get return type (class name) from method descriptor
552:             * @param desc Method descriptor
553:             * @return Return type class name
554:             */
555:            public static String methodDescriptionToReturnType(String desc) {
556:                Type type = Type.getReturnType(desc);
557:                return type.getClassName();
558:            }
559:
560:            /**
561:             * Turn method description with byte code types into a readable signature
562:             * @param desc The bytecode description
563:             * @return The method argument form
564:             */
565:            public static String methodDescriptionToMethodArgument(String desc) {
566:                Type[] types = Type.getArgumentTypes(desc);
567:                StringBuffer sb = new StringBuffer("(");
568:                for (int i = 0; i < types.length; i++) {
569:                    sb.append(types[i].getClassName());
570:                    if (i < types.length - 1) {
571:                        sb.append(",");
572:                    }
573:                }
574:                sb.append(")");
575:                return sb.toString();
576:            }
577:
578:            /**
579:             * Get name of synthetic field getter method added by Terracotta
580:             * @param fieldName The field name
581:             * @return Getter method name
582:             */
583:            public static String fieldGetterMethod(String fieldName) {
584:                return TC_METHOD_PREFIX + "get" + fieldName;
585:            }
586:
587:            /**
588:             * Get name of synthetic field setter method added by Terracotta
589:             * @param fieldName The field name
590:             * @return Setter method name
591:             */
592:            public static String fieldSetterMethod(String fieldName) {
593:                return TC_METHOD_PREFIX + "set" + fieldName;
594:            }
595:
596:            /**
597:             * Add instructions to print msg to System.out
598:             * @param mv Method visitor
599:             * @param msg Message to print
600:             */
601:            public static void systemOutPrintln(MethodVisitor mv, String msg) {
602:                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
603:                        "Ljava/io/PrintStream;");
604:                mv.visitLdcInsn(msg);
605:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream",
606:                        "println", "(Ljava/lang/String;)V");
607:            }
608:
609:            /**
610:             * Translate class name to file name
611:             * @param className The class name "java.lang.String"
612:             * @return The file name on the classpath: "java/lang/String.class"
613:             */
614:            public static final String classNameToFileName(String className) {
615:                return className.replace('.', '/') + ".class";
616:            }
617:
618:            /** 
619:             * Read the bytes defining the class
620:             * @param className The class
621:             * @param loader The classloader
622:             * @return The underlying bytes
623:             */
624:            public static final byte[] getBytesForClass(String className,
625:                    ClassLoader loader) throws ClassNotFoundException {
626:                String resource = classNameToFileName(className);
627:                InputStream is = loader.getResourceAsStream(resource);
628:                if (is == null) {
629:                    throw new ClassNotFoundException(
630:                            "No resource found for class: " + className);
631:                }
632:                try {
633:                    return getBytesForInputstream(is);
634:                } catch (IOException e) {
635:                    throw new ClassNotFoundException("Error reading bytes for "
636:                            + resource, e);
637:                }
638:            }
639:
640:            /**
641:             * Read input stream into a byte array using a 4k buffer.  Close stream when done.
642:             * @param is Input stream
643:             * @return Bytes read from stream
644:             * @throws IOException If there is an error reading the stream
645:             */
646:            public static final byte[] getBytesForInputstream(InputStream is)
647:                    throws IOException {
648:                final int size = 4096;
649:                byte[] buffer = new byte[size];
650:                ByteArrayOutputStream baos = new ByteArrayOutputStream(size);
651:
652:                int read;
653:                try {
654:                    while ((read = is.read(buffer, 0, size)) > 0) {
655:                        baos.write(buffer, 0, read);
656:                    }
657:                } finally {
658:                    if (is != null) {
659:                        try {
660:                            is.close();
661:                        } catch (IOException ioe) {
662:                            // ignore
663:                        }
664:                    }
665:                }
666:
667:                return baos.toByteArray();
668:            }
669:
670:            /**
671:             * Assign the default value to the variable
672:             * @param variable The local variable to which the default value will be assigned
673:             * @param c MethodVisitor
674:             * @param type Type of the variable
675:             */
676:            public static void pushDefaultValue(int variable, MethodVisitor c,
677:                    Type type) {
678:                if (type.getSort() == Type.OBJECT
679:                        || type.getSort() == Type.ARRAY) {
680:                    c.visitInsn(ACONST_NULL);
681:                    c.visitVarInsn(ASTORE, variable);
682:                } else {
683:                    c.visitInsn(getConstant0(type));
684:                    c.visitVarInsn(type.getOpcode(ISTORE), variable);
685:                }
686:            }
687:
688:            /**
689:             * Return the constant 0 value according to the type.
690:             * @param type
691:             */
692:            private static int getConstant0(Type type) {
693:                if (type.getSort() == Type.INT) {
694:                    return ICONST_0;
695:                }
696:                if (type.getSort() == Type.LONG) {
697:                    return LCONST_0;
698:                }
699:                if (type.getSort() == Type.SHORT) {
700:                    return ICONST_0;
701:                }
702:                if (type.getSort() == Type.DOUBLE) {
703:                    return DCONST_0;
704:                }
705:                if (type.getSort() == Type.BOOLEAN) {
706:                    return ICONST_0;
707:                }
708:                if (type.getSort() == Type.FLOAT) {
709:                    return FCONST_0;
710:                }
711:                if (type.getSort() == Type.BYTE) {
712:                    return ICONST_0;
713:                }
714:                if (type.getSort() == Type.CHAR) {
715:                    return ICONST_0;
716:                }
717:
718:                throw new AssertionError(
719:                        "Cannot determine constant 0 of type: "
720:                                + type.getDescriptor());
721:            }
722:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.