Source Code Cross Referenced for JavaProxyClassFactory.java in  » Scripting » jruby » org » jruby » javasupport » proxy » 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 » Scripting » jruby » org.jruby.javasupport.proxy 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /***** BEGIN LICENSE BLOCK *****
002:         * Version: CPL 1.0/GPL 2.0/LGPL 2.1
003:         *
004:         * The contents of this file are subject to the Common Public
005:         * License Version 1.0 (the "License"); you may not use this file
006:         * except in compliance with the License. You may obtain a copy of
007:         * the License at http://www.eclipse.org/legal/cpl-v10.html
008:         *
009:         * Software distributed under the License is distributed on an "AS
010:         * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
011:         * implied. See the License for the specific language governing
012:         * rights and limitations under the License.
013:         *
014:         * Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org>
015:         * 
016:         * Alternatively, the contents of this file may be used under the terms of
017:         * either of the GNU General Public License Version 2 or later (the "GPL"),
018:         * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
019:         * in which case the provisions of the GPL or the LGPL are applicable instead
020:         * of those above. If you wish to allow use of your version of this file only
021:         * under the terms of either the GPL or the LGPL, and not to allow others to
022:         * use your version of this file under the terms of the CPL, indicate your
023:         * decision by deleting the provisions above and replace them with the notice
024:         * and other provisions required by the GPL or the LGPL. If you do not delete
025:         * the provisions above, a recipient may use your version of this file under
026:         * the terms of any one of the CPL, the GPL or the LGPL.
027:         ***** END LICENSE BLOCK *****/package org.jruby.javasupport.proxy;
028:
029:        import java.lang.reflect.Constructor;
030:        import java.lang.reflect.Field;
031:        import java.lang.reflect.InvocationTargetException;
032:        import java.lang.reflect.Method;
033:        import java.lang.reflect.Modifier;
034:        import java.lang.reflect.UndeclaredThrowableException;
035:        import java.security.AccessController;
036:        import java.security.PrivilegedAction;
037:        import java.util.Arrays;
038:        import java.util.Collections;
039:        import java.util.HashMap;
040:        import java.util.HashSet;
041:        import java.util.Iterator;
042:        import java.util.Map;
043:        import java.util.Set;
044:
045:        import org.objectweb.asm.ClassVisitor;
046:        import org.objectweb.asm.ClassWriter;
047:        import org.objectweb.asm.FieldVisitor;
048:        import org.objectweb.asm.Label;
049:        import org.objectweb.asm.Opcodes;
050:        import org.objectweb.asm.Type;
051:        import org.objectweb.asm.commons.GeneratorAdapter;
052:
053:        public class JavaProxyClassFactory {
054:
055:            private static final Type JAVA_LANG_CLASS_TYPE = Type
056:                    .getType(Class.class);
057:
058:            private static final Type[] EMPTY_TYPE_ARR = new Type[0];
059:
060:            private static final org.objectweb.asm.commons.Method HELPER_GET_PROXY_CLASS_METHOD = org.objectweb.asm.commons.Method
061:                    .getMethod(JavaProxyClass.class.getName()
062:                            + " initProxyClass(java.lang.Class)");
063:
064:            private static final org.objectweb.asm.commons.Method CLASS_FORNAME_METHOD = org.objectweb.asm.commons.Method
065:                    .getMethod("java.lang.Class forName(java.lang.String)");
066:
067:            private static final String INVOCATION_HANDLER_FIELD_NAME = "__handler";
068:
069:            private static final String PROXY_CLASS_FIELD_NAME = "__proxy_class";
070:
071:            private static final Class[] EMPTY_CLASS_ARR = new Class[0];
072:
073:            private static final Type INVOCATION_HANDLER_TYPE = Type
074:                    .getType(JavaProxyInvocationHandler.class);
075:
076:            private static final Type PROXY_METHOD_TYPE = Type
077:                    .getType(JavaProxyMethod.class);
078:
079:            private static final Type PROXY_CLASS_TYPE = Type
080:                    .getType(JavaProxyClass.class);
081:
082:            private static final org.objectweb.asm.commons.Method INVOCATION_HANDLER_INVOKE_METHOD = org.objectweb.asm.commons.Method
083:                    .getMethod("java.lang.Object invoke(java.lang.Object, "
084:                            + PROXY_METHOD_TYPE.getClassName()
085:                            + ", java.lang.Object[])");
086:
087:            private static final Type PROXY_HELPER_TYPE = Type
088:                    .getType(InternalJavaProxyHelper.class);
089:
090:            private static final org.objectweb.asm.commons.Method PROXY_HELPER_GET_METHOD = org.objectweb.asm.commons.Method
091:                    .getMethod(PROXY_METHOD_TYPE.getClassName()
092:                            + " initProxyMethod("
093:                            + JavaProxyClass.class.getName()
094:                            + ",java.lang.String,java.lang.String,boolean)");
095:
096:            private static final Type JAVA_PROXY_TYPE = Type
097:                    .getType(InternalJavaProxy.class);
098:
099:            private static int counter;
100:
101:            private static Map proxies = Collections
102:                    .synchronizedMap(new HashMap());
103:
104:            private static Method defineClass_method; // statically initialized below
105:
106:            private static synchronized int nextId() {
107:                return counter++;
108:            }
109:
110:            // TODO: we should be able to optimize this quite a bit post-1.0.  JavaClass already
111:            // has all the methods organized by method name; the next version (supporting protected
112:            // methods/fields) will have them organized even further. So collectMethods here can
113:            // just lookup the overridden methods in the JavaClass map, should be much faster.
114:            static JavaProxyClass newProxyClass(ClassLoader loader,
115:                    String targetClassName, Class super Class,
116:                    Class[] interfaces, Set names)
117:                    throws InvocationTargetException {
118:                if (loader == null) {
119:                    loader = JavaProxyClassFactory.class.getClassLoader();
120:                }
121:
122:                if (super Class == null) {
123:                    super Class = Object.class;
124:                }
125:
126:                if (interfaces == null) {
127:                    interfaces = EMPTY_CLASS_ARR;
128:                }
129:
130:                Set key = new HashSet();
131:                key.add(super Class);
132:                for (int i = 0; i < interfaces.length; i++) {
133:                    key.add(interfaces[i]);
134:                }
135:
136:                // add (potentially) overridden names to the key.
137:                // TODO: see note above re: optimizations
138:                if (names != null) {
139:                    key.addAll(names);
140:                }
141:
142:                JavaProxyClass proxyClass = (JavaProxyClass) proxies.get(key);
143:                if (proxyClass == null) {
144:
145:                    if (targetClassName == null) {
146:                        String pkg = packageName(super Class);
147:                        String fullName = super Class.getName();
148:                        int ix = fullName.lastIndexOf('.');
149:                        String cName = fullName;
150:                        if (ix != -1) {
151:                            cName = fullName.substring(ix + 1);
152:                        }
153:                        if (pkg.startsWith("java.") || pkg.startsWith("javax.")) {
154:                            pkg = packageName(JavaProxyClassFactory.class)
155:                                    + ".gen";
156:                        }
157:                        if (ix == -1) {
158:                            targetClassName = cName + "$Proxy" + nextId();
159:                        } else {
160:                            targetClassName = pkg + "." + cName + "$Proxy"
161:                                    + nextId();
162:                        }
163:                    }
164:
165:                    validateArgs(targetClassName, super Class);
166:
167:                    Map methods = new HashMap();
168:                    collectMethods(super Class, interfaces, methods, names);
169:
170:                    Type selfType = Type.getType("L"
171:                            + toInternalClassName(targetClassName) + ";");
172:                    proxyClass = generate(loader, targetClassName, super Class,
173:                            interfaces, methods, selfType);
174:
175:                    proxies.put(key, proxyClass);
176:                }
177:
178:                return proxyClass;
179:            }
180:
181:            static JavaProxyClass newProxyClass(ClassLoader loader,
182:                    String targetClassName, Class super Class, Class[] interfaces)
183:                    throws InvocationTargetException {
184:                return newProxyClass(loader, targetClassName, super Class,
185:                        interfaces, null);
186:            }
187:
188:            private static JavaProxyClass generate(final ClassLoader loader,
189:                    final String targetClassName, final Class super Class,
190:                    final Class[] interfaces, final Map methods,
191:                    final Type selfType) {
192:                ClassWriter cw = beginProxyClass(targetClassName, super Class,
193:                        interfaces);
194:
195:                GeneratorAdapter clazzInit = createClassInitializer(selfType,
196:                        cw);
197:
198:                generateConstructors(super Class, selfType, cw);
199:
200:                generateGetProxyClass(selfType, cw);
201:
202:                generateGetInvocationHandler(selfType, cw);
203:
204:                generateProxyMethods(super Class, methods, selfType, cw,
205:                        clazzInit);
206:
207:                // finish class initializer
208:                clazzInit.returnValue();
209:                clazzInit.endMethod();
210:
211:                // end class
212:                cw.visitEnd();
213:
214:                byte[] data = cw.toByteArray();
215:
216:                /*
217:                 * try { FileOutputStream o = new
218:                 * FileOutputStream(targetClassName.replace( '/', '.') + ".class");
219:                 * o.write(data); o.close(); } catch (IOException ex) {
220:                 * ex.printStackTrace(); }
221:                 */
222:
223:                Class clazz = invokeDefineClass(loader,
224:                        selfType.getClassName(), data);
225:
226:                // trigger class initialization for the class
227:                try {
228:                    Field proxy_class = clazz
229:                            .getDeclaredField(PROXY_CLASS_FIELD_NAME);
230:                    proxy_class.setAccessible(true);
231:                    return (JavaProxyClass) proxy_class.get(clazz);
232:                } catch (Exception ex) {
233:                    InternalError ie = new InternalError();
234:                    ie.initCause(ex);
235:                    throw ie;
236:                }
237:            }
238:
239:            static {
240:                AccessController.doPrivileged(new PrivilegedAction() {
241:                    public Object run() {
242:                        try {
243:                            defineClass_method = ClassLoader.class
244:                                    .getDeclaredMethod("defineClass",
245:                                            new Class[] { String.class,
246:                                                    byte[].class, int.class,
247:                                                    int.class });
248:                        } catch (Exception e) {
249:                            // should not happen!
250:                            e.printStackTrace();
251:                            return null;
252:                        }
253:                        defineClass_method.setAccessible(true);
254:                        return null;
255:                    }
256:                });
257:            }
258:
259:            private static Class invokeDefineClass(ClassLoader loader,
260:                    String className, byte[] data) {
261:                try {
262:                    return (Class) defineClass_method.invoke(loader,
263:                            new Object[] { className, data, new Integer(0),
264:                                    new Integer(data.length) });
265:                } catch (IllegalArgumentException e) {
266:                    // TODO Auto-generated catch block
267:                    e.printStackTrace();
268:                    return null;
269:                } catch (IllegalAccessException e) {
270:                    // TODO Auto-generated catch block
271:                    e.printStackTrace();
272:                    return null;
273:                } catch (InvocationTargetException e) {
274:                    // TODO Auto-generated catch block
275:                    e.printStackTrace();
276:                    return null;
277:                }
278:            }
279:
280:            private static ClassWriter beginProxyClass(
281:                    final String targetClassName, final Class super Class,
282:                    final Class[] interfaces) {
283:
284:                ClassWriter cw = new ClassWriter(true);
285:
286:                int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
287:                        | Opcodes.ACC_STATIC;
288:                String name = toInternalClassName(targetClassName);
289:                String signature = null;
290:                String super name = toInternalClassName(super Class);
291:                String[] interfaceNames = new String[interfaces.length + 1];
292:                for (int i = 0; i < interfaces.length; i++) {
293:                    interfaceNames[i] = toInternalClassName(interfaces[i]);
294:                }
295:                interfaceNames[interfaces.length] = toInternalClassName(InternalJavaProxy.class);
296:
297:                // start class
298:                cw.visit(Opcodes.V1_3, access, name, signature, super name,
299:                        interfaceNames);
300:
301:                cw.visitField(Opcodes.ACC_PRIVATE,
302:                        INVOCATION_HANDLER_FIELD_NAME,
303:                        INVOCATION_HANDLER_TYPE.getDescriptor(), null, null)
304:                        .visitEnd();
305:
306:                cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
307:                        PROXY_CLASS_FIELD_NAME,
308:                        PROXY_CLASS_TYPE.getDescriptor(), null, null)
309:                        .visitEnd();
310:
311:                return cw;
312:            }
313:
314:            private static void generateProxyMethods(Class super Class,
315:                    Map methods, Type selfType, ClassVisitor cw,
316:                    GeneratorAdapter clazzInit) {
317:                Iterator it = methods.values().iterator();
318:                while (it.hasNext()) {
319:                    MethodData md = (MethodData) it.next();
320:                    Type super ClassType = Type.getType(super Class);
321:                    generateProxyMethod(selfType, super ClassType, cw,
322:                            clazzInit, md);
323:                }
324:            }
325:
326:            private static void generateGetInvocationHandler(Type selfType,
327:                    ClassVisitor cw) {
328:                // make getter for handler
329:                GeneratorAdapter gh = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
330:                        new org.objectweb.asm.commons.Method(
331:                                "___getInvocationHandler",
332:                                INVOCATION_HANDLER_TYPE, EMPTY_TYPE_ARR), null,
333:                        EMPTY_TYPE_ARR, cw);
334:
335:                gh.loadThis();
336:                gh.getField(selfType, INVOCATION_HANDLER_FIELD_NAME,
337:                        INVOCATION_HANDLER_TYPE);
338:                gh.returnValue();
339:                gh.endMethod();
340:            }
341:
342:            private static void generateGetProxyClass(Type selfType,
343:                    ClassVisitor cw) {
344:                // make getter for proxy class
345:                GeneratorAdapter gpc = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
346:                        new org.objectweb.asm.commons.Method(
347:                                "___getProxyClass", PROXY_CLASS_TYPE,
348:                                EMPTY_TYPE_ARR), null, EMPTY_TYPE_ARR, cw);
349:                gpc.getStatic(selfType, PROXY_CLASS_FIELD_NAME,
350:                        PROXY_CLASS_TYPE);
351:                gpc.returnValue();
352:                gpc.endMethod();
353:            }
354:
355:            private static void generateConstructors(Class super Class,
356:                    Type selfType, ClassVisitor cw) {
357:                Constructor[] cons = super Class.getConstructors();
358:                for (int i = 0; i < cons.length; i++) {
359:                    Constructor constructor = cons[i];
360:
361:                    int acc = constructor.getModifiers();
362:                    if (Modifier.isProtected(acc) || Modifier.isPublic(acc)) {
363:                        // ok, it's publix or protected
364:                    } else if (!Modifier.isPrivate(acc)
365:                            && packageName(constructor.getDeclaringClass())
366:                                    .equals(
367:                                            packageName(selfType.getClassName()))) {
368:                        // ok, it's package scoped and we're in the same package
369:                    } else {
370:                        // it's unaccessible
371:                        continue;
372:                    }
373:
374:                    generateConstructor(selfType, constructor, cw);
375:                }
376:            }
377:
378:            private static GeneratorAdapter createClassInitializer(
379:                    Type selfType, ClassVisitor cw) {
380:                GeneratorAdapter clazzInit;
381:                clazzInit = new GeneratorAdapter(Opcodes.ACC_PRIVATE
382:                        | Opcodes.ACC_STATIC,
383:                        new org.objectweb.asm.commons.Method("<clinit>",
384:                                Type.VOID_TYPE, EMPTY_TYPE_ARR), null,
385:                        EMPTY_TYPE_ARR, cw);
386:
387:                clazzInit.visitLdcInsn(selfType.getClassName());
388:                clazzInit.invokeStatic(JAVA_LANG_CLASS_TYPE,
389:                        CLASS_FORNAME_METHOD);
390:                clazzInit.invokeStatic(PROXY_HELPER_TYPE,
391:                        HELPER_GET_PROXY_CLASS_METHOD);
392:                clazzInit.dup();
393:                clazzInit.putStatic(selfType, PROXY_CLASS_FIELD_NAME,
394:                        PROXY_CLASS_TYPE);
395:                return clazzInit;
396:            }
397:
398:            private static void generateProxyMethod(Type selfType,
399:                    Type super Type, ClassVisitor cw,
400:                    GeneratorAdapter clazzInit, MethodData md) {
401:                if (!md.generateProxyMethod()) {
402:                    return;
403:                }
404:
405:                org.objectweb.asm.commons.Method m = md.getMethod();
406:                Type[] ex = toType(md.getExceptions());
407:
408:                String field_name = "__mth$" + md.getName()
409:                        + md.scrambledSignature();
410:
411:                // create static private method field
412:                FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE
413:                        | Opcodes.ACC_STATIC, field_name, PROXY_METHOD_TYPE
414:                        .getDescriptor(), null, null);
415:                fv.visitEnd();
416:
417:                clazzInit.dup();
418:                clazzInit.push(m.getName());
419:                clazzInit.push(m.getDescriptor());
420:                clazzInit.push(md.isImplemented());
421:                clazzInit.invokeStatic(PROXY_HELPER_TYPE,
422:                        PROXY_HELPER_GET_METHOD);
423:                clazzInit.putStatic(selfType, field_name, PROXY_METHOD_TYPE);
424:
425:                org.objectweb.asm.commons.Method sm = new org.objectweb.asm.commons.Method(
426:                        "__super$" + m.getName(), m.getReturnType(), m
427:                                .getArgumentTypes());
428:
429:                //
430:                // construct the proxy method
431:                //
432:                GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
433:                        m, null, ex, cw);
434:
435:                ga.loadThis();
436:                ga.getField(selfType, INVOCATION_HANDLER_FIELD_NAME,
437:                        INVOCATION_HANDLER_TYPE);
438:
439:                // if the method is extending something, then we have
440:                // to test if the handler is initialized...
441:
442:                if (md.isImplemented()) {
443:                    ga.dup();
444:                    Label ok = ga.newLabel();
445:                    ga.ifNonNull(ok);
446:
447:                    ga.loadThis();
448:                    ga.loadArgs();
449:                    ga.invokeConstructor(super Type, m);
450:                    ga.returnValue();
451:                    ga.mark(ok);
452:                }
453:
454:                ga.loadThis();
455:                ga.getStatic(selfType, field_name, PROXY_METHOD_TYPE);
456:
457:                if (m.getArgumentTypes().length == 0) {
458:                    // load static empty array
459:                    ga.getStatic(JAVA_PROXY_TYPE, "NO_ARGS", Type
460:                            .getType(Object[].class));
461:                } else {
462:                    // box arguments
463:                    ga.loadArgArray();
464:                }
465:
466:                Label before = ga.mark();
467:
468:                ga.invokeInterface(INVOCATION_HANDLER_TYPE,
469:                        INVOCATION_HANDLER_INVOKE_METHOD);
470:
471:                Label after = ga.mark();
472:
473:                ga.unbox(m.getReturnType());
474:                ga.returnValue();
475:
476:                // this is a simple rethrow handler
477:                Label rethrow = ga.mark();
478:                ga.visitInsn(Opcodes.ATHROW);
479:
480:                for (int i = 0; i < ex.length; i++) {
481:                    ga.visitTryCatchBlock(before, after, rethrow, ex[i]
482:                            .getInternalName());
483:                }
484:
485:                ga
486:                        .visitTryCatchBlock(before, after, rethrow,
487:                                "java/lang/Error");
488:                ga.visitTryCatchBlock(before, after, rethrow,
489:                        "java/lang/RuntimeException");
490:
491:                Type thr = Type.getType(Throwable.class);
492:                Label handler = ga.mark();
493:                Type udt = Type.getType(UndeclaredThrowableException.class);
494:                int loc = ga.newLocal(thr);
495:                ga.storeLocal(loc, thr);
496:                ga.newInstance(udt);
497:                ga.dup();
498:                ga.loadLocal(loc, thr);
499:                ga.invokeConstructor(udt, org.objectweb.asm.commons.Method
500:                        .getMethod("void <init>(java.lang.Throwable)"));
501:                ga.throwException();
502:
503:                ga.visitTryCatchBlock(before, after, handler,
504:                        "java/lang/Throwable");
505:
506:                ga.endMethod();
507:
508:                //
509:                // construct the super-proxy method
510:                //
511:                if (md.isImplemented()) {
512:
513:                    GeneratorAdapter ga2 = new GeneratorAdapter(
514:                            Opcodes.ACC_PUBLIC, sm, null, ex, cw);
515:
516:                    ga2.loadThis();
517:                    ga2.loadArgs();
518:                    ga2.invokeConstructor(super Type, m);
519:                    ga2.returnValue();
520:                    ga2.endMethod();
521:                }
522:            }
523:
524:            private static Class[] generateConstructor(Type selfType,
525:                    Constructor constructor, ClassVisitor cw) {
526:
527:                Class[] super ConstructorParameterTypes = constructor
528:                        .getParameterTypes();
529:                Class[] newConstructorParameterTypes = new Class[super ConstructorParameterTypes.length + 1];
530:                System.arraycopy(super ConstructorParameterTypes, 0,
531:                        newConstructorParameterTypes, 0,
532:                        super ConstructorParameterTypes.length);
533:                newConstructorParameterTypes[super ConstructorParameterTypes.length] = JavaProxyInvocationHandler.class;
534:
535:                int access = Opcodes.ACC_PUBLIC;
536:                String name1 = "<init>";
537:                String signature = null;
538:                Class[] super ConstructorExceptions = constructor
539:                        .getExceptionTypes();
540:
541:                org.objectweb.asm.commons.Method super _m = new org.objectweb.asm.commons.Method(
542:                        name1, Type.VOID_TYPE,
543:                        toType(super ConstructorParameterTypes));
544:                org.objectweb.asm.commons.Method m = new org.objectweb.asm.commons.Method(
545:                        name1, Type.VOID_TYPE,
546:                        toType(newConstructorParameterTypes));
547:
548:                GeneratorAdapter ga = new GeneratorAdapter(access, m,
549:                        signature, toType(super ConstructorExceptions), cw);
550:
551:                ga.loadThis();
552:                ga.loadArgs(0, super ConstructorParameterTypes.length);
553:                ga.invokeConstructor(Type.getType(constructor
554:                        .getDeclaringClass()), super _m);
555:
556:                ga.loadThis();
557:                ga.loadArg(super ConstructorParameterTypes.length);
558:                ga.putField(selfType, INVOCATION_HANDLER_FIELD_NAME,
559:                        INVOCATION_HANDLER_TYPE);
560:
561:                // do a void return
562:                ga.returnValue();
563:                ga.endMethod();
564:                return newConstructorParameterTypes;
565:            }
566:
567:            private static String toInternalClassName(Class clazz) {
568:                return toInternalClassName(clazz.getName());
569:            }
570:
571:            private static String toInternalClassName(String name) {
572:                return name.replace('.', '/');
573:            }
574:
575:            private static Type[] toType(Class[] parameterTypes) {
576:                Type[] result = new Type[parameterTypes.length];
577:                for (int i = 0; i < result.length; i++) {
578:                    result[i] = Type.getType(parameterTypes[i]);
579:                }
580:                return result;
581:            }
582:
583:            private static void collectMethods(Class super Class,
584:                    Class[] interfaces, Map methods, Set names) {
585:                HashSet allClasses = new HashSet();
586:                addClass(allClasses, methods, super Class, names);
587:                addInterfaces(allClasses, methods, interfaces, names);
588:            }
589:
590:            static class MethodData {
591:                Set methods = new HashSet();
592:
593:                final Method mostSpecificMethod;
594:                final Class[] mostSpecificParameterTypes;
595:
596:                boolean hasPublicDecl = false;
597:
598:                MethodData(Method method) {
599:                    this .mostSpecificMethod = method;
600:                    this .mostSpecificParameterTypes = mostSpecificMethod
601:                            .getParameterTypes();
602:                    hasPublicDecl = method.getDeclaringClass().isInterface()
603:                            || Modifier.isPublic(method.getModifiers());
604:                }
605:
606:                public String scrambledSignature() {
607:                    StringBuffer sb = new StringBuffer();
608:                    Class[] parms = getParameterTypes();
609:                    for (int i = 0; i < parms.length; i++) {
610:                        sb.append('$');
611:                        String name = parms[i].getName();
612:                        name = name.replace('[', '1');
613:                        name = name.replace('.', '_');
614:                        name = name.replace(';', '2');
615:                        sb.append(name);
616:                    }
617:                    return sb.toString();
618:                }
619:
620:                public Class getDeclaringClass() {
621:                    return mostSpecificMethod.getDeclaringClass();
622:                }
623:
624:                public org.objectweb.asm.commons.Method getMethod() {
625:                    return new org.objectweb.asm.commons.Method(getName(), Type
626:                            .getType(getReturnType()),
627:                            getType(getParameterTypes()));
628:                }
629:
630:                private Type[] getType(Class[] parameterTypes) {
631:                    Type[] result = new Type[parameterTypes.length];
632:                    for (int i = 0; i < parameterTypes.length; i++) {
633:                        result[i] = Type.getType(parameterTypes[i]);
634:                    }
635:                    return result;
636:                }
637:
638:                private String getName() {
639:                    return mostSpecificMethod.getName();
640:                }
641:
642:                private Class[] getParameterTypes() {
643:                    return mostSpecificParameterTypes;
644:                }
645:
646:                public Class[] getExceptions() {
647:
648:                    Set all = new HashSet();
649:
650:                    Iterator it = methods.iterator();
651:                    while (it.hasNext()) {
652:                        Method m = (Method) it.next();
653:                        Class[] ex = m.getExceptionTypes();
654:                        for (int i = 0; i < ex.length; i++) {
655:                            Class exx = ex[i];
656:
657:                            if (all.contains(exx)) {
658:                                continue;
659:                            }
660:
661:                            boolean add = true;
662:                            Iterator it2 = all.iterator();
663:                            while (it2.hasNext()) {
664:                                Class de = (Class) it2.next();
665:
666:                                if (de.isAssignableFrom(exx)) {
667:                                    add = false;
668:                                    break;
669:                                } else if (exx.isAssignableFrom(de)) {
670:                                    it2.remove();
671:                                    add = true;
672:                                }
673:
674:                            }
675:
676:                            if (add) {
677:                                all.add(exx);
678:                            }
679:                        }
680:                    }
681:
682:                    return (Class[]) all.toArray(new Class[all.size()]);
683:                }
684:
685:                public boolean generateProxyMethod() {
686:                    return !isFinal() && !isPrivate();
687:                }
688:
689:                public void add(Method method) {
690:                    methods.add(method);
691:                    hasPublicDecl |= Modifier.isPublic(method.getModifiers());
692:                }
693:
694:                Class getReturnType() {
695:                    return mostSpecificMethod.getReturnType();
696:                }
697:
698:                boolean isFinal() {
699:                    if (mostSpecificMethod.getDeclaringClass().isInterface()) {
700:                        return false;
701:                    }
702:
703:                    int mod = mostSpecificMethod.getModifiers();
704:                    return Modifier.isFinal(mod);
705:                }
706:
707:                boolean isPrivate() {
708:                    if (mostSpecificMethod.getDeclaringClass().isInterface()) {
709:                        return false;
710:                    }
711:
712:                    int mod = mostSpecificMethod.getModifiers();
713:                    return Modifier.isPrivate(mod);
714:                }
715:
716:                boolean isImplemented() {
717:                    if (mostSpecificMethod.getDeclaringClass().isInterface()) {
718:                        return false;
719:                    }
720:
721:                    int mod = mostSpecificMethod.getModifiers();
722:                    return !Modifier.isAbstract(mod);
723:                }
724:            }
725:
726:            static class MethodKey {
727:                private String name;
728:
729:                private Class[] arguments;
730:
731:                MethodKey(Method m) {
732:                    this .name = m.getName();
733:                    this .arguments = m.getParameterTypes();
734:                }
735:
736:                public boolean equals(Object obj) {
737:                    if (obj instanceof  MethodKey) {
738:                        MethodKey key = (MethodKey) obj;
739:
740:                        return name.equals(key.name)
741:                                && Arrays.equals(arguments, key.arguments);
742:                    }
743:
744:                    return false;
745:                }
746:
747:                public int hashCode() {
748:                    return name.hashCode();
749:                }
750:            }
751:
752:            private static void addInterfaces(Set allClasses, Map methods,
753:                    Class[] interfaces, Set names) {
754:                for (int i = 0; i < interfaces.length; i++) {
755:                    addInterface(allClasses, methods, interfaces[i], names);
756:                }
757:            }
758:
759:            private static void addInterface(Set allClasses, Map methods,
760:                    Class interfaze, Set names) {
761:                if (allClasses.add(interfaze)) {
762:                    addMethods(methods, interfaze, names);
763:                    addInterfaces(allClasses, methods, interfaze
764:                            .getInterfaces(), names);
765:                }
766:            }
767:
768:            private static void addMethods(Map methods, Class classOrInterface,
769:                    Set names) {
770:                Method[] mths = classOrInterface.getDeclaredMethods();
771:                for (int i = 0; i < mths.length; i++) {
772:                    if (names == null || names.contains(mths[i].getName())) {
773:                        addMethod(methods, mths[i]);
774:                    }
775:                }
776:            }
777:
778:            private static void addMethod(Map methods, Method method) {
779:                int acc = method.getModifiers();
780:
781:                if (Modifier.isStatic(acc) || Modifier.isPrivate(acc)) {
782:                    return;
783:                }
784:
785:                MethodKey mk = new MethodKey(method);
786:                MethodData md = (MethodData) methods.get(mk);
787:                if (md == null) {
788:                    md = new MethodData(method);
789:                    methods.put(mk, md);
790:                }
791:                md.add(method);
792:            }
793:
794:            private static void addClass(Set allClasses, Map methods,
795:                    Class clazz, Set names) {
796:                if (allClasses.add(clazz)) {
797:                    addMethods(methods, clazz, names);
798:                    Class super Class = clazz.getSuperclass();
799:                    if (super Class != null) {
800:                        addClass(allClasses, methods, super Class, names);
801:                    }
802:
803:                    addInterfaces(allClasses, methods, clazz.getInterfaces(),
804:                            names);
805:                }
806:            }
807:
808:            private static void validateArgs(String targetClassName,
809:                    Class super Class) {
810:
811:                if (Modifier.isFinal(super Class.getModifiers())) {
812:                    throw new IllegalArgumentException(
813:                            "cannot extend final class");
814:                }
815:
816:                String targetPackage = packageName(targetClassName);
817:
818:                String pkg = targetPackage.replace('.', '/');
819:                if (pkg.startsWith("java")) {
820:                    throw new IllegalArgumentException(
821:                            "cannor add classes to package " + pkg);
822:                }
823:
824:                Package p = Package.getPackage(pkg);
825:                if (p != null) {
826:                    if (p.isSealed()) {
827:                        throw new IllegalArgumentException("package " + p
828:                                + " is sealed");
829:                    }
830:                }
831:            }
832:
833:            private static String packageName(Class clazz) {
834:                String clazzName = clazz.getName();
835:                return packageName(clazzName);
836:            }
837:
838:            private static String packageName(String clazzName) {
839:                int idx = clazzName.lastIndexOf('.');
840:                if (idx == -1) {
841:                    return "";
842:                } else {
843:                    return clazzName.substring(0, idx);
844:                }
845:            }
846:
847:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.