Source Code Cross Referenced for ProxyClassFile.java in  » Apache-Harmony-Java-SE » org-package » org » apache » harmony » luni » internal » reflect » 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 » Apache Harmony Java SE » org package » org.apache.harmony.luni.internal.reflect 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:
0018:        package org.apache.harmony.luni.internal.reflect;
0019:
0020:        import java.io.PrintStream;
0021:        import java.lang.reflect.Constructor;
0022:        import java.lang.reflect.Field;
0023:        import java.lang.reflect.InvocationHandler;
0024:        import java.lang.reflect.Method;
0025:        import java.lang.reflect.Proxy;
0026:        import java.lang.reflect.UndeclaredThrowableException;
0027:        import java.util.ArrayList;
0028:        import java.util.HashSet;
0029:
0030:        public final class ProxyClassFile implements  ProxyConstants {
0031:
0032:            private static final int INITIAL_CONTENTS_SIZE = 1000;
0033:
0034:            private static final int INITIAL_HEADER_SIZE = 500;
0035:
0036:            private static final int INCREMENT_SIZE = 250;
0037:
0038:            private static Method ObjectEqualsMethod;
0039:
0040:            private static Method ObjectHashCodeMethod;
0041:
0042:            private static Method ObjectToStringMethod;
0043:
0044:            private static Method ClassGetMethod;
0045:
0046:            private static Method HandlerInvokeMethod;
0047:
0048:            private static Constructor<?> ProxyConstructor;
0049:
0050:            private static Constructor<?> UndeclaredThrowableExceptionConstructor;
0051:
0052:            private static Field ProxyHandlerField;
0053:
0054:            public static byte[] generateBytes(String typeName,
0055:                    Class[] interfaces) {
0056:                ProxyClassFile classFile = new ProxyClassFile(typeName,
0057:                        interfaces);
0058:                classFile.findMethods(interfaces);
0059:                classFile.addFields();
0060:                classFile.addMethods();
0061:                classFile.addAttributes();
0062:                return classFile.getBytes();
0063:            }
0064:
0065:            static char[] getConstantPoolName(Class<?> c) {
0066:                if (c.isArray()) {
0067:                    // Array classes are named/ with their signature
0068:                    return c.getName().replace('.', '/').toCharArray();
0069:                }
0070:
0071:                if (c.isPrimitive()) {
0072:                    // Special cases for each base type.
0073:                    if (c == void.class) {
0074:                        return new char[] { 'V' };
0075:                    }
0076:                    if (c == int.class) {
0077:                        return new char[] { 'I' };
0078:                    }
0079:                    if (c == boolean.class) {
0080:                        return new char[] { 'Z' };
0081:                    }
0082:                    if (c == byte.class) {
0083:                        return new char[] { 'B' };
0084:                    }
0085:                    if (c == char.class) {
0086:                        return new char[] { 'C' };
0087:                    }
0088:                    if (c == short.class) {
0089:                        return new char[] { 'S' };
0090:                    }
0091:                    if (c == long.class) {
0092:                        return new char[] { 'J' };
0093:                    }
0094:                    if (c == float.class) {
0095:                        return new char[] { 'F' };
0096:                    }
0097:                    if (c == double.class) {
0098:                        return new char[] { 'D' };
0099:                    }
0100:                }
0101:                return ("L" + c.getName().replace('.', '/') + ";")
0102:                        .toCharArray();
0103:            }
0104:
0105:            static char[] getConstantPoolName(Constructor<?> method) /* (ILjava/lang/Thread;)V */{
0106:                Class[] parameters = method.getParameterTypes();
0107:                StringBuffer buffer = new StringBuffer(
0108:                        parameters.length + 1 * 20);
0109:                buffer.append('(');
0110:                for (Class<?> element : parameters) {
0111:                    buffer.append(getConstantPoolName(element));
0112:                }
0113:                buffer.append(')');
0114:                buffer.append(getConstantPoolName(void.class));
0115:                return buffer.toString().toCharArray();
0116:            }
0117:
0118:            static char[] getConstantPoolName(Method method) /* (ILjava/lang/Thread;)Ljava/lang/Object; */{
0119:                Class[] parameters = method.getParameterTypes();
0120:                StringBuffer buffer = new StringBuffer(
0121:                        parameters.length + 1 * 20);
0122:                buffer.append('(');
0123:                for (Class<?> element : parameters) {
0124:                    buffer.append(getConstantPoolName(element));
0125:                }
0126:                buffer.append(')');
0127:                buffer.append(getConstantPoolName(method.getReturnType()));
0128:                return buffer.toString().toCharArray();
0129:            }
0130:
0131:            private ProxyConstantPool constantPool;
0132:
0133:            // the header contains all the bytes till the end of the constant pool
0134:            byte[] header;
0135:
0136:            int headerOffset;
0137:
0138:            // that collection contains all the remaining bytes of the .class file
0139:            private byte[] contents;
0140:
0141:            private int contentsOffset;
0142:
0143:            private int constantPoolOffset;
0144:
0145:            private ProxyMethod[] proxyMethods;
0146:
0147:            private String typeName;
0148:
0149:            ProxyClassFile(String typeName, Class[] interfaces) {
0150:                super ();
0151:                this .typeName = typeName;
0152:                header = new byte[INITIAL_HEADER_SIZE];
0153:                // generate the magic numbers inside the header
0154:                header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
0155:                header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
0156:                header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
0157:                header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
0158:                // Compatible with JDK 1.2
0159:                header[headerOffset++] = 0;
0160:                header[headerOffset++] = 0;
0161:                header[headerOffset++] = 0;
0162:                header[headerOffset++] = 49;
0163:                constantPoolOffset = headerOffset;
0164:                headerOffset += 2;
0165:                constantPool = new ProxyConstantPool(this );
0166:                contents = new byte[INITIAL_CONTENTS_SIZE];
0167:                // now we continue to generate the bytes inside the contents array
0168:                int accessFlags = AccPublic | AccFinal | AccSuper;
0169:                contents[contentsOffset++] = (byte) (accessFlags >> 8);
0170:                contents[contentsOffset++] = (byte) accessFlags;
0171:                int classNameIndex = constantPool.typeIndex(typeName);
0172:                contents[contentsOffset++] = (byte) (classNameIndex >> 8);
0173:                contents[contentsOffset++] = (byte) classNameIndex;
0174:                int super classNameIndex = constantPool
0175:                        .typeIndex("java/lang/reflect/Proxy");
0176:                contents[contentsOffset++] = (byte) (super classNameIndex >> 8);
0177:                contents[contentsOffset++] = (byte) super classNameIndex;
0178:                int interfacesCount = interfaces.length;
0179:                contents[contentsOffset++] = (byte) (interfacesCount >> 8);
0180:                contents[contentsOffset++] = (byte) interfacesCount;
0181:                for (int i = 0; i < interfacesCount; i++) {
0182:                    int interfaceIndex = constantPool.typeIndex(interfaces[i]
0183:                            .getName());
0184:                    contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
0185:                    contents[contentsOffset++] = (byte) interfaceIndex;
0186:                }
0187:            }
0188:
0189:            private void addAttributes() {
0190:                writeUnsignedShort(0); // classFile does not have attributes of its own
0191:
0192:                // resynchronize all offsets of the classfile
0193:                header = constantPool.poolContent;
0194:                headerOffset = constantPool.currentOffset;
0195:                int constantPoolCount = constantPool.currentIndex;
0196:                header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
0197:                header[constantPoolOffset] = (byte) constantPoolCount;
0198:            }
0199:
0200:            private void writeStaticInitializer() {
0201:                writeUnsignedShort(AccStatic);
0202:                writeUnsignedShort(constantPool.literalIndex(new char[] { '<',
0203:                        'c', 'l', 'i', 'n', 'i', 't', '>' }));
0204:                writeUnsignedShort(constantPool.literalIndex(new char[] { '(',
0205:                        ')', 'V' }));
0206:                writeUnsignedShort(1); //todo add Exceptions    	
0207:                generateCodeAttribute3();
0208:            }
0209:
0210:            private void completeCodeDescription(int codeLength, int offset,
0211:                    int maxLocals) {
0212:                writeUnsignedWord(codeLength + 8, offset);
0213:                writeUnsignedShort(maxLocals + 10, offset + 4);
0214:                writeUnsignedShort(maxLocals, offset + 6);
0215:                writeUnsignedWord(codeLength - 12, offset + 8);
0216:            }
0217:
0218:            private void initializeField(ProxyMethod m, int index) {
0219:                String methodName = m.method.getName();
0220:                Class[] params = m.method.getParameterTypes();
0221:                int paramLengths = params.length;
0222:                writeLdcWithClass(m.getDeclaringClass().getName());
0223:                writeLdc(methodName);
0224:                writeIntConstant(paramLengths);
0225:                writeUnsignedByte(OPC_anewarray);
0226:                writeUnsignedShort(constantPool.typeIndex("java/lang/Class"));
0227:                for (int i = 0; i < paramLengths; i++) {
0228:                    writeUnsignedByte(OPC_dup);
0229:                    writeIntConstant(i);
0230:                    if (params[i].isPrimitive()) {
0231:                        writeUnsignedByte(OPC_getstatic);
0232:                        writeUnsignedShort(constantPool
0233:                                .literalIndex(typeWrapperName(params[i]),
0234:                                        "TYPE", Class.class));
0235:
0236:                    } else {
0237:                        writeLdcWithClass(params[i].getName());
0238:                    }
0239:                    writeUnsignedByte(OPC_aastore);
0240:                }
0241:
0242:                if (ClassGetMethod == null) {
0243:                    try {
0244:                        ClassGetMethod = Class.class.getMethod("getMethod",
0245:                                new Class[] { String.class, Class[].class });
0246:                    } catch (NoSuchMethodException e) {
0247:                        throw new InternalError();
0248:                    }
0249:                }
0250:                writeUnsignedByte(OPC_invokevirtual);
0251:                writeUnsignedShort(constantPool.literalIndex(ClassGetMethod));
0252:                writeUnsignedByte(OPC_putstatic);
0253:                writeUnsignedShort(constantPool.literalIndex(typeName,
0254:                        getFieldNamebyMethodName(methodName, index),
0255:                        Method.class));
0256:            }
0257:
0258:            private void generateCodeAttribute3() {
0259:                writeUnsignedShort(constantPool.literalIndex(CodeName));
0260:                int codeStart = contentsOffset;
0261:                writeUnsignedWord(0); //skip these fields so far        
0262:                writeUnsignedWord(0);
0263:                writeUnsignedWord(0);
0264:                for (int i = 0; i < proxyMethods.length; i++) {
0265:                    initializeField(proxyMethods[i], i);
0266:                }
0267:                int gotoTarget = contentsOffset;
0268:                writeUnsignedByte(OPC_goto);
0269:                int targetForGotoOffset = contentsOffset;
0270:                writeUnsignedShort(4); //to be updated        
0271:                int handlerStart = contentsOffset - codeStart - 12;
0272:                generateExceptionHandler();
0273:                gotoTarget = contentsOffset - gotoTarget;
0274:                writeUnsignedByte(OPC_return);
0275:                writeUnsignedShort(gotoTarget, targetForGotoOffset);
0276:                completeCodeDescription(contentsOffset - codeStart, codeStart,
0277:                        1);
0278:                writeUnsignedShort(1);
0279:                writeUnsignedShort(0);
0280:                writeUnsignedShort(handlerStart);
0281:                writeUnsignedShort(handlerStart);
0282:                writeUnsignedShort(constantPool
0283:                        .typeIndex("java/lang/Exception"));
0284:                writeUnsignedShort(0); // there are no attributes for the code        
0285:            }
0286:
0287:            //return handlerStart
0288:            private void generateExceptionHandler() {
0289:                //writeUnsignedByte(OPC_astore_0);    	
0290:                writeUnsignedByte(OPC_astore_0);
0291:                writeUnsignedByte(OPC_aload_0);
0292:
0293:                writeUnsignedByte(OPC_getstatic);
0294:                writeUnsignedShort(constantPool.literalIndex(
0295:                        "java/lang/System", "err", PrintStream.class));
0296:                Method m = null;
0297:                try {
0298:                    m = Exception.class.getMethod("printStackTrace",
0299:                            new Class[] { PrintStream.class });
0300:                } catch (Exception e) {
0301:                    e.printStackTrace(System.err);
0302:                }
0303:
0304:                writeUnsignedByte(OPC_invokevirtual);
0305:                writeUnsignedShort(constantPool.literalIndex(m));
0306:            }
0307:
0308:            private String getFieldNamebyMethodName(String methodName, int index) {
0309:                return methodName + "Method" + index;
0310:            }
0311:
0312:            private void addMethods() {
0313:                int methodCount = proxyMethods.length;
0314:                writeUnsignedShort(methodCount + 2);
0315:
0316:                // save constructor
0317:                writeUnsignedShort(AccPublic);
0318:                writeUnsignedShort(constantPool.literalIndex(Init));
0319:                if (ProxyConstructor == null) {
0320:                    try {
0321:                        ProxyConstructor = Proxy.class
0322:                                .getDeclaredConstructor(new Class[] { InvocationHandler.class });
0323:                    } catch (NoSuchMethodException e) {
0324:                        throw new InternalError();
0325:                    }
0326:                }
0327:                writeUnsignedShort(constantPool
0328:                        .literalIndex(getConstantPoolName(ProxyConstructor)));
0329:                writeUnsignedShort(1); // store just the code attribute
0330:                writeUnsignedShort(constantPool.literalIndex(CodeName));
0331:                // save attribute_length(4), max_stack(2), max_locals(2), code_length(4)
0332:                int codeLength = 6;
0333:                writeUnsignedWord(12 + codeLength); // max_stack(2), max_locals(2),
0334:                // code_length(4), 2 zero shorts
0335:                writeUnsignedShort(2);
0336:                writeUnsignedShort(2);
0337:                writeUnsignedWord(codeLength);
0338:                writeUnsignedByte(OPC_aload_0);
0339:                writeUnsignedByte(OPC_aload_1);
0340:                writeUnsignedByte(OPC_invokespecial);
0341:                writeUnsignedShort(constantPool.literalIndex(ProxyConstructor));
0342:                writeUnsignedByte(OPC_return);
0343:                writeUnsignedShort(0); // no exceptions table
0344:                writeUnsignedShort(0); // there are no attributes for the code
0345:                // attribute
0346:
0347:                for (int i = 0; i < methodCount; i++) {
0348:                    ProxyMethod pMethod = proxyMethods[i];
0349:                    Method method = pMethod.method;
0350:                    writeUnsignedShort(AccPublic | AccFinal);
0351:                    writeUnsignedShort(constantPool.literalIndex(method
0352:                            .getName().toCharArray()));
0353:                    writeUnsignedShort(constantPool
0354:                            .literalIndex(getConstantPoolName(method)));
0355:
0356:                    Class[] thrownsExceptions = pMethod.commonExceptions;
0357:                    int eLength = thrownsExceptions.length;
0358:                    if (eLength > 0) {
0359:                        writeUnsignedShort(2); // store the exception & code attributes
0360:                        // The method has a throw clause. So we need to add an exception
0361:                        // attribute
0362:                        writeUnsignedShort(constantPool
0363:                                .literalIndex(ExceptionsName));
0364:                        // The attribute length = length * 2 + 2 in case of a exception
0365:                        // attribute
0366:                        writeUnsignedWord(eLength * 2 + 2);
0367:                        writeUnsignedShort(eLength);
0368:                        for (int e = 0; e < eLength; e++) {
0369:                            writeUnsignedShort(constantPool
0370:                                    .typeIndex(thrownsExceptions[e].getName()));
0371:                        }
0372:                    } else {
0373:                        writeUnsignedShort(1); // store just the code attribute
0374:                    }
0375:                    generateCodeAttribute(pMethod, i);
0376:                }
0377:
0378:                writeStaticInitializer();
0379:            }
0380:
0381:            private void findMethods(Class[] interfaces) {
0382:                /*
0383:                 * find all methods defined by the interfaces (including inherited
0384:                 * interfaces) plus hashCode, equals & toString from Object build an
0385:                 * array with the methods... no duplicates - check up to the array size
0386:                 * when the interface's first method was added
0387:                 */
0388:                if (ObjectEqualsMethod == null) {
0389:                    try {
0390:                        ObjectEqualsMethod = Object.class.getMethod("equals",
0391:                                new Class[] { Object.class });
0392:                        ObjectHashCodeMethod = Object.class.getMethod(
0393:                                "hashCode", new Class[0]);
0394:                        ObjectToStringMethod = Object.class.getMethod(
0395:                                "toString", new Class[0]);
0396:                    } catch (NoSuchMethodException ex) {
0397:                        throw new InternalError();
0398:                    }
0399:                }
0400:
0401:                ArrayList<ProxyMethod> allMethods = new ArrayList<ProxyMethod>(
0402:                        25);
0403:                allMethods
0404:                        .add(new ProxyMethod(Object.class, ObjectEqualsMethod));
0405:                allMethods.add(new ProxyMethod(Object.class,
0406:                        ObjectHashCodeMethod));
0407:                allMethods.add(new ProxyMethod(Object.class,
0408:                        ObjectToStringMethod));
0409:
0410:                HashSet<Class<?>> interfacesSeen = new HashSet<Class<?>>();
0411:                for (Class<?> element : interfaces) {
0412:                    findMethods(element, allMethods, interfacesSeen);
0413:                }
0414:
0415:                proxyMethods = new ProxyMethod[allMethods.size()];
0416:                allMethods.toArray(proxyMethods);
0417:            }
0418:
0419:            private void addFields() {
0420:                //writeUnsignedShort(0); // we have no fields        
0421:                int methodCount = proxyMethods.length;
0422:                writeUnsignedShort(methodCount);
0423:                for (int i = 0; i < methodCount; i++) {
0424:                    writeUnsignedShort(AccPublic | AccStatic);
0425:                    String methodName = getFieldNamebyMethodName(
0426:                            proxyMethods[i].method.getName(), i);
0427:                    writeUnsignedShort(constantPool.literalIndex(methodName
0428:                            .toCharArray()));
0429:                    writeUnsignedShort(constantPool
0430:                            .literalIndex("Ljava/lang/reflect/Method;"
0431:                                    .toCharArray()));
0432:                    writeUnsignedShort(0);
0433:                }
0434:            }
0435:
0436:            private void findMethods(Class<?> nextInterface,
0437:                    ArrayList<ProxyMethod> allMethods,
0438:                    HashSet<Class<?>> interfacesSeen) {
0439:                /*
0440:                 * add the nextInterface's methods to allMethods if an equivalent method
0441:                 * already exists then return types must be identical... don't replace
0442:                 * it
0443:                 */
0444:                if (interfacesSeen.contains(nextInterface)) {
0445:                    return; // already walked it
0446:                }
0447:                interfacesSeen.add(nextInterface);
0448:
0449:                int existingMethodCount = allMethods.size();
0450:                Method[] methods = nextInterface.getMethods();
0451:                nextMethod: for (Method method : methods) {
0452:                    for (int j = 0; j < existingMethodCount; j++) {
0453:                        if (allMethods.get(j).matchMethod(method)) {
0454:                            continue nextMethod;
0455:                        }
0456:                    }
0457:                    allMethods.add(new ProxyMethod(nextInterface, method));
0458:                }
0459:
0460:                Class<?>[] super Interfaces = nextInterface.getInterfaces();
0461:                for (Class<?> element : super Interfaces) {
0462:                    // recursion should be minimal
0463:                    findMethods(element, allMethods, interfacesSeen);
0464:                }
0465:            }
0466:
0467:            private void generateCodeAttribute(ProxyMethod pMethod, int index) {
0468:                int codeAttributeOffset = contentsOffset;
0469:                int contentsLength = contents.length;
0470:                if (contentsOffset + 20 + 100 >= contentsLength) {
0471:                    System.arraycopy(contents, 0,
0472:                            (contents = new byte[contentsLength
0473:                                    + INCREMENT_SIZE]), 0, contentsLength);
0474:                }
0475:                writeUnsignedShort(constantPool.literalIndex(CodeName));
0476:                // leave space for attribute_length(4), max_stack(2), max_locals(2),
0477:                // code_length(4)
0478:                contentsOffset += 12;
0479:
0480:                /*
0481:                 * to push the args for the call to invoke push the receiver field h 0
0482:                 * aload0 1 getfield 33 java.lang.reflect.Proxy.h
0483:                 * Ljava.lang.reflect.InvocationHandler; push the receiver as the first
0484:                 * arg 4 aload0 push the method push the array of args call invoke 89
0485:                 * invokeinterface 67
0486:                 * java.lang.reflect.InvocationHandler.invoke(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object;
0487:                 * cast return result catch & convert exceptions if necessary
0488:                 */
0489:
0490:                int codeStartOffset = contentsOffset;
0491:                writeUnsignedByte(OPC_aload_0);
0492:                writeUnsignedByte(OPC_getfield);
0493:                if (ProxyHandlerField == null) {
0494:                    try {
0495:                        ProxyHandlerField = Proxy.class.getDeclaredField("h");
0496:                    } catch (NoSuchFieldException e) {
0497:                        throw new InternalError();
0498:                    }
0499:                }
0500:                writeUnsignedShort(constantPool.literalIndex(ProxyHandlerField));
0501:                writeUnsignedByte(OPC_aload_0);
0502:                Method method = pMethod.method;
0503:                Class[] argTypes = method.getParameterTypes();
0504:                writeUnsignedByte(OPC_getstatic);
0505:                writeUnsignedShort(constantPool.literalIndex(typeName,
0506:                        getFieldNamebyMethodName(pMethod.method.getName(),
0507:                                index), Method.class));
0508:                int maxLocals = genInvokeArgs(argTypes);
0509:                writeUnsignedByte(OPC_invokeinterface);
0510:                if (HandlerInvokeMethod == null) {
0511:                    try {
0512:                        HandlerInvokeMethod = InvocationHandler.class
0513:                                .getMethod("invoke", new Class[] {
0514:                                        Object.class, Method.class,
0515:                                        Object[].class });
0516:                    } catch (NoSuchMethodException e) {
0517:                        throw new InternalError();
0518:                    }
0519:                }
0520:                writeUnsignedShort(constantPool
0521:                        .literalIndex(HandlerInvokeMethod));
0522:                writeUnsignedByte(4); // invoke has 3 args
0523:                writeUnsignedByte(0); // 4th operand must be 0
0524:                genCastReturnType(method.getReturnType());
0525:                int codeLength = contentsOffset - codeStartOffset;
0526:
0527:                Class[] checkedExceptions = pMethod.getCheckedExceptions();
0528:                int checkedLength = checkedExceptions.length;
0529:                if (checkedLength > 0) {
0530:                    int codeEndIndex = contentsOffset - codeStartOffset;
0531:                    writeUnsignedByte(OPC_athrow); // re-throw the caught exception
0532:
0533:                    genStoreArg(maxLocals);
0534:                    writeUnsignedByte(OPC_new);
0535:                    writeUnsignedShort(constantPool
0536:                            .typeIndex("java/lang/reflect/UndeclaredThrowableException"));
0537:                    writeUnsignedByte(OPC_dup);
0538:                    genLoadArg(maxLocals);
0539:                    maxLocals++; // now expecting the exception
0540:                    writeUnsignedByte(OPC_invokespecial);
0541:                    if (UndeclaredThrowableExceptionConstructor == null) {
0542:                        try {
0543:                            UndeclaredThrowableExceptionConstructor = UndeclaredThrowableException.class
0544:                                    .getConstructor(new Class[] { Throwable.class });
0545:                        } catch (NoSuchMethodException e) {
0546:                            throw new InternalError();
0547:                        }
0548:                    }
0549:                    writeUnsignedShort(constantPool
0550:                            .literalIndex(UndeclaredThrowableExceptionConstructor));
0551:                    writeUnsignedByte(OPC_athrow);
0552:
0553:                    codeLength = contentsOffset - codeStartOffset;
0554:
0555:                    // write the exception table
0556:                    writeUnsignedShort(checkedLength + 1);
0557:                    for (int i = 0; i < checkedLength; i++) {
0558:                        writeUnsignedShort(0);
0559:                        writeUnsignedShort(codeEndIndex);
0560:                        writeUnsignedShort(codeEndIndex);
0561:                        writeUnsignedShort(constantPool
0562:                                .typeIndex(checkedExceptions[i].getName()));
0563:                    }
0564:                    writeUnsignedShort(0);
0565:                    writeUnsignedShort(codeEndIndex);
0566:                    writeUnsignedShort(codeEndIndex + 1); // starts after the first
0567:                    // throw
0568:                    writeUnsignedShort(constantPool
0569:                            .typeIndex("java/lang/Throwable"));
0570:                } else {
0571:                    writeUnsignedShort(0); // no exceptions table
0572:                }
0573:                // there are no attributes for the code attribute
0574:                writeUnsignedShort(0);
0575:
0576:                /*
0577:                 * Complete the creation of the code attribute by setting the
0578:                 * attribute_length, max_stack max_locals, code_length & exception table
0579:                 * codeAttributeOffset is the position inside contents byte array before
0580:                 * we started to write That means that to write the attribute_length you
0581:                 * need to offset by 2 the value of codeAttributeOffset to get the right
0582:                 * position, 6 for the max_stack etc...
0583:                 */
0584:                int codeAttributeLength = contentsOffset
0585:                        - (codeAttributeOffset + 6);
0586:                contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
0587:                contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
0588:                contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
0589:                contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
0590:
0591:                int maxStack = maxLocals + 10; // larger than the exact amount
0592:                contents[codeAttributeOffset + 6] = (byte) (maxStack >> 8);
0593:                contents[codeAttributeOffset + 7] = (byte) maxStack;
0594:                contents[codeAttributeOffset + 8] = (byte) (maxLocals >> 8);
0595:                contents[codeAttributeOffset + 9] = (byte) maxLocals;
0596:                contents[codeAttributeOffset + 10] = (byte) (codeLength >> 24);
0597:                contents[codeAttributeOffset + 11] = (byte) (codeLength >> 16);
0598:                contents[codeAttributeOffset + 12] = (byte) (codeLength >> 8);
0599:                contents[codeAttributeOffset + 13] = (byte) codeLength;
0600:            }
0601:
0602:            /**
0603:             * Add argument array for call to InvocationHandler.invoke
0604:             * 
0605:             * 46 aconstnull or 81 iconst1 82 anewarray 61 java.lang.Object 85 dup 86
0606:             * iconst0 87 aload1 88 aastore or 58 iconst2 59 anewarray 61
0607:             * java.lang.Object 62 dup 63 iconst0 64 new 84 java.lang.Integer 67 dup 68
0608:             * iload1 69 invokespecial 107 java.lang.Integer.<init>(I)V 72 aastore 73
0609:             * dup 74 iconst1 75 new 69 java.lang.Boolean 78 dup 79 iload2 80
0610:             * invokespecial 110 java.lang.Boolean.<init>(Z)V 83 aastore
0611:             */
0612:            private int genInvokeArgs(Class[] argTypes) {
0613:                int argByteOffset = 1; // remember h is at position 0
0614:                int length = argTypes.length;
0615:                if (length == 0) {
0616:                    writeUnsignedByte(OPC_aconst_null);
0617:                } else {
0618:                    writeIntConstant(length);
0619:                    writeUnsignedByte(OPC_anewarray);
0620:                    writeUnsignedShort(constantPool
0621:                            .typeIndex("java/lang/Object"));
0622:                    for (int i = 0; i < length; i++) {
0623:                        writeUnsignedByte(OPC_dup);
0624:                        writeIntConstant(i);
0625:                        argByteOffset = genInvokeArg(argTypes[i], argByteOffset);
0626:                        writeUnsignedByte(OPC_aastore);
0627:                    }
0628:                }
0629:                return argByteOffset;
0630:            }
0631:
0632:            private int genInvokeArg(Class<?> type, int argByteOffset) {
0633:                // offset represents maxLocals in bytes
0634:                if (type.isPrimitive()) {
0635:                    writeUnsignedByte(OPC_new);
0636:                    writeUnsignedShort(constantPool
0637:                            .typeIndex(typeWrapperName(type)));
0638:                    writeUnsignedByte(OPC_dup);
0639:                    if (argByteOffset > 255) {
0640:                        writeUnsignedByte(OPC_wide);
0641:                    }
0642:                    if (type == long.class) {
0643:                        switch (argByteOffset) {
0644:                        case 0:
0645:                            writeUnsignedByte(OPC_lload_0);
0646:                            break;
0647:                        case 1:
0648:                            writeUnsignedByte(OPC_lload_1);
0649:                            break;
0650:                        case 2:
0651:                            writeUnsignedByte(OPC_lload_2);
0652:                            break;
0653:                        case 3:
0654:                            writeUnsignedByte(OPC_lload_3);
0655:                            break;
0656:                        default:
0657:                            writeUnsignedByte(OPC_lload);
0658:                            if (argByteOffset > 255) {
0659:                                writeUnsignedShort(argByteOffset);
0660:                            } else {
0661:                                writeUnsignedByte(argByteOffset);
0662:                            }
0663:                        }
0664:                        argByteOffset += 2;
0665:                    } else if (type == float.class) {
0666:                        switch (argByteOffset) {
0667:                        case 0:
0668:                            writeUnsignedByte(OPC_fload_0);
0669:                            break;
0670:                        case 1:
0671:                            writeUnsignedByte(OPC_fload_1);
0672:                            break;
0673:                        case 2:
0674:                            writeUnsignedByte(OPC_fload_2);
0675:                            break;
0676:                        case 3:
0677:                            writeUnsignedByte(OPC_fload_3);
0678:                            break;
0679:                        default:
0680:                            writeUnsignedByte(OPC_fload);
0681:                            if (argByteOffset > 255) {
0682:                                writeUnsignedShort(argByteOffset);
0683:                            } else {
0684:                                writeUnsignedByte(argByteOffset);
0685:                            }
0686:                        }
0687:                        argByteOffset++;
0688:                    } else if (type == double.class) {
0689:                        switch (argByteOffset) {
0690:                        case 0:
0691:                            writeUnsignedByte(OPC_dload_0);
0692:                            break;
0693:                        case 1:
0694:                            writeUnsignedByte(OPC_dload_1);
0695:                            break;
0696:                        case 2:
0697:                            writeUnsignedByte(OPC_dload_2);
0698:                            break;
0699:                        case 3:
0700:                            writeUnsignedByte(OPC_dload_3);
0701:                            break;
0702:                        default:
0703:                            writeUnsignedByte(OPC_dload);
0704:                            if (argByteOffset > 255) {
0705:                                writeUnsignedShort(argByteOffset);
0706:                            } else {
0707:                                writeUnsignedByte(argByteOffset);
0708:                            }
0709:                        }
0710:                        argByteOffset += 2;
0711:                    } else { // handles int, short, byte, boolean & char
0712:                        switch (argByteOffset) {
0713:                        case 0:
0714:                            writeUnsignedByte(OPC_iload_0);
0715:                            break;
0716:                        case 1:
0717:                            writeUnsignedByte(OPC_iload_1);
0718:                            break;
0719:                        case 2:
0720:                            writeUnsignedByte(OPC_iload_2);
0721:                            break;
0722:                        case 3:
0723:                            writeUnsignedByte(OPC_iload_3);
0724:                            break;
0725:                        default:
0726:                            writeUnsignedByte(OPC_iload);
0727:                            if (argByteOffset > 255) {
0728:                                writeUnsignedShort(argByteOffset);
0729:                            } else {
0730:                                writeUnsignedByte(argByteOffset);
0731:                            }
0732:                        }
0733:                        argByteOffset++;
0734:                    }
0735:                    writeUnsignedByte(OPC_invokespecial);
0736:                    writeUnsignedShort(constantPool
0737:                            .literalIndex(typeInitMethod(type)));
0738:                } else {
0739:                    genLoadArg(argByteOffset);
0740:                    argByteOffset++;
0741:                }
0742:                return argByteOffset;
0743:            }
0744:
0745:            /**
0746:             * 94 checkcast 69 java.lang.Boolean 97 invokevirtual 73
0747:             * java.lang.Boolean.booleanValue()Z 100 ireturn or 52 checkcast 91
0748:             * java.lang.String 55 areturn
0749:             */
0750:            private void genCastReturnType(Class<?> type) {
0751:                if (type.isPrimitive()) {
0752:                    if (type == void.class) {
0753:                        writeUnsignedByte(OPC_pop);
0754:                        writeUnsignedByte(OPC_return);
0755:                    } else {
0756:                        writeUnsignedByte(OPC_checkcast);
0757:                        writeUnsignedShort(constantPool
0758:                                .typeIndex(typeWrapperName(type)));
0759:                        writeUnsignedByte(OPC_invokevirtual);
0760:                        writeUnsignedShort(constantPool
0761:                                .literalIndex(typeAccessMethod(type)));
0762:                        if (type == long.class) {
0763:                            writeUnsignedByte(OPC_lreturn);
0764:                        } else if (type == float.class) {
0765:                            writeUnsignedByte(OPC_freturn);
0766:                        } else if (type == double.class) {
0767:                            writeUnsignedByte(OPC_dreturn);
0768:                        } else { // handles int, short, byte, boolean & char
0769:                            writeUnsignedByte(OPC_ireturn);
0770:                        }
0771:                    }
0772:                } else {
0773:                    writeUnsignedByte(OPC_checkcast);
0774:                    writeUnsignedShort(constantPool.typeIndex(type.getName()));
0775:                    writeUnsignedByte(OPC_areturn);
0776:                }
0777:            }
0778:
0779:            private void genLoadArg(int argByteOffset) {
0780:                if (argByteOffset > 255) {
0781:                    writeUnsignedByte(OPC_wide);
0782:                    writeUnsignedByte(OPC_aload);
0783:                    writeUnsignedShort(argByteOffset);
0784:                } else {
0785:                    switch (argByteOffset) {
0786:                    case 0:
0787:                        writeUnsignedByte(OPC_aload_0);
0788:                        break;
0789:                    case 1:
0790:                        writeUnsignedByte(OPC_aload_1);
0791:                        break;
0792:                    case 2:
0793:                        writeUnsignedByte(OPC_aload_2);
0794:                        break;
0795:                    case 3:
0796:                        writeUnsignedByte(OPC_aload_3);
0797:                        break;
0798:                    default:
0799:                        writeUnsignedByte(OPC_aload);
0800:                        writeUnsignedByte(argByteOffset);
0801:                    }
0802:                }
0803:            }
0804:
0805:            private void genStoreArg(int argByteOffset) {
0806:                if (argByteOffset > 255) {
0807:                    writeUnsignedByte(OPC_wide);
0808:                    writeUnsignedByte(OPC_astore);
0809:                    writeUnsignedShort(argByteOffset);
0810:                } else {
0811:                    switch (argByteOffset) {
0812:                    case 0:
0813:                        writeUnsignedByte(OPC_astore_0);
0814:                        break;
0815:                    case 1:
0816:                        writeUnsignedByte(OPC_astore_1);
0817:                        break;
0818:                    case 2:
0819:                        writeUnsignedByte(OPC_astore_2);
0820:                        break;
0821:                    case 3:
0822:                        writeUnsignedByte(OPC_astore_3);
0823:                        break;
0824:                    default:
0825:                        writeUnsignedByte(OPC_astore);
0826:                        writeUnsignedByte(argByteOffset);
0827:                    }
0828:                }
0829:            }
0830:
0831:            private byte[] getBytes() {
0832:                byte[] fullContents = new byte[headerOffset + contentsOffset];
0833:                System.arraycopy(header, 0, fullContents, 0, headerOffset);
0834:                System.arraycopy(contents, 0, fullContents, headerOffset,
0835:                        contentsOffset);
0836:                return fullContents;
0837:            }
0838:
0839:            private Method typeAccessMethod(Class<?> baseType) {
0840:                try {
0841:                    if (baseType == int.class) {
0842:                        return Integer.class.getMethod("intValue",
0843:                                (Class[]) null);
0844:                    }
0845:                    if (baseType == short.class) {
0846:                        return Short.class.getMethod("shortValue",
0847:                                (Class[]) null);
0848:                    }
0849:                    if (baseType == byte.class) {
0850:                        return Byte.class
0851:                                .getMethod("byteValue", (Class[]) null);
0852:                    }
0853:                    if (baseType == boolean.class) {
0854:                        return Boolean.class.getMethod("booleanValue",
0855:                                (Class[]) null);
0856:                    }
0857:                    if (baseType == char.class) {
0858:                        return Character.class.getMethod("charValue",
0859:                                (Class[]) null);
0860:                    }
0861:                    if (baseType == long.class) {
0862:                        return Long.class
0863:                                .getMethod("longValue", (Class[]) null);
0864:                    }
0865:                    if (baseType == float.class) {
0866:                        return Float.class.getMethod("floatValue",
0867:                                (Class[]) null);
0868:                    }
0869:                    if (baseType == double.class) {
0870:                        return Double.class.getMethod("doubleValue",
0871:                                (Class[]) null);
0872:                    }
0873:                } catch (NoSuchMethodException e) {
0874:                    throw new InternalError();
0875:                }
0876:                return null;
0877:            }
0878:
0879:            private Field typeField(Class<?> baseType) {
0880:                try {
0881:                    if (baseType == int.class) {
0882:                        return Integer.class.getField("TYPE");
0883:                    }
0884:                    if (baseType == short.class) {
0885:                        return Short.class.getField("TYPE");
0886:                    }
0887:                    if (baseType == byte.class) {
0888:                        return Byte.class.getField("TYPE");
0889:                    }
0890:                    if (baseType == boolean.class) {
0891:                        return Boolean.class.getField("TYPE");
0892:                    }
0893:                    if (baseType == char.class) {
0894:                        return Character.class.getField("TYPE");
0895:                    }
0896:                    if (baseType == long.class) {
0897:                        return Long.class.getField("TYPE");
0898:                    }
0899:                    if (baseType == float.class) {
0900:                        return Float.class.getField("TYPE");
0901:                    }
0902:                    if (baseType == double.class) {
0903:                        return Double.class.getField("TYPE");
0904:                    }
0905:                } catch (NoSuchFieldException e) {
0906:                    throw new InternalError();
0907:                }
0908:                return null;
0909:            }
0910:
0911:            private Constructor<?> typeInitMethod(Class<?> baseType) {
0912:                try {
0913:                    if (baseType == int.class) {
0914:                        return Integer.class
0915:                                .getConstructor(new Class[] { int.class });
0916:                    }
0917:                    if (baseType == short.class) {
0918:                        return Short.class
0919:                                .getConstructor(new Class[] { short.class });
0920:                    }
0921:                    if (baseType == byte.class) {
0922:                        return Byte.class
0923:                                .getConstructor(new Class[] { byte.class });
0924:                    }
0925:                    if (baseType == boolean.class) {
0926:                        return Boolean.class
0927:                                .getConstructor(new Class[] { boolean.class });
0928:                    }
0929:                    if (baseType == char.class) {
0930:                        return Character.class
0931:                                .getConstructor(new Class[] { char.class });
0932:                    }
0933:                    if (baseType == long.class) {
0934:                        return Long.class
0935:                                .getConstructor(new Class[] { long.class });
0936:                    }
0937:                    if (baseType == float.class) {
0938:                        return Float.class
0939:                                .getConstructor(new Class[] { float.class });
0940:                    }
0941:                    if (baseType == double.class) {
0942:                        return Double.class
0943:                                .getConstructor(new Class[] { double.class });
0944:                    }
0945:                } catch (NoSuchMethodException e) {
0946:                    throw new InternalError();
0947:                }
0948:                return null;
0949:            }
0950:
0951:            private String typeWrapperName(Class<?> baseType) {
0952:                if (baseType == int.class) {
0953:                    return "java/lang/Integer";
0954:                }
0955:                if (baseType == short.class) {
0956:                    return "java/lang/Short";
0957:                }
0958:                if (baseType == byte.class) {
0959:                    return "java/lang/Byte";
0960:                }
0961:                if (baseType == boolean.class) {
0962:                    return "java/lang/Boolean";
0963:                }
0964:                if (baseType == char.class) {
0965:                    return "java/lang/Character";
0966:                }
0967:                if (baseType == long.class) {
0968:                    return "java/lang/Long";
0969:                }
0970:                if (baseType == float.class) {
0971:                    return "java/lang/Float";
0972:                }
0973:                if (baseType == double.class) {
0974:                    return "java/lang/Double";
0975:                }
0976:                return null;
0977:            }
0978:
0979:            private void writeIntConstant(int b) {
0980:                switch (b) {
0981:                case 0:
0982:                    writeUnsignedByte(OPC_iconst_0);
0983:                    break;
0984:                case 1:
0985:                    writeUnsignedByte(OPC_iconst_1);
0986:                    break;
0987:                case 2:
0988:                    writeUnsignedByte(OPC_iconst_2);
0989:                    break;
0990:                case 3:
0991:                    writeUnsignedByte(OPC_iconst_3);
0992:                    break;
0993:                case 4:
0994:                    writeUnsignedByte(OPC_iconst_4);
0995:                    break;
0996:                case 5:
0997:                    writeUnsignedByte(OPC_iconst_5);
0998:                    break;
0999:                default:
1000:                    writeUnsignedByte(OPC_bipush);
1001:                    writeUnsignedByte(b);
1002:                }
1003:            }
1004:
1005:            private void writeLdc(String constant) {
1006:                int index = constantPool.literalIndexForLdc(constant
1007:                        .toCharArray());
1008:                if (index <= 0) {
1009:                    throw new InternalError();
1010:                }
1011:                if (index > 255) {
1012:                    writeUnsignedByte(OPC_ldc_w);
1013:                    writeUnsignedShort(index);
1014:                } else {
1015:                    writeUnsignedByte(OPC_ldc);
1016:                    writeUnsignedByte(index);
1017:                }
1018:            }
1019:
1020:            private void writeLdcWithClass(String name) {
1021:                int index = constantPool.typeIndex(name);
1022:                if (index <= 0) {
1023:                    throw new InternalError();
1024:                }
1025:                if (index > 255) {
1026:                    writeUnsignedByte(OPC_ldc_w);
1027:                    writeUnsignedShort(index);
1028:                } else {
1029:                    writeUnsignedByte(OPC_ldc);
1030:                    writeUnsignedByte(index);
1031:                }
1032:            }
1033:
1034:            private void writeUnsignedByte(int b) {
1035:                try {
1036:                    contents[contentsOffset++] = (byte) b;
1037:                } catch (IndexOutOfBoundsException e) {
1038:                    int actualLength = contents.length;
1039:                    System
1040:                            .arraycopy(contents, 0,
1041:                                    (contents = new byte[actualLength
1042:                                            + INCREMENT_SIZE]), 0, actualLength);
1043:                    contents[contentsOffset - 1] = (byte) b;
1044:                }
1045:            }
1046:
1047:            private void writeUnsignedShort(int b) {
1048:                writeUnsignedByte(b >>> 8);
1049:                writeUnsignedByte(b);
1050:            }
1051:
1052:            private void writeUnsignedWord(int b) {
1053:                writeUnsignedByte(b >>> 24);
1054:                writeUnsignedByte(b >>> 16);
1055:                writeUnsignedByte(b >>> 8);
1056:                writeUnsignedByte(b);
1057:            }
1058:
1059:            private void writeUnsignedByte(int b, int offset) {
1060:                try {
1061:                    contents[offset] = (byte) b;
1062:                } catch (IndexOutOfBoundsException e) {
1063:                    int actualLength = contents.length;
1064:                    System
1065:                            .arraycopy(contents, 0,
1066:                                    (contents = new byte[actualLength
1067:                                            + INCREMENT_SIZE]), 0, actualLength);
1068:                    contents[offset - 1] = (byte) b;
1069:                }
1070:            }
1071:
1072:            private void writeUnsignedShort(int b, int offset) {
1073:                writeUnsignedByte(b >>> 8, offset);
1074:                writeUnsignedByte(b, offset + 1);
1075:            }
1076:
1077:            private void writeUnsignedWord(int b, int offset) {
1078:                writeUnsignedByte(b >>> 24, offset);
1079:                writeUnsignedByte(b >>> 16, offset + 1);
1080:                writeUnsignedByte(b >>> 8, offset + 2);
1081:                writeUnsignedByte(b, offset + 3);
1082:            }
1083:
1084:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.