Source Code Cross Referenced for JavaProxyClass.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.Array;
030:        import java.lang.reflect.Constructor;
031:        import java.lang.reflect.InvocationTargetException;
032:        import java.lang.reflect.Method;
033:        import java.security.AccessController;
034:        import java.security.PrivilegedActionException;
035:        import java.security.PrivilegedExceptionAction;
036:        import java.util.ArrayList;
037:        import java.util.Arrays;
038:        import java.util.HashMap;
039:        import java.util.HashSet;
040:        import java.util.Iterator;
041:        import java.util.List;
042:        import java.util.Map;
043:        import java.util.Set;
044:
045:        import org.jruby.Ruby;
046:        import org.jruby.RubyArray;
047:        import org.jruby.RubyClass;
048:        import org.jruby.RubyFixnum;
049:        import org.jruby.RubyModule;
050:        import org.jruby.RubyObject;
051:        import org.jruby.RubyNil;
052:        import org.jruby.RubyString;
053:        import org.jruby.exceptions.RaiseException;
054:        import org.jruby.javasupport.JavaClass;
055:        import org.jruby.javasupport.JavaObject;
056:        import org.jruby.javasupport.JavaUtil;
057:        import org.jruby.runtime.CallbackFactory;
058:        import org.jruby.runtime.ObjectAllocator;
059:        import org.jruby.runtime.builtin.IRubyObject;
060:
061:        /**
062:         * Generalized proxy for classes and interfaces.
063:         * 
064:         * API looks a lot like java.lang.reflect.Proxy, except that you can specify a
065:         * super class in addition to a set of interfaces.
066:         * 
067:         * The main implication for users of this class is to handle the case where a
068:         * proxy method overrides an existing method, because in this case the
069:         * invocation handler should "default" to calling the super implementation
070:         * {JavaProxyMethod.invokeSuper}.
071:         * 
072:         * 
073:         * @author krab@trifork.com
074:         * @see java.lang.reflect.Proxy
075:         * 
076:         */
077:        public class JavaProxyClass extends JavaProxyReflectionObject {
078:            static ThreadLocal runtimeTLS = new ThreadLocal();
079:            private final Class proxyClass;
080:            private ArrayList methods = new ArrayList();
081:            private HashMap methodMap = new HashMap();
082:
083:            /* package scope */
084:            JavaProxyClass(Class proxyClass) {
085:                super (getThreadLocalRuntime(),
086:                        (RubyClass) getThreadLocalRuntime().getModule("Java")
087:                                .getClass("JavaProxyClass"));
088:
089:                this .proxyClass = proxyClass;
090:            }
091:
092:            public Object getValue() {
093:                return this ;
094:            }
095:
096:            private static Ruby getThreadLocalRuntime() {
097:                return (Ruby) runtimeTLS.get();
098:            }
099:
100:            public static JavaProxyClass getProxyClass(Ruby runtime,
101:                    Class super Class, Class[] interfaces, Set names)
102:                    throws InvocationTargetException {
103:                Object save = runtimeTLS.get();
104:                runtimeTLS.set(runtime);
105:                try {
106:                    ClassLoader loader = runtime.getJavaSupport()
107:                            .getJavaClassLoader();
108:
109:                    return JavaProxyClassFactory.newProxyClass(loader, null,
110:                            super Class, interfaces, names);
111:                } finally {
112:                    runtimeTLS.set(save);
113:                }
114:            }
115:
116:            public static JavaProxyClass getProxyClass(Ruby runtime,
117:                    Class super Class, Class[] interfaces)
118:                    throws InvocationTargetException {
119:                return getProxyClass(runtime, super Class, interfaces, null);
120:            }
121:
122:            public static Object newProxyInstance(Ruby runtime,
123:                    Class super Class, Class[] interfaces,
124:                    Class[] constructorParameters, Object[] constructorArgs,
125:                    JavaProxyInvocationHandler handler)
126:                    throws IllegalArgumentException, InstantiationException,
127:                    IllegalAccessException, InvocationTargetException,
128:                    SecurityException, NoSuchMethodException {
129:                JavaProxyClass jpc = getProxyClass(runtime, super Class,
130:                        interfaces);
131:                JavaProxyConstructor cons = jpc
132:                        .getConstructor(constructorParameters == null ? new Class[0]
133:                                : constructorParameters);
134:
135:                return cons.newInstance(constructorArgs, handler);
136:
137:            }
138:
139:            public Class getSuperclass() {
140:                return proxyClass.getSuperclass();
141:            }
142:
143:            public Class[] getInterfaces() {
144:                Class[] ifaces = proxyClass.getInterfaces();
145:                Class[] result = new Class[ifaces.length - 1];
146:                int pos = 0;
147:                for (int i = 0; i < ifaces.length; i++) {
148:                    if (ifaces[i] != InternalJavaProxy.class) {
149:                        result[pos++] = ifaces[i];
150:                    }
151:                }
152:                return result;
153:            }
154:
155:            public JavaProxyConstructor[] getConstructors() {
156:                Constructor[] cons = proxyClass.getConstructors();
157:                JavaProxyConstructor[] result = new JavaProxyConstructor[cons.length];
158:                for (int i = 0; i < cons.length; i++) {
159:                    result[i] = new JavaProxyConstructor(getRuntime(), this ,
160:                            cons[i]);
161:                }
162:                return result;
163:            }
164:
165:            public JavaProxyConstructor getConstructor(Class[] args)
166:                    throws SecurityException, NoSuchMethodException {
167:
168:                Class[] realArgs = new Class[args.length + 1];
169:                System.arraycopy(args, 0, realArgs, 0, args.length);
170:                realArgs[args.length] = JavaProxyInvocationHandler.class;
171:
172:                Constructor constructor = proxyClass.getConstructor(realArgs);
173:                return new JavaProxyConstructor(getRuntime(), this , constructor);
174:            }
175:
176:            public JavaProxyMethod[] getMethods() {
177:                return (JavaProxyMethod[]) methods
178:                        .toArray(new JavaProxyMethod[methods.size()]);
179:            }
180:
181:            public JavaProxyMethod getMethod(String name, Class[] parameterTypes) {
182:                List methods = (List) methodMap.get(name);
183:                if (methods != null) {
184:                    for (int i = methods.size(); --i >= 0;) {
185:                        ProxyMethodImpl jpm = (ProxyMethodImpl) methods.get(i);
186:                        if (jpm.matches(name, parameterTypes))
187:                            return jpm;
188:                    }
189:                }
190:                return null;
191:            }
192:
193:            /** return the class of instances of this proxy class */
194:            Class getProxyClass() {
195:                return proxyClass;
196:            }
197:
198:            public static class ProxyMethodImpl extends
199:                    JavaProxyReflectionObject implements  JavaProxyMethod {
200:                private final Method m;
201:
202:                private Object state;
203:
204:                private final Method sm;
205:                private final Class[] parameterTypes;
206:
207:                private final JavaProxyClass clazz;
208:
209:                public ProxyMethodImpl(Ruby runtime, JavaProxyClass clazz,
210:                        Method m, Method sm) {
211:                    super (runtime, runtime.getModule("Java").getClass(
212:                            "JavaProxyMethod"));
213:                    this .m = m;
214:                    this .parameterTypes = m.getParameterTypes();
215:                    this .sm = sm;
216:                    this .clazz = clazz;
217:                }
218:
219:                public Method getMethod() {
220:                    return m;
221:                }
222:
223:                public Method getSuperMethod() {
224:                    return sm;
225:                }
226:
227:                public int getModifiers() {
228:                    return m.getModifiers();
229:                }
230:
231:                public String getName() {
232:                    return m.getName();
233:                }
234:
235:                public Class[] getExceptionTypes() {
236:                    return m.getExceptionTypes();
237:                }
238:
239:                public Class[] getParameterTypes() {
240:                    return parameterTypes;
241:                }
242:
243:                public Object getState() {
244:                    return state;
245:                }
246:
247:                public boolean hasSuperImplementation() {
248:                    return sm != null;
249:                }
250:
251:                public Object invoke(Object proxy, Object[] args)
252:                        throws IllegalArgumentException,
253:                        IllegalAccessException, InvocationTargetException,
254:                        NoSuchMethodException {
255:
256:                    if (!hasSuperImplementation())
257:                        throw new NoSuchMethodException();
258:
259:                    return sm.invoke(proxy, args);
260:                }
261:
262:                public void setState(Object state) {
263:                    this .state = state;
264:                }
265:
266:                public String toString() {
267:                    return m.toString();
268:                }
269:
270:                public Object defaultResult() {
271:                    Class rt = m.getReturnType();
272:
273:                    if (rt == Void.TYPE)
274:                        return null;
275:                    if (rt == Boolean.TYPE)
276:                        return Boolean.FALSE;
277:                    if (rt == Byte.TYPE)
278:                        return new Byte((byte) 0);
279:                    if (rt == Short.TYPE)
280:                        return new Short((short) 0);
281:                    if (rt == Integer.TYPE)
282:                        return new Integer(0);
283:                    if (rt == Long.TYPE)
284:                        return new Long(0L);
285:                    if (rt == Float.TYPE)
286:                        return new Float(0.0f);
287:                    if (rt == Double.TYPE)
288:                        return new Double(0.0);
289:
290:                    return null;
291:                }
292:
293:                public boolean matches(String name, Class[] parameterTypes) {
294:                    return m.getName().equals(name)
295:                            && Arrays.equals(this .parameterTypes,
296:                                    parameterTypes);
297:                }
298:
299:                public Class getReturnType() {
300:                    return m.getReturnType();
301:                }
302:
303:                public static RubyClass createJavaProxyMethodClass(
304:                        Ruby runtime, RubyModule javaProxyModule) {
305:                    RubyClass result = javaProxyModule.defineClassUnder(
306:                            "JavaProxyMethod", runtime.getObject(),
307:                            ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
308:
309:                    CallbackFactory callbackFactory = runtime
310:                            .callbackFactory(JavaProxyClass.ProxyMethodImpl.class);
311:
312:                    JavaProxyReflectionObject.registerRubyMethods(runtime,
313:                            result);
314:
315:                    result.defineFastMethod("argument_types", callbackFactory
316:                            .getFastMethod("argument_types"));
317:                    result.defineFastMethod("declaring_class", callbackFactory
318:                            .getFastMethod("getDeclaringClass"));
319:                    result.defineFastMethod("super?", callbackFactory
320:                            .getFastMethod("super_p"));
321:                    result.defineFastMethod("arity", callbackFactory
322:                            .getFastMethod("arity"));
323:                    result.defineFastMethod("name", callbackFactory
324:                            .getFastMethod("name"));
325:                    result.defineFastMethod("inspect", callbackFactory
326:                            .getFastMethod("inspect"));
327:                    result.defineFastMethod("invoke", callbackFactory
328:                            .getFastOptMethod("do_invoke"));
329:
330:                    return result;
331:                }
332:
333:                public RubyObject name() {
334:                    return getRuntime().newString(getName());
335:                }
336:
337:                public JavaProxyClass getDeclaringClass() {
338:                    return clazz;
339:                }
340:
341:                public RubyArray argument_types() {
342:                    return buildRubyArray(getParameterTypes());
343:                }
344:
345:                public IRubyObject super _p() {
346:                    return hasSuperImplementation() ? getRuntime().getTrue()
347:                            : getRuntime().getFalse();
348:                }
349:
350:                public RubyFixnum arity() {
351:                    return getRuntime().newFixnum(getArity());
352:                }
353:
354:                protected String nameOnInspection() {
355:                    return getDeclaringClass().nameOnInspection() + "/"
356:                            + getName();
357:                }
358:
359:                public IRubyObject inspect() {
360:                    StringBuffer result = new StringBuffer();
361:                    result.append(nameOnInspection());
362:                    result.append("(");
363:                    Class[] parameterTypes = getParameterTypes();
364:                    for (int i = 0; i < parameterTypes.length; i++) {
365:                        result.append(parameterTypes[i].getName());
366:                        if (i < parameterTypes.length - 1) {
367:                            result.append(',');
368:                        }
369:                    }
370:                    result.append(")>");
371:                    return getRuntime().newString(result.toString());
372:                }
373:
374:                public IRubyObject do_invoke(IRubyObject[] nargs) {
375:                    if (nargs.length != 1 + getArity()) {
376:                        throw getRuntime().newArgumentError(nargs.length,
377:                                1 + getArity());
378:                    }
379:
380:                    IRubyObject invokee = nargs[0];
381:                    if (!(invokee instanceof  JavaObject)) {
382:                        throw getRuntime().newTypeError(
383:                                "invokee not a java object");
384:                    }
385:                    Object receiver_value = ((JavaObject) invokee).getValue();
386:                    Object[] arguments = new Object[nargs.length - 1];
387:                    System.arraycopy(nargs, 1, arguments, 0, arguments.length);
388:
389:                    Class[] parameterTypes = getParameterTypes();
390:                    for (int i = 0; i < arguments.length; i++) {
391:                        arguments[i] = JavaUtil.convertRubyToJava(
392:                                (IRubyObject) arguments[i], parameterTypes[i]);
393:                    }
394:
395:                    try {
396:                        Object javaResult = sm
397:                                .invoke(receiver_value, arguments);
398:                        return JavaUtil.convertJavaToRuby(getRuntime(),
399:                                javaResult, getReturnType());
400:                    } catch (IllegalArgumentException e) {
401:                        throw getRuntime().newTypeError(
402:                                "expected " + argument_types().inspect());
403:                    } catch (IllegalAccessException iae) {
404:                        throw getRuntime().newTypeError(
405:                                "illegal access on '" + sm.getName() + "': "
406:                                        + iae.getMessage());
407:                    } catch (InvocationTargetException ite) {
408:                        ite.getTargetException().printStackTrace();
409:                        getRuntime().getJavaSupport().handleNativeException(
410:                                ite.getTargetException());
411:                        // This point is only reached if there was an exception handler
412:                        // installed.
413:                        return getRuntime().getNil();
414:                    }
415:                }
416:
417:                private int getArity() {
418:                    return getParameterTypes().length;
419:                }
420:
421:            }
422:
423:            JavaProxyMethod initMethod(String name, String desc,
424:                    boolean hasSuper) {
425:                Class proxy = proxyClass;
426:                try {
427:                    Class[] parms = parse(proxy.getClassLoader(), desc);
428:                    Method m = proxy.getDeclaredMethod(name, parms);
429:                    Method sm = null;
430:                    if (hasSuper) {
431:                        sm = proxy.getDeclaredMethod("__super$" + name, parms);
432:                    }
433:
434:                    JavaProxyMethod jpm = new ProxyMethodImpl(getRuntime(),
435:                            this , m, sm);
436:                    methods.add(jpm);
437:                    List methodsWithName = (List) methodMap.get(name);
438:                    if (methodsWithName == null) {
439:                        methodsWithName = new ArrayList(2);
440:                        methodMap.put(name, methodsWithName);
441:                    }
442:                    methodsWithName.add(jpm);
443:
444:                    return jpm;
445:                } catch (ClassNotFoundException e) {
446:                    throw new InternalError(e.getMessage());
447:                } catch (SecurityException e) {
448:                    throw new InternalError(e.getMessage());
449:                } catch (NoSuchMethodException e) {
450:                    throw new InternalError(e.getMessage());
451:                }
452:            }
453:
454:            private static Class[] parse(final ClassLoader loader, String desc)
455:                    throws ClassNotFoundException {
456:                List al = new ArrayList();
457:                int idx = 1;
458:                while (desc.charAt(idx) != ')') {
459:
460:                    int arr = 0;
461:                    while (desc.charAt(idx) == '[') {
462:                        idx += 1;
463:                        arr += 1;
464:                    }
465:
466:                    Class type;
467:
468:                    switch (desc.charAt(idx)) {
469:                    case 'L':
470:                        int semi = desc.indexOf(';', idx);
471:                        final String name = desc.substring(idx + 1, semi);
472:                        idx = semi;
473:                        try {
474:                            type = (Class) AccessController
475:                                    .doPrivileged(new PrivilegedExceptionAction() {
476:                                        public Object run()
477:                                                throws ClassNotFoundException {
478:                                            return Class.forName(name.replace(
479:                                                    '/', '.'), false, loader);
480:                                        }
481:                                    });
482:                        } catch (PrivilegedActionException e) {
483:                            throw (ClassNotFoundException) e.getException();
484:                        }
485:                        break;
486:
487:                    case 'B':
488:                        type = Byte.TYPE;
489:                        break;
490:                    case 'C':
491:                        type = Character.TYPE;
492:                        break;
493:                    case 'Z':
494:                        type = Boolean.TYPE;
495:                        break;
496:                    case 'S':
497:                        type = Short.TYPE;
498:                        break;
499:                    case 'I':
500:                        type = Integer.TYPE;
501:                        break;
502:                    case 'J':
503:                        type = Long.TYPE;
504:                        break;
505:                    case 'F':
506:                        type = Float.TYPE;
507:                        break;
508:                    case 'D':
509:                        type = Double.TYPE;
510:                        break;
511:                    default:
512:                        throw new InternalError("cannot parse " + desc + "["
513:                                + idx + "]");
514:                    }
515:
516:                    idx += 1;
517:
518:                    if (arr != 0) {
519:                        type = Array.newInstance(type, new int[arr]).getClass();
520:                    }
521:
522:                    al.add(type);
523:                }
524:
525:                return (Class[]) al.toArray(new Class[al.size()]);
526:            }
527:
528:            //
529:            // Ruby-level methods
530:            //
531:
532:            public static RubyClass createJavaProxyClassClass(Ruby runtime,
533:                    RubyModule javaModule) {
534:                RubyClass result = javaModule.defineClassUnder(
535:                        "JavaProxyClass", runtime.getObject(),
536:                        ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
537:                CallbackFactory callbackFactory = runtime
538:                        .callbackFactory(JavaProxyClass.class);
539:
540:                JavaProxyReflectionObject.registerRubyMethods(runtime, result);
541:
542:                result.defineFastMethod("constructors", callbackFactory
543:                        .getFastMethod("constructors"));
544:                result.defineFastMethod("superclass", callbackFactory
545:                        .getFastMethod("superclass"));
546:                result.defineFastMethod("interfaces", callbackFactory
547:                        .getFastMethod("interfaces"));
548:                result.defineFastMethod("methods", callbackFactory
549:                        .getFastMethod("methods"));
550:
551:                result.getMetaClass().defineFastMethod(
552:                        "get",
553:                        callbackFactory.getFastSingletonMethod("get",
554:                                JavaClass.class));
555:                result.getMetaClass().defineFastMethod(
556:                        "get_with_class",
557:                        callbackFactory.getFastSingletonMethod(
558:                                "get_with_class", RubyClass.class));
559:
560:                return result;
561:            }
562:
563:            public static RubyObject get(IRubyObject recv, JavaClass type) {
564:                try {
565:                    return getProxyClass(recv.getRuntime(), (Class) type
566:                            .getValue(), new Class[0]);
567:                } catch (Error e) {
568:                    RaiseException ex = recv.getRuntime().newArgumentError(
569:                            "unable to create proxy class for "
570:                                    + type.getValue());
571:                    ex.initCause(e);
572:                    throw ex;
573:                } catch (InvocationTargetException e) {
574:                    RaiseException ex = recv.getRuntime().newArgumentError(
575:                            "unable to create proxy class for "
576:                                    + type.getValue());
577:                    ex.initCause(e);
578:                    throw ex;
579:                }
580:            }
581:
582:            private static final HashSet EXCLUDE_MODULES = new HashSet();
583:            static {
584:                EXCLUDE_MODULES.add("Kernel");
585:                EXCLUDE_MODULES.add("Java");
586:                EXCLUDE_MODULES.add("JavaProxyMethods");
587:                EXCLUDE_MODULES.add("Enumerable");
588:            }
589:
590:            private static final HashSet EXCLUDE_METHODS = new HashSet();
591:            static {
592:                EXCLUDE_METHODS.add("class");
593:                EXCLUDE_METHODS.add("finalize");
594:                EXCLUDE_METHODS.add("initialize");
595:                EXCLUDE_METHODS.add("java_class");
596:                EXCLUDE_METHODS.add("java_object");
597:                EXCLUDE_METHODS.add("__jcreate!");
598:                EXCLUDE_METHODS.add("__jsend!");
599:            }
600:
601:            public static RubyObject get_with_class(IRubyObject recv,
602:                    RubyClass clazz) {
603:                Ruby runtime = recv.getRuntime();
604:
605:                // Let's only generate methods for those the user may actually 
606:                // intend to override.  That includes any defined in the current
607:                // class, and any ancestors that are also JavaProxyClasses (but none
608:                // from any other ancestor classes). Methods defined in mixins will
609:                // be considered intentionally overridden, except those from Kernel,
610:                // Java, and JavaProxyMethods, as well as Enumerable. 
611:                // TODO: may want to exclude other common mixins?
612:
613:                JavaClass javaClass = null;
614:                Set names = new HashSet(); // need names ordered for key generation later
615:                List interfaceList = new ArrayList();
616:
617:                List ancestors = clazz.getAncestorList();
618:                boolean skipRemainingClasses = false;
619:                for (Iterator iter = ancestors.iterator(); iter.hasNext();) {
620:                    RubyModule ancestor = (RubyModule) iter.next();
621:                    if (ancestor instanceof  RubyClass) {
622:                        if (skipRemainingClasses)
623:                            continue;
624:                        Map vars = ancestor.getInstanceVariables();
625:                        // we only collect methods and interfaces for 
626:                        // user-defined proxy classes.
627:                        if (!vars.containsKey("@java_proxy_class")) {
628:                            skipRemainingClasses = true;
629:                            continue;
630:                        }
631:
632:                        // get JavaClass if this is the new proxy class; verify it
633:                        // matches if this is a superclass proxy.
634:                        IRubyObject var = (IRubyObject) vars.get("@java_class");
635:                        if (var == null) {
636:                            throw runtime
637:                                    .newTypeError("no java_class defined for proxy (or ancestor): "
638:                                            + ancestor);
639:                        } else if (!(var instanceof  JavaClass)) {
640:                            throw runtime
641:                                    .newTypeError("invalid java_class defined for proxy (or ancestor): "
642:                                            + ancestor + ": " + var);
643:                        }
644:                        if (javaClass == null) {
645:                            javaClass = (JavaClass) var;
646:                        } else if (javaClass != var) {
647:                            throw runtime
648:                                    .newTypeError("java_class defined for "
649:                                            + clazz
650:                                            + " ("
651:                                            + javaClass
652:                                            + ") does not match java_class for ancestor "
653:                                            + ancestor + " (" + var + ")");
654:                        }
655:                        // get any included interfaces
656:                        var = (IRubyObject) vars.get("@java_interfaces");
657:                        if (var != null && !(var instanceof  RubyNil)) {
658:                            if (!(var instanceof  RubyArray)) {
659:                                throw runtime
660:                                        .newTypeError("invalid java_interfaces defined for proxy (or ancestor): "
661:                                                + ancestor + ": " + var);
662:                            }
663:                            RubyArray ifcArray = (RubyArray) var;
664:                            int size = ifcArray.size();
665:                            for (int i = size; --i >= 0;) {
666:                                IRubyObject ifc = ifcArray.eltInternal(i);
667:                                if (!(ifc instanceof  JavaClass)) {
668:                                    throw runtime
669:                                            .newTypeError("invalid java interface defined for proxy (or ancestor): "
670:                                                    + ancestor + ": " + ifc);
671:                                }
672:                                Class interfaceClass = ((JavaClass) ifc)
673:                                        .javaClass();
674:                                if (!interfaceClass.isInterface()) {
675:                                    throw runtime
676:                                            .newTypeError("invalid java interface defined for proxy (or ancestor): "
677:                                                    + ancestor
678:                                                    + ": "
679:                                                    + ifc
680:                                                    + " (not an interface)");
681:                                }
682:                                if (!interfaceList.contains(interfaceClass)) {
683:                                    interfaceList.add(interfaceClass);
684:                                }
685:                            }
686:                        }
687:                        // set this class's method names in var @__java_ovrd_methods if this
688:                        // is the new class; otherwise, get method names from there if this is
689:                        // a proxy superclass.
690:                        var = (IRubyObject) vars.get("@__java_ovrd_methods");
691:                        if (var == null) {
692:                            // lock in the overridden methods for the new class, and any as-yet
693:                            // uninstantiated ancestor class.
694:                            Map methods;
695:                            RubyArray methodNames;
696:                            synchronized (methods = ancestor.getMethods()) {
697:                                methodNames = RubyArray.newArrayLight(runtime,
698:                                        methods.size());
699:                                for (Iterator meths = methods.keySet()
700:                                        .iterator(); meths.hasNext();) {
701:                                    String methodName = (String) meths.next();
702:                                    if (!EXCLUDE_METHODS.contains(methodName)) {
703:                                        names.add(methodName);
704:                                        methodNames.add(runtime
705:                                                .newString(methodName));
706:                                    }
707:                                }
708:                            }
709:                            // TODO: OK to just do a put here?
710:                            ancestor.setInstanceVariable(
711:                                    "@__java_ovrd_methods", methodNames);
712:                        } else {
713:                            if (!(var instanceof  RubyArray)) {
714:                                throw runtime
715:                                        .newTypeError("invalid @__java_ovrd_methods defined for proxy: "
716:                                                + ancestor + ": " + var);
717:                            }
718:                            RubyArray methodNames = (RubyArray) var;
719:                            int size = methodNames.size();
720:                            for (int i = size; --i >= 0;) {
721:                                IRubyObject methodName = methodNames
722:                                        .eltInternal(i);
723:                                if (!(methodName instanceof  RubyString)) {
724:                                    throw runtime
725:                                            .newTypeError("invalid method name defined for proxy (or ancestor): "
726:                                                    + ancestor
727:                                                    + ": "
728:                                                    + methodName);
729:                                }
730:                                names.add(methodName.asSymbol());
731:                            }
732:                        }
733:                    } else if (!EXCLUDE_MODULES.contains(ancestor.getName())) {
734:                        Map methods;
735:                        synchronized (methods = ancestor.getMethods()) {
736:                            for (Iterator meths = methods.keySet().iterator(); meths
737:                                    .hasNext();) {
738:                                String methodName = (String) meths.next();
739:                                if (!EXCLUDE_METHODS.contains(methodName)) {
740:                                    names.add(methodName);
741:                                }
742:                            }
743:                        }
744:                    }
745:                }
746:
747:                if (javaClass == null) {
748:                    throw runtime
749:                            .newArgumentError("unable to create proxy class: no java_class defined for "
750:                                    + clazz);
751:                }
752:
753:                int interfaceCount = interfaceList.size();
754:                Class[] interfaces = new Class[interfaceCount];
755:                for (int i = interfaceCount; --i >= 0;) {
756:                    interfaces[i] = (Class) interfaceList.get(i);
757:                }
758:
759:                try {
760:                    return getProxyClass(recv.getRuntime(), javaClass
761:                            .javaClass(), interfaces, names);
762:                } catch (Error e) {
763:                    RaiseException ex = recv.getRuntime().newArgumentError(
764:                            "unable to create proxy class for "
765:                                    + javaClass.getValue() + " : "
766:                                    + e.getMessage());
767:                    //e.printStackTrace();
768:                    ex.initCause(e);
769:                    throw ex;
770:                } catch (InvocationTargetException e) {
771:                    RaiseException ex = recv.getRuntime().newArgumentError(
772:                            "unable to create proxy class for "
773:                                    + javaClass.getValue() + " : "
774:                                    + e.getMessage());
775:                    //e.printStackTrace();
776:                    ex.initCause(e);
777:                    throw ex;
778:                }
779:            }
780:
781:            public RubyObject super class() {
782:                return JavaClass.get(getRuntime(), getSuperclass());
783:            }
784:
785:            public RubyArray methods() {
786:                return buildRubyArray(getMethods());
787:            }
788:
789:            public RubyArray interfaces() {
790:                return buildRubyArray(getInterfaces());
791:            }
792:
793:            public RubyArray constructors() {
794:                return buildRubyArray(getConstructors());
795:            }
796:
797:            public static void createJavaProxyModule(Ruby runtime) {
798:                // TODO Auto-generated method stub
799:
800:                RubyModule javaProxyModule = runtime.getModule("Java");
801:                JavaProxyClass.createJavaProxyClassClass(runtime,
802:                        javaProxyModule);
803:                ProxyMethodImpl.createJavaProxyMethodClass(runtime,
804:                        javaProxyModule);
805:                JavaProxyConstructor.createJavaProxyConstructorClass(runtime,
806:                        javaProxyModule);
807:            }
808:
809:            public String nameOnInspection() {
810:                return "[Proxy:" + getSuperclass().getName() + "]";
811:            }
812:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.