Source Code Cross Referenced for DynamicRuntime.java in  » Scripting » Pnuts » pnuts » compiler » 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 » Pnuts » pnuts.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#)DynamicRuntime.java 1.7 05/05/09
0003:         *
0004:         * Copyright (c) 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
0005:         *
0006:         * See the file "LICENSE.txt" for information on usage and redistribution
0007:         * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
0008:         */
0009:        package pnuts.compiler;
0010:
0011:        import java.lang.reflect.Constructor;
0012:        import java.lang.reflect.Field;
0013:        import java.lang.reflect.InvocationTargetException;
0014:        import java.lang.reflect.Method;
0015:        import java.lang.reflect.Modifier;
0016:        import java.security.AccessController;
0017:        import java.security.PrivilegedAction;
0018:        import java.util.Map;
0019:        import java.util.HashMap;
0020:        import java.util.WeakHashMap;
0021:        import java.io.IOException;
0022:
0023:        import org.pnuts.util.*;
0024:        import org.pnuts.lang.*;
0025:
0026:        import pnuts.lang.Context;
0027:        import pnuts.lang.Pnuts;
0028:        import pnuts.lang.PnutsException;
0029:        import pnuts.lang.PnutsFunction;
0030:        import pnuts.lang.Runtime;
0031:
0032:        public class DynamicRuntime extends Runtime {
0033:            private final static boolean DEBUG = false;
0034:            private final static Object[] noarg = new Object[] {};
0035:
0036:            private CodeLoader codeLoader = null;
0037:            static boolean hasCollection = false;
0038:            static {
0039:                try {
0040:                    Class.forName("java.util.Collection");
0041:                    hasCollection = true;
0042:                } catch (Exception e) {
0043:                }
0044:            }
0045:
0046:            /**
0047:             * call a method
0048:             */
0049:            protected Object _callMethod(Context context, Class c, String name,
0050:                    Object args[], Class types[], Object target) {
0051:                try {
0052:                    ClassLoader cl = codeLoader;
0053:                    synchronized (this ) {
0054:                        if (cl == null) {
0055:                            cl = Compiler.createCodeLoader(context
0056:                                    .getClassLoader(), true);
0057:                            codeLoader = (CodeLoader) cl;
0058:                        }
0059:                    }
0060:                    return callMethod(context, c, name, args, types, target,
0061:                            (CodeLoader) cl);
0062:                } catch (IllegalAccessException e0) {
0063:                    throw new PnutsException(e0, context);
0064:                } catch (InvocationTargetException e1) {
0065:                    Throwable t = e1.getTargetException();
0066:                    if (t instanceof  PnutsException) {
0067:                        throw (PnutsException) t;
0068:                    } else {
0069:                        throw new PnutsException(t, context);
0070:                    }
0071:                } catch (NoMemberFoundException e2) {
0072:                    throw new PnutsException("method.notFound", new Object[] {
0073:                            name, c.getName(), Pnuts.format(args) }, context);
0074:                } catch (PnutsException e3) {
0075:                    throw e3;
0076:                } catch (Throwable e4) {
0077:                    throw new PnutsException(e4, context);
0078:                }
0079:            }
0080:
0081:            Object callMethod(Context context, Class c, String name,
0082:                    Object args[], Class types[], Object target,
0083:                    CodeLoader codeLoader) throws IllegalAccessException,
0084:                    IllegalArgumentException, InvocationTargetException {
0085:                ProxyCache methodCache = null;
0086:
0087:                if (name == CLONE && args.length == 0) {
0088:                    if (target instanceof  Object[]) {
0089:                        return ((Object[]) target).clone();
0090:                    } else if (target instanceof  int[]) {
0091:                        return ((int[]) target).clone();
0092:                    } else if (target instanceof  byte[]) {
0093:                        return ((byte[]) target).clone();
0094:                    } else if (target instanceof  short[]) {
0095:                        return ((short[]) target).clone();
0096:                    } else if (target instanceof  char[]) {
0097:                        return ((char[]) target).clone();
0098:                    } else if (target instanceof  long[]) {
0099:                        return ((long[]) target).clone();
0100:                    } else if (target instanceof  float[]) {
0101:                        return ((float[]) target).clone();
0102:                    } else if (target instanceof  double[]) {
0103:                        return ((double[]) target).clone();
0104:                    } else if (target instanceof  boolean[]) {
0105:                        return ((boolean[]) target).clone();
0106:                    }
0107:                }
0108:
0109:                ProxyCache[] m = methodFinder.getMethods(context, c, name);
0110:                if (m == null) {
0111:                    return super ._callMethod(context, c, name, args, types,
0112:                            target);
0113:                }
0114:
0115:                int count = 0;
0116:                int min = Integer.MAX_VALUE;
0117:                Stack methods = new Stack();
0118:                int nargs = args.length;
0119:                cand: for (int i = 0; i < m.length; i++) {
0120:                    Class p[] = m[i].paramTypes;
0121:                    if (p.length != nargs) {
0122:                        continue;
0123:                    }
0124:                    count = 0;
0125:                    for (int j = 0; j < p.length; j++) {
0126:                        Class pj = p[j];
0127:                        if (types != null) {
0128:                            Class tj = types[j];
0129:                            if (tj != null && pj != tj
0130:                                    && !pj.isAssignableFrom(tj)) {
0131:                                continue cand;
0132:                            }
0133:                        }
0134:                        int t = matchType(pj, args[j]);
0135:                        if (t < 0) {
0136:                            continue cand;
0137:                        }
0138:                        count += t;
0139:                    }
0140:                    if (count > min) {
0141:                        continue;
0142:                    }
0143:
0144:                    if ((m[i].type == ProxyCache.STATIC) != (target == null)) {
0145:                        continue;
0146:                    }
0147:
0148:                    if (count < min) {
0149:                        methods.removeAllElements();
0150:                        methods.push(m[i]);
0151:                        min = count;
0152:                    } else if (count == min) {
0153:                        methods.push(m[i]);
0154:                        if (DEBUG) {
0155:                            System.out.println("push " + m[i]);
0156:                        }
0157:                    }
0158:                }
0159:
0160:                Class clazz = c;
0161:                out: while (clazz != null) {
0162:                    int size = methods.size();
0163:                    for (int i = 0; i < size; i++) {
0164:                        methodCache = (ProxyCache) methods.pop();
0165:                        if (methodCache.declaringClass == clazz) {
0166:                            break out;
0167:                        }
0168:                    }
0169:                    clazz = clazz.getSuperclass();
0170:                }
0171:
0172:                if (methodCache != null) {
0173:                    boolean retry = false;
0174:                    while (true) {
0175:                        try {
0176:                            if (methodCache.proxy == null || retry) {
0177:                                methodCache.proxy = DynamicProxyFactory
0178:                                        .makeProxy(name,
0179:                                                methodCache.targetClass,
0180:                                                methodCache.returnType,
0181:                                                methodCache.paramTypes,
0182:                                                methodCache.type, codeLoader);
0183:                            }
0184:                            if (nargs == 0) {
0185:                                return methodCache.invoke(target);
0186:                            } else {
0187:                                return methodCache.invoke(target, args);
0188:                            }
0189:                        } catch (ClassCastException cce) {
0190:                            if (!retry) {
0191:                                codeLoader = Compiler.createCodeLoader(
0192:                                        getClassLoader(c), true);
0193:                                if (DEBUG) {
0194:                                    System.out.println("retry");
0195:                                }
0196:                                retry = true;
0197:                                continue;
0198:                            }
0199:                            if (DEBUG) {
0200:                                System.out.println("use reflection");
0201:                            }
0202:                            methodFinder.useReflection(c);
0203:                            return super ._callMethod(context, c, name, args,
0204:                                    types, target);
0205:                        } catch (LinkageError err) {
0206:                            if (DEBUG) {
0207:                                System.out.println(err + " , " + codeLoader);
0208:                            }
0209:                            if (!retry) {
0210:                                codeLoader = Compiler.createCodeLoader(
0211:                                        getClassLoader(c), true);
0212:                                if (DEBUG) {
0213:                                    System.out.println("retry");
0214:                                }
0215:                                retry = true;
0216:                                continue;
0217:                            }
0218:                            if (DEBUG) {
0219:                                System.out.println("use reflection");
0220:                            }
0221:                            methodFinder.useReflection(c);
0222:                            return super ._callMethod(context, c, name, args,
0223:                                    types, target);
0224:                        } catch (PnutsException pex) {
0225:                            throw pex;
0226:                        } catch (Throwable t) {
0227:                            if (t instanceof  ClassNotFoundException) {
0228:                                if (DEBUG) {
0229:                                    System.out.println(t);
0230:                                }
0231:                                if (DEBUG) {
0232:                                    System.out.println("use reflection");
0233:                                }
0234:                                methodFinder.useReflection(c);
0235:                                return super ._callMethod(context, c, name,
0236:                                        args, types, target);
0237:                            } else {
0238:                                throw new PnutsException(t, context);
0239:                            }
0240:                        }
0241:                    }
0242:                } else {
0243:                    if (target instanceof  Class) {
0244:                        return callMethod(context, (Class) target, name, args,
0245:                                types, null, codeLoader);
0246:                    }
0247:                    throw new NoMemberFoundException();
0248:                }
0249:            }
0250:
0251:            protected Object _callConstructor(Context context, Class c,
0252:                    Object args[], Class types[]) {
0253:                try {
0254:                    ClassLoader cl = codeLoader;
0255:                    synchronized (this ) {
0256:                        if (cl == null) {
0257:                            cl = Compiler.createCodeLoader(context
0258:                                    .getClassLoader(), true);
0259:                            codeLoader = (CodeLoader) cl;
0260:                        }
0261:                    }
0262:                    return _callConstructor(context, c, args, types,
0263:                            (CodeLoader) cl);
0264:
0265:                } catch (InvocationTargetException e1) {
0266:                    Throwable t = ((InvocationTargetException) e1)
0267:                            .getTargetException();
0268:                    if (t instanceof  PnutsException) {
0269:                        throw (PnutsException) t;
0270:                    } else {
0271:                        throw new PnutsException(t, context);
0272:                    }
0273:                } catch (NoMemberFoundException e2) {
0274:                    throw new PnutsException("constructor.notFound",
0275:                            new Object[] { c, Pnuts.format(args) }, context);
0276:                } catch (PnutsException e3) {
0277:                    throw e3;
0278:                } catch (Throwable e4) {
0279:                    throw new PnutsException(e4, context);
0280:                }
0281:            }
0282:
0283:            protected Object _callConstructor(Context context, Class c,
0284:                    Object args[], Class types[], CodeLoader codeLoader)
0285:                    throws IllegalAccessException, IllegalArgumentException,
0286:                    InvocationTargetException, InstantiationException {
0287:                ProxyCache cs[] = methodFinder.getConstructors(context, c);
0288:                ProxyCache cons = null;
0289:
0290:                if (cs == null) {
0291:                    return super ._callConstructor(context, c, args, types);
0292:                }
0293:
0294:                int count = 0;
0295:                int min = Integer.MAX_VALUE;
0296:                cand: for (int i = 0; i < cs.length; i++) {
0297:                    Class p[] = cs[i].paramTypes;
0298:                    if (p.length != args.length) {
0299:                        continue;
0300:                    }
0301:                    count = 0;
0302:                    for (int j = 0; j < p.length; j++) {
0303:                        Class pj = p[j];
0304:                        if (types != null) {
0305:                            Class tj = types[j];
0306:                            if (tj != null && pj != tj
0307:                                    && !pj.isAssignableFrom(tj)) {
0308:                                continue cand;
0309:                            }
0310:                        }
0311:                        int t = matchType(pj, args[j]);
0312:                        if (t < 0) {
0313:                            continue cand;
0314:                        }
0315:                        count += t;
0316:                    }
0317:                    if (count < min) {
0318:                        min = count;
0319:                        cons = cs[i];
0320:                    }
0321:                }
0322:                if (cons != null) {
0323:                    boolean retry = false;
0324:                    while (true) {
0325:                        if (cons.proxy == null || retry) {
0326:                            cons.proxy = DynamicProxyFactory.makeProxy(
0327:                                    "<init>", cons.declaringClass,
0328:                                    cons.returnType, cons.paramTypes,
0329:                                    ProxyCache.CONSTRUCTOR, codeLoader);
0330:                        }
0331:                        try {
0332:                            if (args.length == 0) {
0333:                                return cons.invoke(null);
0334:                            } else {
0335:                                return cons.invoke(null, args);
0336:                            }
0337:                        } catch (ClassCastException cce) {
0338:                            if (DEBUG) {
0339:                                System.out.println(cce);
0340:                            }
0341:                            if (!retry) {
0342:                                codeLoader = Compiler.createCodeLoader(
0343:                                        getClassLoader(c), true);
0344:                                if (DEBUG) {
0345:                                    System.out.println("retry");
0346:                                }
0347:                                retry = true;
0348:                                continue;
0349:                            }
0350:                            methodFinder.useReflection(c);
0351:                            return super ._callConstructor(context, c, args,
0352:                                    types);
0353:                        } catch (LinkageError err) {
0354:                            if (DEBUG) {
0355:                                System.out.println(err);
0356:                            }
0357:                            if (!retry) {
0358:                                codeLoader = Compiler.createCodeLoader(
0359:                                        getClassLoader(c), true);
0360:                                if (DEBUG) {
0361:                                    System.out.println("retry");
0362:                                }
0363:                                retry = true;
0364:                                continue;
0365:                            }
0366:                            methodFinder.useReflection(c);
0367:                            return super ._callConstructor(context, c, args,
0368:                                    types);
0369:                        } catch (PnutsException pex) {
0370:                            throw pex;
0371:                        } catch (Throwable t) {
0372:                            /* jdk1.1.8 throws ClassNotFoundException instead of NoClassDefFoundError */
0373:                            if (DEBUG) {
0374:                                System.out.println(t);
0375:                            }
0376:                            if (t instanceof  ClassNotFoundException
0377:                                    || t instanceof  IllegalAccessError) {
0378:                                methodFinder.useReflection(c);
0379:                                return super ._callConstructor(context, c, args,
0380:                                        types);
0381:                            } else {
0382:                                throw new PnutsException(t, context);
0383:                            }
0384:                        }
0385:                    }
0386:                } else {
0387:                    throw new NoMemberFoundException();
0388:                }
0389:            }
0390:
0391:            static class ProxyCache {
0392:                final static int DEFAULT = 0;
0393:                final static int STATIC = 1;
0394:                final static int CONSTRUCTOR = 2;
0395:
0396:                Class[] paramTypes;
0397:                Class declaringClass;
0398:                Class targetClass;
0399:                Class returnType;
0400:                int type;
0401:                DynamicProxy proxy;
0402:                boolean hasArrayParam;
0403:
0404:                ProxyCache(Method method, Class clazz) {
0405:                    this .paramTypes = method.getParameterTypes();
0406:                    this .declaringClass = method.getDeclaringClass();
0407:                    this .returnType = method.getReturnType();
0408:                    this .type = Modifier.isStatic(method.getModifiers()) ? STATIC
0409:                            : DEFAULT;
0410:                    this .targetClass = clazz;
0411:                    init();
0412:                }
0413:
0414:                ProxyCache(Constructor cons) {
0415:                    this .paramTypes = cons.getParameterTypes();
0416:                    this .declaringClass = cons.getDeclaringClass();
0417:                    this .targetClass = cons.getDeclaringClass();
0418:                    this .returnType = void.class;
0419:                    this .type = CONSTRUCTOR;
0420:                    init();
0421:                }
0422:
0423:                void init() {
0424:                    Class[] types = this .paramTypes;
0425:                    for (int i = 0; i < types.length; i++) {
0426:                        if (types[i].isArray()) {
0427:                            hasArrayParam = true;
0428:                            break;
0429:                        }
0430:                    }
0431:                }
0432:
0433:                Object invoke(Object target) {
0434:                    return proxy.invoke(target);
0435:                }
0436:
0437:                Object invoke(Object target, Object[] args) {
0438:                    if (hasArrayParam) {
0439:                        for (int i = 0; i < paramTypes.length; i++) {
0440:                            Class type = paramTypes[i];
0441:                            Object arg = args[i];
0442:                            if (arg != null && type.isArray()
0443:                                    && !type.isInstance(arg)) {
0444:                                args[i] = transform(type, arg);
0445:                            }
0446:                        }
0447:                    }
0448:                    return proxy.invoke(target, args);
0449:                }
0450:            }
0451:
0452:            static abstract class MethodFinder {
0453:                public abstract ProxyCache[] getConstructors(Context context,
0454:                        Class c);
0455:
0456:                public abstract ProxyCache[] getMethods(Context context,
0457:                        Class c, String name);
0458:
0459:                public abstract void useReflection(Class c);
0460:            }
0461:
0462:            static class Java2MethodFinder extends MethodFinder {
0463:                private Map mtab = Runtime.createWeakMap();
0464:                private Map ctab = Runtime.createWeakMap();
0465:
0466:                private static java.lang.ref.SoftReference USE_REFLECTION = new java.lang.ref.SoftReference(
0467:                        Runtime.createWeakMap());
0468:
0469:                public void useReflection(Class c) {
0470:                    if (DEBUG) {
0471:                        System.out.println("use reflection for " + c.getName());
0472:                    }
0473:                    mtab.put(c, USE_REFLECTION);
0474:                    ctab.put(c, USE_REFLECTION);
0475:                }
0476:
0477:                public ProxyCache[] getMethods(Context context, Class c,
0478:                        String name) {
0479:                    java.lang.ref.SoftReference cache = (java.lang.ref.SoftReference) mtab
0480:                            .get(c);
0481:                    Map map;
0482:                    if (cache == null || (map = (Map) cache.get()) == null) {
0483:                        map = Runtime.createWeakMap();
0484:                        mtab.put(c, new java.lang.ref.SoftReference(map));
0485:                    } else if (cache == USE_REFLECTION) {
0486:                        return null;
0487:                    }
0488:                    Object v = map.get(name);
0489:                    if (v instanceof  ProxyCache[]) {
0490:                        return (ProxyCache[]) v;
0491:                    } else {
0492:                        if (DEBUG) {
0493:                            System.out.println(c + ":" + name);
0494:                        }
0495:                        //				boolean isPublic = Modifier.isPublic(c.getModifiers());
0496:
0497:                        Method m[] = Runtime.getMethods(context, c);
0498:                        if (m == null) { // for Bug:4137722
0499:                            throw new NoClassDefFoundError("" + c);
0500:                        }
0501:                        int j = 0;
0502:                        for (int i = 0; i < m.length; i++) {
0503:                            String m_name = m[i].getName();
0504:                            if (m_name.equals(name) && i >= j) {
0505:                                m[j] = m[i];
0506:                                j++;
0507:                            }
0508:                        }
0509:                        ProxyCache px[] = new ProxyCache[j];
0510:                        for (int i = 0; i < j; i++) {
0511:                            Method mi = findCallableMethod(c, m[i].getName(),
0512:                                    m[i].getParameterTypes());
0513:                            if (mi != null) {
0514:                                px[i] = new ProxyCache(mi, c);
0515:                            } else {
0516:                                px[i] = new ProxyCache(m[i], c);
0517:                            }
0518:                        }
0519:                        map.put(name, px);
0520:                        return px;
0521:                    }
0522:                }
0523:
0524:                public ProxyCache[] getConstructors(Context context, Class c) {
0525:
0526:                    java.lang.ref.SoftReference cache = (java.lang.ref.SoftReference) ctab
0527:                            .get(c);
0528:                    ProxyCache[] pc;
0529:                    if (cache == USE_REFLECTION) {
0530:                        return null;
0531:                    } else if (cache == null
0532:                            || (pc = (ProxyCache[]) cache.get()) == null) {
0533:                        Constructor con[] = Runtime.getConstructors(context, c);
0534:                        ProxyCache px[] = new ProxyCache[con.length];
0535:                        for (int i = 0; i < con.length; i++) {
0536:                            px[i] = new ProxyCache(con[i]);
0537:                        }
0538:                        ctab.put(c, new java.lang.ref.SoftReference(px));
0539:                        return px;
0540:                    } else {
0541:                        return pc;
0542:                    }
0543:                }
0544:            }
0545:
0546:            /**
0547:             * This method maps a proxy object of a Constructor to a PnutsFunction.
0548:             * Call of the resulting function is faster than reflection API calls.
0549:             *
0550:             * @param cons	a constructor
0551:             * @return	an instance the constructor creates.
0552:             */
0553:            public static PnutsFunction makeProxy(Constructor cons) {
0554:                final DynamicProxy px = DynamicProxyFactory.makeProxy(cons,
0555:                        Compiler.createCodeLoader(getClassLoader(cons
0556:                                .getDeclaringClass()), true));
0557:
0558:                if (cons.getParameterTypes().length == 0) {
0559:                    return new PnutsFunction() {
0560:                        public Object exec(Object[] args, Context context) {
0561:                            return px.invoke(null);
0562:                        }
0563:                    };
0564:                } else {
0565:                    return new PnutsFunction() {
0566:                        public Object exec(Object[] args, Context context) {
0567:                            return px.invoke(null, args);
0568:                        }
0569:                    };
0570:                }
0571:            }
0572:
0573:            /**
0574:             * This method maps a proxy object of a Method to a PnutsFunction.
0575:             * Call of the resulting function is expected to be faster than
0576:             * reflection API calls.
0577:             *
0578:             * @param method	a method
0579:             * @return	the result of the 'method' call.
0580:             */
0581:            public static PnutsFunction makeProxy(Method method) {
0582:                final DynamicProxy px = DynamicProxyFactory.makeProxy(method,
0583:                        Compiler.createCodeLoader(getClassLoader(method
0584:                                .getDeclaringClass()), true));
0585:                final String _name = method.getName();
0586:                boolean _static = Modifier.isStatic(method.getModifiers());
0587:                int nargs = method.getParameterTypes().length;
0588:
0589:                if (_static) {
0590:                    if (nargs == 0) {
0591:                        return new PnutsFunction() {
0592:                            public String getName() {
0593:                                return _name;
0594:                            }
0595:
0596:                            public Object exec(Object[] args, Context context) {
0597:                                return px.invoke(null);
0598:                            }
0599:                        };
0600:                    } else {
0601:                        return new PnutsFunction() {
0602:                            public String getName() {
0603:                                return _name;
0604:                            }
0605:
0606:                            public Object exec(Object[] args, Context context) {
0607:                                return px.invoke(null, args);
0608:                            }
0609:                        };
0610:                    }
0611:                } else {
0612:                    if (nargs == 0) {
0613:                        return new PnutsFunction() {
0614:                            public String getName() {
0615:                                return _name;
0616:                            }
0617:
0618:                            public Object exec(Object[] args, Context context) {
0619:                                return px.invoke(args[0]);
0620:                            }
0621:                        };
0622:                    } else {
0623:                        return new PnutsFunction() {
0624:                            public String getName() {
0625:                                return _name;
0626:                            }
0627:
0628:                            public Object exec(Object[] args, Context context) {
0629:                                Object target = args[0];
0630:                                System.arraycopy(args, 1, args, 0,
0631:                                        args.length - 1);
0632:                                return px.invoke(target, args);
0633:                            }
0634:                        };
0635:                    }
0636:                }
0637:            }
0638:
0639:            static ClassLoader getClassLoader(final Class clazz) {
0640:                if (Compiler.hasJava2Security) {
0641:                    return (ClassLoader) AccessController
0642:                            .doPrivileged(new PrivilegedAction() {
0643:                                public Object run() {
0644:                                    return clazz.getClassLoader();
0645:                                }
0646:                            });
0647:                } else {
0648:                    return clazz.getClassLoader();
0649:                }
0650:            }
0651:
0652:            static class NoMemberFoundException extends RuntimeException {
0653:            }
0654:
0655:            static MethodFinder methodFinder = new Java2MethodFinder();
0656:
0657:            private Map beanAccessors = Runtime.createWeakMap();
0658:
0659:            static class BeanInfoParam {
0660:                Class targetClass;
0661:
0662:                Class stopClass;
0663:
0664:                BeanInfoParam(Class targetClass, Class stopClass) {
0665:                    this .targetClass = targetClass;
0666:                    this .stopClass = stopClass;
0667:                }
0668:
0669:                public int hashCode() {
0670:                    return targetClass.hashCode() ^ stopClass.hashCode();
0671:                }
0672:
0673:                public boolean equals(Object that) {
0674:                    if (that instanceof  BeanInfoParam) {
0675:                        BeanInfoParam p = (BeanInfoParam) that;
0676:                        return p.targetClass == this .targetClass
0677:                                && p.stopClass == this .stopClass;
0678:                    }
0679:                    return false;
0680:                }
0681:            }
0682:
0683:            private Accessor getAccessor(Class cls, Class stopClass) {
0684:                Object key;
0685:                if (stopClass == null) {
0686:                    key = cls;
0687:                } else {
0688:                    key = new BeanInfoParam(cls, stopClass);
0689:                }
0690:                java.lang.ref.SoftReference ref = (java.lang.ref.SoftReference) beanAccessors
0691:                        .get(key);
0692:                if (ref == null) {
0693:                    Accessor a = createBeanAccessor(cls, stopClass);
0694:                    beanAccessors.put(key, new java.lang.ref.SoftReference(a));
0695:                    return a;
0696:                } else {
0697:                    Accessor a = (Accessor) ref.get();
0698:                    if (a == null) {
0699:                        a = createBeanAccessor(cls, stopClass);
0700:                        beanAccessors.put(key, new java.lang.ref.SoftReference(
0701:                                a));
0702:                    }
0703:                    return a;
0704:                }
0705:            }
0706:
0707:            private Accessor createBeanAccessor(Class cls, Class stopClass) {
0708:                return new DynamicAccessor(cls, stopClass);
0709:            }
0710:
0711:            protected static class DynamicAccessor extends
0712:                    pnuts.lang.Runtime.Accessor {
0713:                boolean isPublic;
0714:
0715:                protected DynamicAccessor(Class cls, Class stopClass) {
0716:                    super (cls, stopClass);
0717:                    this .isPublic = Modifier.isPublic(cls.getModifiers());
0718:                }
0719:
0720:                public void addReadMethod(String name, Object method) {
0721:                    Method m = (Method) method;
0722:                    Method m0 = m;
0723:                    if (!isPublic) {
0724:                        String methodName = m.getName();
0725:                        Class[] types = m.getParameterTypes();
0726:                        m = findCallableMethod(beanClass, methodName, types);
0727:                    }
0728:                    if (m != null) {
0729:                        CodeLoader loader = Compiler.createCodeLoader(
0730:                                getClassLoader(m.getDeclaringClass()), true);
0731:                        DynamicProxy px = DynamicProxyFactory.makeProxy(m,
0732:                                loader);
0733:                        ProxyCache pc = new ProxyCache(m, beanClass);
0734:                        pc.proxy = px;
0735:                        super .addReadMethod(name, pc);
0736:                    } else {
0737:                        DynamicProxy px = createReflectionProxy(beanClass,
0738:                                name, stopClass);
0739:                        ProxyCache pc = new ProxyCache(m0, beanClass);
0740:                        pc.proxy = px;
0741:                        super .addReadMethod(name, pc);
0742:                        super .addWriteMethod(name, pc);
0743:                    }
0744:                }
0745:
0746:                public void addWriteMethod(String name, Object method) {
0747:                    Method m = (Method) method;
0748:                    Method m0 = m;
0749:                    if (!isPublic) {
0750:                        String methodName = m.getName();
0751:                        Class[] types = m.getParameterTypes();
0752:                        m = findCallableMethod(beanClass, methodName, types);
0753:                    }
0754:                    if (m != null) {
0755:                        CodeLoader loader = Compiler.createCodeLoader(
0756:                                getClassLoader(m.getDeclaringClass()), true);
0757:                        DynamicProxy px = DynamicProxyFactory.makeProxy(m,
0758:                                loader);
0759:                        ProxyCache pc = new ProxyCache(m, beanClass);
0760:                        pc.proxy = px;
0761:                        super .addWriteMethod(name, pc);
0762:                    } else {
0763:                        DynamicProxy px = createReflectionProxy(beanClass,
0764:                                name, stopClass);
0765:                        ProxyCache pc = new ProxyCache(m0, beanClass);
0766:                        pc.proxy = px;
0767:                        super .addReadMethod(name, pc);
0768:                        super .addWriteMethod(name, pc);
0769:                    }
0770:                }
0771:            }
0772:
0773:            static void createMethodMap(ObjectDesc d, final Map readMethods,
0774:                    final Map writeMethods) {
0775:                d.handleProperties(new PropertyHandler() {
0776:                    public void handle(String propertyName, Class type,
0777:                            Method readMethod, Method writeMethod) {
0778:                        if (readMethod != null) {
0779:                            readMethods.put(propertyName, readMethod);
0780:                        }
0781:                        if (writeMethod != null) {
0782:                            writeMethods.put(propertyName, writeMethod);
0783:                        }
0784:                    }
0785:                });
0786:            }
0787:
0788:            static DynamicProxy createReflectionProxy(Class cls, String name,
0789:                    Class stopClass) {
0790:                ObjectDesc od = ObjectDescFactory.getDefault().create(cls,
0791:                        stopClass);
0792:                Map rmap = new HashMap();
0793:                Map wmap = new HashMap();
0794:                createMethodMap(od, rmap, wmap);
0795:                Method w = (Method) rmap.get(name);
0796:                Method r = (Method) wmap.get(name);
0797:                if (r != null) {
0798:                    r.setAccessible(true);
0799:                }
0800:                if (w != null) {
0801:                    w.setAccessible(true);
0802:                }
0803:                final Method readMethod = r;
0804:                final Method writeMethod = w;
0805:                DynamicProxy px = new DynamicProxy() {
0806:                    public Object invoke(Object target) {
0807:                        try {
0808:                            return readMethod.invoke(target, noarg);
0809:                        } catch (IllegalAccessException iae) {
0810:                        } catch (InvocationTargetException ite) {
0811:                        }
0812:                        return null;
0813:                    }
0814:
0815:                    public Object invoke(Object target, Object[] args) {
0816:                        try {
0817:                            writeMethod.invoke(target, args);
0818:                        } catch (IllegalAccessException iae) {
0819:                        } catch (InvocationTargetException ite) {
0820:                        }
0821:                        return null;
0822:                    }
0823:                };
0824:                return px;
0825:            }
0826:
0827:            /**
0828:             * Gets a Bean property of the specified bean.
0829:             *
0830:             * @param target the target bean
0831:             * @param name the Bean property name
0832:             */
0833:            public Object getBeanProperty(Object target, String name)
0834:                    throws IllegalAccessException {
0835:                return getBeanProperty(target, name, null);
0836:            }
0837:
0838:            /**
0839:             * Gets a Bean property of the specified bean.
0840:             *
0841:             * @param target the target bean
0842:             * @param name the Bean property name
0843:             * @param stopClass the Introspector's "stopClass"
0844:             */
0845:            protected Object getBeanProperty(Object target, String name,
0846:                    Class stopClass) throws IllegalAccessException {
0847:                pnuts.lang.Runtime.Accessor a = getAccessor(target.getClass(),
0848:                        stopClass);
0849:                ProxyCache readMethodProxy = (ProxyCache) a
0850:                        .findReadMethod(name);
0851:                if (readMethodProxy != null) {
0852:                    return readMethodProxy.invoke(target);
0853:                }
0854:                if (target instanceof  Class) {
0855:                    Class cls = (Class) target;
0856:                    Field field = getField(cls, name);
0857:                    if (field != null
0858:                            && Modifier.isStatic(field.getModifiers())) {
0859:                        return field.get(null);
0860:                    }
0861:                }
0862:                if (a.findWriteMethod(name) == null) {
0863:                    Class cls = target.getClass();
0864:                    Field field = getField(cls, name);
0865:                    if (field != null
0866:                            && !Modifier.isStatic(field.getModifiers())) {
0867:                        return field.get(target);
0868:                    }
0869:                }
0870:                throw new IllegalArgumentException(
0871:                        "not readable property: target=" + target
0872:                                + ", fieldName=" + name);
0873:            }
0874:
0875:            /**
0876:             * Sets a Bean property of the specified bean.
0877:             *
0878:             * @param target the target bean
0879:             * @param name the Bean property name
0880:             * @param value the new property value
0881:             */
0882:            public void setBeanProperty(Object target, String name, Object value)
0883:                    throws IllegalAccessException, InvocationTargetException {
0884:                setBeanProperty(target, name, value, null);
0885:            }
0886:
0887:            /**
0888:             * Sets a Bean property of the specified bean.
0889:             *
0890:             * @param target the target bean
0891:             * @param name the Bean property name
0892:             * @param value the new property value
0893:             * @param stopClass the Introspector's "stopClass"
0894:             */
0895:            protected void setBeanProperty(Object target, String name,
0896:                    Object value, Class stopClass)
0897:                    throws IllegalAccessException, InvocationTargetException {
0898:                pnuts.lang.Runtime.Accessor a = getAccessor(target.getClass(),
0899:                        stopClass);
0900:                ProxyCache writeMethodProxy = (ProxyCache) a
0901:                        .findWriteMethod(name);
0902:                if (writeMethodProxy != null) {
0903:                    try {
0904:                        Object[] arg = new Object[] { value };
0905:                        writeMethodProxy.invoke(target, arg);
0906:                        return;
0907:                    } catch (ClassCastException cce) {
0908:                        try {
0909:                            super .setBeanProperty(target, name, value,
0910:                                    stopClass);
0911:                            return;
0912:                        } catch (Exception e) {
0913:                            Class type = getBeanPropertyType(target.getClass(),
0914:                                    name);
0915:
0916:                            String msg = getMessage("pnuts.lang.pnuts",
0917:                                    "type.mismatch", new Object[] { type,
0918:                                            target, name, value,
0919:                                            value.getClass().getName() });
0920:                            throw new IllegalArgumentException(msg);
0921:                        }
0922:                    }
0923:                }
0924:                if (target instanceof  Class) {
0925:                    Class cls = (Class) target;
0926:                    Field field = getField(cls, name);
0927:                    if (field != null
0928:                            && Modifier.isStatic(field.getModifiers())) {
0929:                        field.set(null, value);
0930:                        return;
0931:                    }
0932:                }
0933:                if (a.findReadMethod(name) == null) {
0934:                    Class cls = target.getClass();
0935:                    Field field = getField(cls, name);
0936:                    if (field != null
0937:                            && !Modifier.isStatic(field.getModifiers())) {
0938:                        field.set(target, value);
0939:                        return;
0940:                    }
0941:                }
0942:                throw new IllegalArgumentException(
0943:                        "not writable property: target=" + target
0944:                                + ", fieldName=" + name);
0945:            }
0946:
0947:            /**
0948:             * Gets the type of a bean property
0949:             *
0950:             * @param cls the class of the bean
0951:             * @param name the property name of the bean property
0952:             * @return the type of the property
0953:             */
0954:            public Class getBeanPropertyType(Class cls, String name) {
0955:                return getAccessor(cls, null).getType(name);
0956:            }
0957:
0958:            protected Object _getField(Context context, Class c, String name,
0959:                    Object target) {
0960:                try {
0961:                    ClassLoader cl = codeLoader;
0962:                    synchronized (this ) {
0963:                        if (cl == null) {
0964:                            cl = Compiler.createCodeLoader(context
0965:                                    .getClassLoader(), true);
0966:                            codeLoader = (CodeLoader) cl;
0967:                        }
0968:                    }
0969:                    return _getField(context, c, name, target, (CodeLoader) cl);
0970:                } catch (NoSuchFieldException nsf) {
0971:                    throw new PnutsException("field.notFound", new Object[] {
0972:                            name, target }, context);
0973:                } catch (Exception e) {
0974:                    throw new PnutsException(e, context);
0975:                }
0976:            }
0977:
0978:            protected void _putField(Context context, Class c, String name,
0979:                    Object target, Object value) {
0980:                try {
0981:                    ClassLoader cl = codeLoader;
0982:                    synchronized (this ) {
0983:                        if (cl == null) {
0984:                            cl = Compiler.createCodeLoader(context
0985:                                    .getClassLoader(), true);
0986:                            codeLoader = (CodeLoader) cl;
0987:                        }
0988:                    }
0989:                    _putField(context, c, name, target, value, (CodeLoader) cl);
0990:                } catch (Exception e) {
0991:                    throw new PnutsException(e, context);
0992:                }
0993:            }
0994:
0995:            Object _getField(Context context, Class c, String name,
0996:                    Object target, CodeLoader codeLoader)
0997:                    throws NoSuchFieldException, InstantiationException,
0998:                    IOException, IllegalAccessException {
0999:                FieldAccessor fa = (FieldAccessor) fieldCache.get(c);
1000:                if (fa == null) {
1001:                    if (target instanceof  Class) {
1002:                        fa = FieldAccessorGenerator.generate(name,
1003:                                (Class) target, codeLoader, true);
1004:                    } else {
1005:                        fa = FieldAccessorGenerator.generate(name, c,
1006:                                codeLoader, false);
1007:                    }
1008:                    fieldCache.put(c, fa);
1009:                }
1010:                return fa.get(target);
1011:            }
1012:
1013:            void _putField(Context context, Class c, String name,
1014:                    Object target, Object value, CodeLoader codeLoader)
1015:                    throws NoSuchFieldException, InstantiationException,
1016:                    IOException, IllegalAccessException {
1017:                FieldAccessor fa = (FieldAccessor) fieldCache.get(c);
1018:                if (fa == null) {
1019:                    if (target instanceof  Class) {
1020:                        fa = FieldAccessorGenerator.generate(name,
1021:                                (Class) target, codeLoader, true);
1022:                    } else {
1023:                        fa = FieldAccessorGenerator.generate(name, c,
1024:                                codeLoader, false);
1025:                    }
1026:                    fieldCache.put(c, fa);
1027:                }
1028:                fa.set(target, value);
1029:            }
1030:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.