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


0001:        /***** BEGIN LICENSE BLOCK *****
0002:         * Version: CPL 1.0/GPL 2.0/LGPL 2.1
0003:         *
0004:         * The contents of this file are subject to the Common Public
0005:         * License Version 1.0 (the "License"); you may not use this file
0006:         * except in compliance with the License. You may obtain a copy of
0007:         * the License at http://www.eclipse.org/legal/cpl-v10.html
0008:         *
0009:         * Software distributed under the License is distributed on an "AS
0010:         * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
0011:         * implied. See the License for the specific language governing
0012:         * rights and limitations under the License.
0013:         *
0014:         * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
0015:         * Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
0016:         * Copyright (C) 2004-2005 Thomas E Enebo <enebo@acm.org>
0017:         * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
0018:         * Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net>
0019:         * Copyright (C) 2005 Charles O Nutter <headius@headius.com>
0020:         * Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org>
0021:         * Copyright (C) 2007 Miguel Covarrubias <mlcovarrubias@gmail.com>
0022:         * Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
0023:         * 
0024:         * Alternatively, the contents of this file may be used under the terms of
0025:         * either of the GNU General Public License Version 2 or later (the "GPL"),
0026:         * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
0027:         * in which case the provisions of the GPL or the LGPL are applicable instead
0028:         * of those above. If you wish to allow use of your version of this file only
0029:         * under the terms of either the GPL or the LGPL, and not to allow others to
0030:         * use your version of this file under the terms of the CPL, indicate your
0031:         * decision by deleting the provisions above and replace them with the notice
0032:         * and other provisions required by the GPL or the LGPL. If you do not delete
0033:         * the provisions above, a recipient may use your version of this file under
0034:         * the terms of any one of the CPL, the GPL or the LGPL.
0035:         ***** END LICENSE BLOCK *****/package org.jruby.javasupport;
0036:
0037:        import java.beans.BeanInfo;
0038:        import java.beans.IntrospectionException;
0039:        import java.beans.Introspector;
0040:        import java.beans.PropertyDescriptor;
0041:        import java.lang.reflect.Array;
0042:        import java.lang.reflect.Constructor;
0043:        import java.lang.reflect.Field;
0044:        import java.lang.reflect.Method;
0045:        import java.lang.reflect.Modifier;
0046:        import java.util.ArrayList;
0047:        import java.util.HashMap;
0048:        import java.util.HashSet;
0049:        import java.util.Iterator;
0050:        import java.util.List;
0051:        import java.util.Map;
0052:        import java.util.Set;
0053:        import java.util.regex.Matcher;
0054:        import java.util.regex.Pattern;
0055:
0056:        import org.jruby.Ruby;
0057:        import org.jruby.RubyArray;
0058:        import org.jruby.RubyBoolean;
0059:        import org.jruby.RubyClass;
0060:        import org.jruby.RubyFixnum;
0061:        import org.jruby.RubyInteger;
0062:        import org.jruby.RubyMethod;
0063:        import org.jruby.RubyModule;
0064:        import org.jruby.RubyNumeric;
0065:        import org.jruby.RubyString;
0066:        import org.jruby.exceptions.RaiseException;
0067:        import org.jruby.runtime.Arity;
0068:        import org.jruby.runtime.Block;
0069:        import org.jruby.runtime.CallType;
0070:        import org.jruby.runtime.CallbackFactory;
0071:        import org.jruby.runtime.ObjectAllocator;
0072:        import org.jruby.runtime.Visibility;
0073:        import org.jruby.runtime.builtin.IRubyObject;
0074:        import org.jruby.runtime.callback.Callback;
0075:        import org.jruby.util.IdUtil;
0076:        import org.jruby.util.collections.IntHashMap;
0077:
0078:        public class JavaClass extends JavaObject {
0079:
0080:            private static boolean DEBUG = false;
0081:
0082:            private static class AssignedName {
0083:                // to override an assigned name, the type must be less than
0084:                // or equal to the assigned type. so a field name in a subclass
0085:                // will override an alias in a superclass, but not a method.
0086:                static final int RESERVED = 0;
0087:                static final int METHOD = 1;
0088:                static final int FIELD = 2;
0089:                static final int PROTECTED_METHOD = 3;
0090:                static final int WEAKLY_RESERVED = 4; // we'll be peeved, but not devastated, if you override
0091:                static final int ALIAS = 5;
0092:                // yes, protected fields are weaker than aliases. many conflicts
0093:                // in the old AWT code, for example, where you really want 'size'
0094:                // to mean the public method getSize, not the protected field 'size'.
0095:                static final int PROTECTED_FIELD = 6;
0096:                String name;
0097:                int type;
0098:
0099:                AssignedName() {
0100:                }
0101:
0102:                AssignedName(String name, int type) {
0103:                    this .name = name;
0104:                    this .type = type;
0105:                }
0106:            }
0107:
0108:            // TODO: other reserved names?
0109:            private static final Map RESERVED_NAMES = new HashMap();
0110:            static {
0111:                RESERVED_NAMES.put("__id__", new AssignedName("__id__",
0112:                        AssignedName.RESERVED));
0113:                RESERVED_NAMES.put("__send__", new AssignedName("__send__",
0114:                        AssignedName.RESERVED));
0115:                RESERVED_NAMES.put("class", new AssignedName("class",
0116:                        AssignedName.RESERVED));
0117:                RESERVED_NAMES.put("initialize", new AssignedName("initialize",
0118:                        AssignedName.RESERVED));
0119:                RESERVED_NAMES.put("object_id", new AssignedName("object_id",
0120:                        AssignedName.RESERVED));
0121:                RESERVED_NAMES.put("private", new AssignedName("private",
0122:                        AssignedName.RESERVED));
0123:                RESERVED_NAMES.put("protected", new AssignedName("protected",
0124:                        AssignedName.RESERVED));
0125:                RESERVED_NAMES.put("public", new AssignedName("public",
0126:                        AssignedName.RESERVED));
0127:
0128:                // weakly reserved names
0129:                RESERVED_NAMES.put("id", new AssignedName("id",
0130:                        AssignedName.WEAKLY_RESERVED));
0131:            }
0132:            private static final Map STATIC_RESERVED_NAMES = new HashMap(
0133:                    RESERVED_NAMES);
0134:            static {
0135:                STATIC_RESERVED_NAMES.put("new", new AssignedName("new",
0136:                        AssignedName.RESERVED));
0137:            }
0138:            private static final Map INSTANCE_RESERVED_NAMES = new HashMap(
0139:                    RESERVED_NAMES);
0140:
0141:            private static abstract class NamedCallback implements  Callback {
0142:                static final int STATIC_FIELD = 1;
0143:                static final int STATIC_METHOD = 2;
0144:                static final int INSTANCE_FIELD = 3;
0145:                static final int INSTANCE_METHOD = 4;
0146:                String name;
0147:                int type;
0148:                Visibility visibility = Visibility.PUBLIC;
0149:                boolean isProtected;
0150:
0151:                NamedCallback() {
0152:                }
0153:
0154:                NamedCallback(String name, int type) {
0155:                    this .name = name;
0156:                    this .type = type;
0157:                }
0158:
0159:                abstract void install(RubyClass proxy);
0160:
0161:                // small hack to save a cast later on
0162:                boolean hasLocalMethod() {
0163:                    return true;
0164:                }
0165:
0166:                boolean isPublic() {
0167:                    return visibility == Visibility.PUBLIC;
0168:                }
0169:
0170:                boolean isProtected() {
0171:                    return visibility == Visibility.PROTECTED;
0172:                }
0173:
0174:                void logMessage(IRubyObject self, IRubyObject[] args) {
0175:                    if (!DEBUG) {
0176:                        return;
0177:                    }
0178:                    String type;
0179:                    switch (this .type) {
0180:                    case STATIC_FIELD:
0181:                        type = "static field";
0182:                        break;
0183:                    case STATIC_METHOD:
0184:                        type = "static method";
0185:                        break;
0186:                    case INSTANCE_FIELD:
0187:                        type = "instance field";
0188:                        break;
0189:                    case INSTANCE_METHOD:
0190:                        type = "instance method";
0191:                        break;
0192:                    default:
0193:                        type = "?";
0194:                        break;
0195:                    }
0196:                    StringBuffer b = new StringBuffer(type).append(" => '")
0197:                            .append(name).append("'; args.length = ").append(
0198:                                    args.length);
0199:                    for (int i = 0; i < args.length; i++) {
0200:                        b.append("\n   arg[").append(i).append("] = ").append(
0201:                                args[i]);
0202:                    }
0203:                    System.out.println(b);
0204:                }
0205:            }
0206:
0207:            private static abstract class FieldCallback extends NamedCallback {
0208:                Field field;
0209:                JavaField javaField;
0210:
0211:                FieldCallback() {
0212:                }
0213:
0214:                FieldCallback(String name, int type, Field field) {
0215:                    super (name, type);
0216:                    this .field = field;
0217:                    //            if (Modifier.isProtected(field.getModifiers())) {
0218:                    //                field.setAccessible(true);
0219:                    //                this.visibility = Visibility.PROTECTED;
0220:                    //            }
0221:                }
0222:            }
0223:
0224:            private class StaticFieldGetter extends FieldCallback {
0225:                StaticFieldGetter() {
0226:                }
0227:
0228:                StaticFieldGetter(String name, Field field) {
0229:                    super (name, STATIC_FIELD, field);
0230:                }
0231:
0232:                void install(RubyClass proxy) {
0233:                    proxy.getSingletonClass().defineFastMethod(this .name, this ,
0234:                            this .visibility);
0235:                }
0236:
0237:                public IRubyObject execute(IRubyObject self,
0238:                        IRubyObject[] args, Block block) {
0239:                    logMessage(self, args);
0240:                    if (javaField == null) {
0241:                        javaField = new JavaField(getRuntime(), field);
0242:                    }
0243:                    return Java.java_to_ruby(self, javaField.static_value(),
0244:                            Block.NULL_BLOCK);
0245:                }
0246:
0247:                public Arity getArity() {
0248:                    return Arity.NO_ARGUMENTS;
0249:                }
0250:            }
0251:
0252:            private class StaticFieldSetter extends FieldCallback {
0253:                StaticFieldSetter() {
0254:                }
0255:
0256:                StaticFieldSetter(String name, Field field) {
0257:                    super (name, STATIC_FIELD, field);
0258:                }
0259:
0260:                void install(RubyClass proxy) {
0261:                    proxy.getSingletonClass().defineFastMethod(this .name, this ,
0262:                            this .visibility);
0263:                }
0264:
0265:                public IRubyObject execute(IRubyObject self,
0266:                        IRubyObject[] args, Block block) {
0267:                    logMessage(self, args);
0268:                    if (javaField == null) {
0269:                        javaField = new JavaField(getRuntime(), field);
0270:                    }
0271:                    return Java.java_to_ruby(self, javaField
0272:                            .set_static_value(Java.ruby_to_java(self, args[0],
0273:                                    Block.NULL_BLOCK)), Block.NULL_BLOCK);
0274:                }
0275:
0276:                public Arity getArity() {
0277:                    return Arity.ONE_ARGUMENT;
0278:                }
0279:            }
0280:
0281:            private class InstanceFieldGetter extends FieldCallback {
0282:                InstanceFieldGetter() {
0283:                }
0284:
0285:                InstanceFieldGetter(String name, Field field) {
0286:                    super (name, INSTANCE_FIELD, field);
0287:                }
0288:
0289:                void install(RubyClass proxy) {
0290:                    proxy.defineFastMethod(this .name, this , this .visibility);
0291:                }
0292:
0293:                public IRubyObject execute(IRubyObject self,
0294:                        IRubyObject[] args, Block block) {
0295:                    logMessage(self, args);
0296:                    if (javaField == null) {
0297:                        javaField = new JavaField(getRuntime(), field);
0298:                    }
0299:                    return Java.java_to_ruby(self, javaField.value(self
0300:                            .getInstanceVariable("@java_object")),
0301:                            Block.NULL_BLOCK);
0302:                }
0303:
0304:                public Arity getArity() {
0305:                    return Arity.NO_ARGUMENTS;
0306:                }
0307:            }
0308:
0309:            private class InstanceFieldSetter extends FieldCallback {
0310:                InstanceFieldSetter() {
0311:                }
0312:
0313:                InstanceFieldSetter(String name, Field field) {
0314:                    super (name, INSTANCE_FIELD, field);
0315:                }
0316:
0317:                void install(RubyClass proxy) {
0318:                    proxy.defineFastMethod(this .name, this , this .visibility);
0319:                }
0320:
0321:                public IRubyObject execute(IRubyObject self,
0322:                        IRubyObject[] args, Block block) {
0323:                    logMessage(self, args);
0324:                    if (javaField == null) {
0325:                        javaField = new JavaField(getRuntime(), field);
0326:                    }
0327:                    return Java.java_to_ruby(self, javaField.set_value(self
0328:                            .getInstanceVariable("@java_object"), Java
0329:                            .ruby_to_java(self, args[0], Block.NULL_BLOCK)),
0330:                            Block.NULL_BLOCK);
0331:                }
0332:
0333:                public Arity getArity() {
0334:                    return Arity.ONE_ARGUMENT;
0335:                }
0336:            }
0337:
0338:            private static abstract class MethodCallback extends NamedCallback {
0339:                boolean haveLocalMethod;
0340:                List methods;
0341:                List aliases;
0342:                IntHashMap javaMethods;
0343:                IntHashMap matchingMethods;
0344:                JavaMethod javaMethod;
0345:
0346:                MethodCallback() {
0347:                }
0348:
0349:                MethodCallback(String name, int type) {
0350:                    super (name, type);
0351:                }
0352:
0353:                void addMethod(Method method, Class javaClass) {
0354:                    if (methods == null) {
0355:                        methods = new ArrayList();
0356:                    }
0357:                    methods.add(method);
0358:                    //            if (Modifier.isProtected(method.getModifiers())) {
0359:                    //                visibility = Visibility.PROTECTED;
0360:                    //            }
0361:                    haveLocalMethod |= javaClass == method.getDeclaringClass();
0362:                }
0363:
0364:                void addAlias(String alias) {
0365:                    if (aliases == null) {
0366:                        aliases = new ArrayList();
0367:                    }
0368:                    if (!aliases.contains(alias))
0369:                        aliases.add(alias);
0370:                }
0371:
0372:                boolean hasLocalMethod() {
0373:                    return haveLocalMethod;
0374:                }
0375:
0376:                // TODO: varargs?
0377:                // TODO: rework Java.matching_methods_internal and
0378:                // ProxyData.method_cache, since we really don't need to be passing
0379:                // around RubyArray objects anymore.
0380:                void createJavaMethods(Ruby runtime) {
0381:                    if (methods != null) {
0382:                        if (methods.size() == 1) {
0383:                            javaMethod = JavaMethod.create(runtime,
0384:                                    (Method) methods.get(0));
0385:                        } else {
0386:                            javaMethods = new IntHashMap();
0387:                            matchingMethods = new IntHashMap();
0388:                            for (Iterator iter = methods.iterator(); iter
0389:                                    .hasNext();) {
0390:                                Method method = (Method) iter.next();
0391:                                // TODO: deal with varargs
0392:                                //int arity = method.isVarArgs() ? -1 : method.getParameterTypes().length;
0393:                                int arity = method.getParameterTypes().length;
0394:                                RubyArray methodsForArity = (RubyArray) javaMethods
0395:                                        .get(arity);
0396:                                if (methodsForArity == null) {
0397:                                    methodsForArity = RubyArray
0398:                                            .newArrayLight(runtime);
0399:                                    javaMethods.put(arity, methodsForArity);
0400:                                }
0401:                                methodsForArity.append(JavaMethod.create(
0402:                                        runtime, method));
0403:                            }
0404:                        }
0405:                        methods = null;
0406:                    }
0407:                }
0408:
0409:                void raiseNoMatchingMethodError(IRubyObject proxy,
0410:                        IRubyObject[] args, int start) {
0411:                    int len = args.length;
0412:                    List argTypes = new ArrayList(len - start);
0413:                    for (int i = start; i < len; i++) {
0414:                        argTypes.add(((JavaClass) ((JavaObject) args[i])
0415:                                .java_class()).getValue());
0416:                    }
0417:                    throw proxy.getRuntime().newNameError(
0418:                            "no "
0419:                                    + this .name
0420:                                    + " with arguments matching "
0421:                                    + argTypes
0422:                                    + " on object "
0423:                                    + proxy.callMethod(proxy.getRuntime()
0424:                                            .getCurrentContext(), "inspect"),
0425:                            null);
0426:                }
0427:            }
0428:
0429:            private class StaticMethodInvoker extends MethodCallback {
0430:                StaticMethodInvoker() {
0431:                }
0432:
0433:                StaticMethodInvoker(String name) {
0434:                    super (name, STATIC_METHOD);
0435:                }
0436:
0437:                void install(RubyClass proxy) {
0438:                    if (haveLocalMethod) {
0439:                        RubyClass singleton = proxy.getSingletonClass();
0440:                        singleton.defineFastMethod(this .name, this ,
0441:                                this .visibility);
0442:                        if (aliases != null && isPublic()) {
0443:                            for (Iterator iter = aliases.iterator(); iter
0444:                                    .hasNext();) {
0445:                                singleton.defineAlias((String) iter.next(),
0446:                                        this .name);
0447:                            }
0448:                            aliases = null;
0449:                        }
0450:                    }
0451:                }
0452:
0453:                public IRubyObject execute(IRubyObject self,
0454:                        IRubyObject[] args, Block block) {
0455:                    logMessage(self, args);
0456:                    if (javaMethod == null && javaMethods == null) {
0457:                        createJavaMethods(self.getRuntime());
0458:                    }
0459:                    // TODO: ok to convert args in place, rather than new array?
0460:                    int len = args.length;
0461:                    IRubyObject[] convertedArgs = new IRubyObject[len];
0462:                    for (int i = len; --i >= 0;) {
0463:                        convertedArgs[i] = Java.ruby_to_java(self, args[i],
0464:                                Block.NULL_BLOCK);
0465:                    }
0466:                    if (javaMethods == null) {
0467:                        return Java
0468:                                .java_to_ruby(self, javaMethod
0469:                                        .invoke_static(convertedArgs),
0470:                                        Block.NULL_BLOCK);
0471:                    } else {
0472:                        int argsTypeHash = 0;
0473:                        for (int i = len; --i >= 0;) {
0474:                            argsTypeHash += 3 * args[i].getMetaClass().id;
0475:                        }
0476:                        IRubyObject match = (IRubyObject) matchingMethods
0477:                                .get(argsTypeHash);
0478:                        if (match == null) {
0479:                            // TODO: varargs?
0480:                            RubyArray methods = (RubyArray) javaMethods
0481:                                    .get(len);
0482:                            if (methods == null) {
0483:                                raiseNoMatchingMethodError(self, convertedArgs,
0484:                                        0);
0485:                            }
0486:                            match = Java.matching_method_internal(
0487:                                    JAVA_UTILITIES, methods, convertedArgs, 0,
0488:                                    len);
0489:                        }
0490:                        return Java
0491:                                .java_to_ruby(self, ((JavaMethod) match)
0492:                                        .invoke_static(convertedArgs),
0493:                                        Block.NULL_BLOCK);
0494:                    }
0495:                }
0496:
0497:                public Arity getArity() {
0498:                    return Arity.OPTIONAL;
0499:                }
0500:            }
0501:
0502:            private class InstanceMethodInvoker extends MethodCallback {
0503:                InstanceMethodInvoker() {
0504:                }
0505:
0506:                InstanceMethodInvoker(String name) {
0507:                    super (name, INSTANCE_METHOD);
0508:                }
0509:
0510:                void install(RubyClass proxy) {
0511:                    if (haveLocalMethod) {
0512:                        proxy
0513:                                .defineFastMethod(this .name, this ,
0514:                                        this .visibility);
0515:                        if (aliases != null && isPublic()) {
0516:                            for (Iterator iter = aliases.iterator(); iter
0517:                                    .hasNext();) {
0518:                                proxy.defineAlias((String) iter.next(),
0519:                                        this .name);
0520:                            }
0521:                            aliases = null;
0522:                        }
0523:                    }
0524:                }
0525:
0526:                public IRubyObject execute(IRubyObject self,
0527:                        IRubyObject[] args, Block block) {
0528:                    logMessage(self, args);
0529:                    if (javaMethod == null && javaMethods == null) {
0530:                        createJavaMethods(self.getRuntime());
0531:                    }
0532:                    // TODO: ok to convert args in place, rather than new array?
0533:                    int len = args.length;
0534:                    IRubyObject[] convertedArgs = new IRubyObject[len + 1];
0535:                    convertedArgs[0] = self.getInstanceVariable("@java_object");
0536:                    for (int i = len; --i >= 0;) {
0537:                        convertedArgs[i + 1] = Java.ruby_to_java(self, args[i],
0538:                                Block.NULL_BLOCK);
0539:                    }
0540:                    if (javaMethods == null) {
0541:                        return Java.java_to_ruby(self, javaMethod
0542:                                .invoke(convertedArgs), Block.NULL_BLOCK);
0543:                    } else {
0544:                        int argsTypeHash = 0;
0545:                        for (int i = len; --i >= 0;) {
0546:                            argsTypeHash += 3 * args[i].getMetaClass().id;
0547:                        }
0548:                        IRubyObject match = (IRubyObject) matchingMethods
0549:                                .get(argsTypeHash);
0550:                        if (match == null) {
0551:                            // TODO: varargs?
0552:                            RubyArray methods = (RubyArray) javaMethods
0553:                                    .get(len);
0554:                            if (methods == null) {
0555:                                raiseNoMatchingMethodError(self, convertedArgs,
0556:                                        1);
0557:                            }
0558:                            match = Java.matching_method_internal(
0559:                                    JAVA_UTILITIES, methods, convertedArgs, 1,
0560:                                    len);
0561:                            matchingMethods.put(argsTypeHash, match);
0562:                        }
0563:                        return Java.java_to_ruby(self, ((JavaMethod) match)
0564:                                .invoke(convertedArgs), Block.NULL_BLOCK);
0565:                    }
0566:                }
0567:
0568:                public Arity getArity() {
0569:                    return Arity.OPTIONAL;
0570:                }
0571:            }
0572:
0573:            private static class ConstantField {
0574:                static final int CONSTANT = Modifier.FINAL | Modifier.PUBLIC
0575:                        | Modifier.STATIC;
0576:                Field field;
0577:
0578:                ConstantField(Field field) {
0579:                    this .field = field;
0580:                }
0581:
0582:                void install(RubyModule proxy) {
0583:                    if (proxy.getConstantAt(field.getName()) == null) {
0584:                        JavaField javaField = new JavaField(proxy.getRuntime(),
0585:                                field);
0586:                        RubyString name = javaField.name();
0587:                        proxy.const_set(name, Java.java_to_ruby(proxy,
0588:                                javaField.static_value(), Block.NULL_BLOCK));
0589:                    }
0590:                }
0591:
0592:                static boolean isConstant(Field field) {
0593:                    return (field.getModifiers() & CONSTANT) == CONSTANT
0594:                            && Character.isUpperCase(field.getName().charAt(0));
0595:                }
0596:            }
0597:
0598:            private final RubyModule JAVA_UTILITIES = getRuntime()
0599:                    .getJavaSupport().getJavaUtilitiesModule();
0600:
0601:            private Map staticAssignedNames;
0602:            private Map instanceAssignedNames;
0603:            private Map staticCallbacks;
0604:            private Map instanceCallbacks;
0605:            private List constantFields;
0606:            // caching constructors, as they're accessed for each new instance
0607:            private RubyArray constructors;
0608:
0609:            protected Map getStaticAssignedNames() {
0610:                return staticAssignedNames;
0611:            }
0612:
0613:            protected Map getInstanceAssignedNames() {
0614:                return instanceAssignedNames;
0615:            }
0616:
0617:            private JavaClass(Ruby runtime, Class javaClass) {
0618:                super (runtime, (RubyClass) runtime.getJavaSupport()
0619:                        .getJavaClassClass(), javaClass);
0620:                if (javaClass.isInterface()) {
0621:                    initializeInterface(javaClass);
0622:                } else if (!(javaClass.isArray() || javaClass.isPrimitive())) {
0623:                    // TODO: public only?
0624:                    initializeClass(javaClass);
0625:                }
0626:            }
0627:
0628:            private void initializeInterface(Class javaClass) {
0629:                Map staticNames = new HashMap(STATIC_RESERVED_NAMES);
0630:                List constantFields = new ArrayList();
0631:                Field[] fields;
0632:                try {
0633:                    fields = javaClass.getDeclaredFields();
0634:                } catch (SecurityException e) {
0635:                    fields = javaClass.getFields();
0636:                }
0637:                for (int i = fields.length; --i >= 0;) {
0638:                    Field field = fields[i];
0639:                    if (javaClass != field.getDeclaringClass())
0640:                        continue;
0641:                    if (ConstantField.isConstant(field)) {
0642:                        constantFields.add(new ConstantField(field));
0643:                    }
0644:                }
0645:                this .staticAssignedNames = staticNames;
0646:                this .constantFields = constantFields;
0647:            }
0648:
0649:            private void initializeClass(Class javaClass) {
0650:                Class super class = javaClass.getSuperclass();
0651:                Map staticNames;
0652:                Map instanceNames;
0653:                if (super class == null) {
0654:                    staticNames = new HashMap();
0655:                    instanceNames = new HashMap();
0656:                } else {
0657:                    JavaClass super JavaClass = get(getRuntime(), super class);
0658:                    staticNames = new HashMap(super JavaClass
0659:                            .getStaticAssignedNames());
0660:                    instanceNames = new HashMap(super JavaClass
0661:                            .getInstanceAssignedNames());
0662:                }
0663:                staticNames.putAll(STATIC_RESERVED_NAMES);
0664:                instanceNames.putAll(INSTANCE_RESERVED_NAMES);
0665:                Map staticCallbacks = new HashMap();
0666:                Map instanceCallbacks = new HashMap();
0667:                List constantFields = new ArrayList();
0668:                Field[] fields = javaClass.getFields();
0669:                for (int i = fields.length; --i >= 0;) {
0670:                    Field field = fields[i];
0671:                    if (javaClass != field.getDeclaringClass())
0672:                        continue;
0673:
0674:                    if (ConstantField.isConstant(field)) {
0675:                        constantFields.add(new ConstantField(field));
0676:                        continue;
0677:                    }
0678:                    String name = field.getName();
0679:                    int modifiers = field.getModifiers();
0680:                    if (Modifier.isStatic(modifiers)) {
0681:                        AssignedName assignedName = (AssignedName) staticNames
0682:                                .get(name);
0683:                        if (assignedName != null
0684:                                && assignedName.type < AssignedName.FIELD)
0685:                            continue;
0686:                        staticNames.put(name, new AssignedName(name,
0687:                                AssignedName.FIELD));
0688:                        staticCallbacks.put(name, new StaticFieldGetter(name,
0689:                                field));
0690:                        if (!Modifier.isFinal(modifiers)) {
0691:                            String setName = name + '=';
0692:                            staticCallbacks.put(setName, new StaticFieldSetter(
0693:                                    setName, field));
0694:                        }
0695:                    } else {
0696:                        AssignedName assignedName = (AssignedName) instanceNames
0697:                                .get(name);
0698:                        if (assignedName != null
0699:                                && assignedName.type < AssignedName.FIELD)
0700:                            continue;
0701:                        instanceNames.put(name, new AssignedName(name,
0702:                                AssignedName.FIELD));
0703:                        instanceCallbacks.put(name, new InstanceFieldGetter(
0704:                                name, field));
0705:                        if (!Modifier.isFinal(modifiers)) {
0706:                            String setName = name + '=';
0707:                            instanceCallbacks.put(setName,
0708:                                    new InstanceFieldSetter(setName, field));
0709:                        }
0710:                    }
0711:                }
0712:                // TODO: protected methods.  this is going to require a rework 
0713:                // of some of the mechanism.  
0714:                Method[] methods = javaClass.getMethods();
0715:                for (int i = methods.length; --i >= 0;) {
0716:                    // we need to collect all methods, though we'll only
0717:                    // install the ones that are named in this class
0718:                    Method method = methods[i];
0719:                    String name = method.getName();
0720:                    if (Modifier.isStatic(method.getModifiers())) {
0721:                        AssignedName assignedName = (AssignedName) staticNames
0722:                                .get(name);
0723:                        if (assignedName == null) {
0724:                            staticNames.put(name, new AssignedName(name,
0725:                                    AssignedName.METHOD));
0726:                        } else {
0727:                            if (assignedName.type < AssignedName.METHOD)
0728:                                continue;
0729:                            if (assignedName.type != AssignedName.METHOD) {
0730:                                staticCallbacks.remove(name);
0731:                                staticCallbacks.remove(name + '=');
0732:                                staticNames.put(name, new AssignedName(name,
0733:                                        AssignedName.METHOD));
0734:                            }
0735:                        }
0736:                        StaticMethodInvoker invoker = (StaticMethodInvoker) staticCallbacks
0737:                                .get(name);
0738:                        if (invoker == null) {
0739:                            invoker = new StaticMethodInvoker(name);
0740:                            staticCallbacks.put(name, invoker);
0741:                        }
0742:                        invoker.addMethod(method, javaClass);
0743:                    } else {
0744:                        AssignedName assignedName = (AssignedName) instanceNames
0745:                                .get(name);
0746:                        if (assignedName == null) {
0747:                            instanceNames.put(name, new AssignedName(name,
0748:                                    AssignedName.METHOD));
0749:                        } else {
0750:                            if (assignedName.type < AssignedName.METHOD)
0751:                                continue;
0752:                            if (assignedName.type != AssignedName.METHOD) {
0753:                                instanceCallbacks.remove(name);
0754:                                instanceCallbacks.remove(name + '=');
0755:                                instanceNames.put(name, new AssignedName(name,
0756:                                        AssignedName.METHOD));
0757:                            }
0758:                        }
0759:                        InstanceMethodInvoker invoker = (InstanceMethodInvoker) instanceCallbacks
0760:                                .get(name);
0761:                        if (invoker == null) {
0762:                            invoker = new InstanceMethodInvoker(name);
0763:                            instanceCallbacks.put(name, invoker);
0764:                        }
0765:                        invoker.addMethod(method, javaClass);
0766:                    }
0767:                }
0768:                this .staticAssignedNames = staticNames;
0769:                this .instanceAssignedNames = instanceNames;
0770:                this .staticCallbacks = staticCallbacks;
0771:                this .instanceCallbacks = instanceCallbacks;
0772:                this .constantFields = constantFields;
0773:            }
0774:
0775:            public void setupProxy(RubyClass proxy) {
0776:                proxy.defineFastMethod("__jsend!", __jsend_method);
0777:                Class javaClass = javaClass();
0778:                if (javaClass.isInterface()) {
0779:                    setupInterfaceProxy(proxy);
0780:                    return;
0781:                } else if (javaClass.isArray() || javaClass.isPrimitive()) {
0782:                    return;
0783:                }
0784:                for (Iterator iter = constantFields.iterator(); iter.hasNext();) {
0785:                    ((ConstantField) iter.next()).install(proxy);
0786:                }
0787:                for (Iterator iter = staticCallbacks.values().iterator(); iter
0788:                        .hasNext();) {
0789:                    NamedCallback callback = (NamedCallback) iter.next();
0790:                    if (callback.type == NamedCallback.STATIC_METHOD
0791:                            && callback.hasLocalMethod()) {
0792:                        assignAliases((MethodCallback) callback,
0793:                                staticAssignedNames);
0794:                    }
0795:                    callback.install(proxy);
0796:                }
0797:                for (Iterator iter = instanceCallbacks.values().iterator(); iter
0798:                        .hasNext();) {
0799:                    NamedCallback callback = (NamedCallback) iter.next();
0800:                    if (callback.type == NamedCallback.INSTANCE_METHOD
0801:                            && callback.hasLocalMethod()) {
0802:                        assignAliases((MethodCallback) callback,
0803:                                instanceAssignedNames);
0804:                    }
0805:                    callback.install(proxy);
0806:                }
0807:                // setup constants for public inner classes
0808:                Class[] classes = javaClass.getClasses();
0809:                for (int i = classes.length; --i >= 0;) {
0810:                    if (javaClass == classes[i].getDeclaringClass()) {
0811:                        Class clazz = classes[i];
0812:                        String simpleName = getSimpleName(clazz);
0813:
0814:                        if (simpleName.length() == 0)
0815:                            continue;
0816:
0817:                        // Ignore bad constant named inner classes pending JRUBY-697
0818:                        if (IdUtil.isConstant(simpleName)
0819:                                && proxy.getConstantAt(simpleName) == null) {
0820:                            proxy.const_set(getRuntime().newString(simpleName),
0821:                                    Java.get_proxy_class(JAVA_UTILITIES, get(
0822:                                            getRuntime(), clazz)));
0823:                        }
0824:                    }
0825:                }
0826:                // TODO: we can probably release our references to the constantFields
0827:                // array and static/instance callback hashes at this point. I don't see
0828:                // a case where the proxy would be GC'd and we'd have to reinitialize.
0829:                // I suppose we could keep a reference to the proxy just to be sure...
0830:            }
0831:
0832:            private static void assignAliases(MethodCallback callback,
0833:                    Map assignedNames) {
0834:                String name = callback.name;
0835:                addUnassignedAlias(getRubyCasedName(name), assignedNames,
0836:                        callback);
0837:                // logic adapted from java.beans.Introspector
0838:                if (!(name.length() > 3 || name.startsWith("is")))
0839:                    return;
0840:
0841:                String javaPropertyName = getJavaPropertyName(name);
0842:                if (javaPropertyName == null)
0843:                    return; // not a Java property name, done with this method
0844:
0845:                for (Iterator iter = callback.methods.iterator(); iter
0846:                        .hasNext();) {
0847:                    Method method = (Method) iter.next();
0848:                    Class[] argTypes = method.getParameterTypes();
0849:                    Class resultType = method.getReturnType();
0850:                    int argCount = argTypes.length;
0851:                    if (argCount == 0) {
0852:                        if (name.startsWith("get")) {
0853:                            addUnassignedAlias(
0854:                                    getRubyCasedName(javaPropertyName),
0855:                                    assignedNames, callback);
0856:                            addUnassignedAlias(javaPropertyName, assignedNames,
0857:                                    callback);
0858:                        } else if (resultType == boolean.class
0859:                                && name.startsWith("is")) {
0860:                            String rubyName = getRubyCasedName(name
0861:                                    .substring(2));
0862:                            if (rubyName != null) {
0863:                                addUnassignedAlias(rubyName, assignedNames,
0864:                                        callback);
0865:                                addUnassignedAlias(rubyName + '?',
0866:                                        assignedNames, callback);
0867:                            }
0868:                            if (!javaPropertyName.equals(rubyName)) {
0869:                                addUnassignedAlias(javaPropertyName,
0870:                                        assignedNames, callback);
0871:                                addUnassignedAlias(javaPropertyName + '?',
0872:                                        assignedNames, callback);
0873:                            }
0874:                        }
0875:                    } else if (argCount == 1) {
0876:                        // indexed get
0877:                        if (argTypes[0] == int.class && name.startsWith("get")) {
0878:                            addUnassignedAlias(getRubyCasedName(name
0879:                                    .substring(3)), assignedNames, callback);
0880:                            addUnassignedAlias(javaPropertyName, assignedNames,
0881:                                    callback);
0882:                        } else if (resultType == void.class
0883:                                && name.startsWith("set")) {
0884:                            String rubyName = getRubyCasedName(name
0885:                                    .substring(3));
0886:                            if (rubyName != null) {
0887:                                addUnassignedAlias(rubyName + '=',
0888:                                        assignedNames, callback);
0889:                            }
0890:                            if (!javaPropertyName.equals(rubyName)) {
0891:                                addUnassignedAlias(javaPropertyName + '=',
0892:                                        assignedNames, callback);
0893:                            }
0894:                        }
0895:                    }
0896:                }
0897:            }
0898:
0899:            private static void addUnassignedAlias(String name,
0900:                    Map assignedNames, MethodCallback callback) {
0901:                if (name != null) {
0902:                    AssignedName assignedName = (AssignedName) assignedNames
0903:                            .get(name);
0904:                    if (assignedName == null) {
0905:                        callback.addAlias(name);
0906:                        assignedNames.put(name, new AssignedName(name,
0907:                                AssignedName.ALIAS));
0908:                    } else if (assignedName.type == AssignedName.ALIAS) {
0909:                        callback.addAlias(name);
0910:                    } else if (assignedName.type > AssignedName.ALIAS) {
0911:                        // TODO: there will be some additional logic in this branch
0912:                        // dealing with conflicting protected fields. 
0913:                        callback.addAlias(name);
0914:                        assignedNames.put(name, new AssignedName(name,
0915:                                AssignedName.ALIAS));
0916:                    }
0917:                }
0918:            }
0919:
0920:            private static final Pattern JAVA_PROPERTY_CHOPPER = Pattern
0921:                    .compile("(get|set|is)([A-Z0-9])(.*)");
0922:
0923:            public static String getJavaPropertyName(String beanMethodName) {
0924:                Matcher m = JAVA_PROPERTY_CHOPPER.matcher(beanMethodName);
0925:
0926:                if (!m.find())
0927:                    return null;
0928:                String javaPropertyName = m.group(2).toLowerCase() + m.group(3);
0929:                return javaPropertyName;
0930:            }
0931:
0932:            private static final Pattern CAMEL_CASE_SPLITTER = Pattern
0933:                    .compile("([a-z])([A-Z])");
0934:
0935:            public static String getRubyCasedName(String javaCasedName) {
0936:                Matcher m = CAMEL_CASE_SPLITTER.matcher(javaCasedName);
0937:                String rubyCasedName = m.replaceAll("$1_$2").toLowerCase();
0938:                if (rubyCasedName.equals(javaCasedName)) {
0939:                    return null;
0940:                }
0941:                return rubyCasedName;
0942:            }
0943:
0944:            public void setupInterfaceProxy(RubyClass proxy) {
0945:                Class javaClass = javaClass();
0946:                for (Iterator iter = constantFields.iterator(); iter.hasNext();) {
0947:                    ((ConstantField) iter.next()).install(proxy);
0948:                }
0949:                // setup constants for public inner classes
0950:                Class[] classes = javaClass.getClasses();
0951:                for (int i = classes.length; --i >= 0;) {
0952:                    if (javaClass == classes[i].getDeclaringClass()) {
0953:                        Class clazz = classes[i];
0954:                        String simpleName = getSimpleName(clazz);
0955:                        if (simpleName.length() == 0)
0956:                            continue;
0957:
0958:                        // Ignore bad constant named inner classes pending JRUBY-697
0959:                        if (IdUtil.isConstant(simpleName)
0960:                                && proxy.getConstantAt(simpleName) == null) {
0961:                            proxy.const_set(getRuntime().newString(simpleName),
0962:                                    Java.get_proxy_class(JAVA_UTILITIES, get(
0963:                                            getRuntime(), clazz)));
0964:                        }
0965:                    }
0966:                }
0967:            }
0968:
0969:            public void setupInterfaceModule(RubyModule module) {
0970:                Class javaClass = javaClass();
0971:                for (Iterator iter = constantFields.iterator(); iter.hasNext();) {
0972:                    ((ConstantField) iter.next()).install(module);
0973:                }
0974:                // setup constants for public inner classes
0975:                Class[] classes = javaClass.getClasses();
0976:                for (int i = classes.length; --i >= 0;) {
0977:                    if (javaClass == classes[i].getDeclaringClass()) {
0978:                        Class clazz = classes[i];
0979:                        String simpleName = getSimpleName(clazz);
0980:                        if (simpleName.length() == 0)
0981:                            continue;
0982:
0983:                        // Ignore bad constant named inner classes pending JRUBY-697
0984:                        if (IdUtil.isConstant(simpleName)
0985:                                && module.getConstantAt(simpleName) == null) {
0986:                            module.const_set(
0987:                                    getRuntime().newString(simpleName), Java
0988:                                            .get_proxy_class(JAVA_UTILITIES,
0989:                                                    get(getRuntime(), clazz)));
0990:                        }
0991:                    }
0992:                }
0993:            }
0994:
0995:            // unsynchronized, so create won't hold up get by other threads
0996:            public static JavaClass get(Ruby runtime, Class klass) {
0997:                JavaClass javaClass = runtime.getJavaSupport()
0998:                        .getJavaClassFromCache(klass);
0999:                if (javaClass == null) {
1000:                    javaClass = createJavaClass(runtime, klass);
1001:                }
1002:                return javaClass;
1003:            }
1004:
1005:            private static synchronized JavaClass createJavaClass(Ruby runtime,
1006:                    Class klass) {
1007:                // double-check the cache now that we're synchronized
1008:                JavaClass javaClass = runtime.getJavaSupport()
1009:                        .getJavaClassFromCache(klass);
1010:                if (javaClass == null) {
1011:                    javaClass = new JavaClass(runtime, klass);
1012:                    runtime.getJavaSupport().putJavaClassIntoCache(javaClass);
1013:                }
1014:                return javaClass;
1015:            }
1016:
1017:            public static RubyClass createJavaClassClass(Ruby runtime,
1018:                    RubyModule javaModule) {
1019:                // FIXME: Determine if a real allocator is needed here. Do people want to extend
1020:                // JavaClass? Do we want them to do that? Can you Class.new(JavaClass)? Should
1021:                // you be able to?
1022:                // TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here, since we don't intend for people to monkey with
1023:                // this type and it can't be marshalled. Confirm. JRUBY-415
1024:                RubyClass result = javaModule.defineClassUnder("JavaClass",
1025:                        javaModule.getClass("JavaObject"),
1026:                        ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
1027:
1028:                CallbackFactory callbackFactory = runtime
1029:                        .callbackFactory(JavaClass.class);
1030:
1031:                result.includeModule(runtime.getModule("Comparable"));
1032:
1033:                JavaObject.registerRubyMethods(runtime, result);
1034:
1035:                result.getMetaClass().defineFastMethod(
1036:                        "for_name",
1037:                        callbackFactory.getFastSingletonMethod("for_name",
1038:                                IRubyObject.class));
1039:                result.defineFastMethod("public?", callbackFactory
1040:                        .getFastMethod("public_p"));
1041:                result.defineFastMethod("protected?", callbackFactory
1042:                        .getFastMethod("protected_p"));
1043:                result.defineFastMethod("private?", callbackFactory
1044:                        .getFastMethod("private_p"));
1045:                result.defineFastMethod("final?", callbackFactory
1046:                        .getFastMethod("final_p"));
1047:                result.defineFastMethod("interface?", callbackFactory
1048:                        .getFastMethod("interface_p"));
1049:                result.defineFastMethod("array?", callbackFactory
1050:                        .getFastMethod("array_p"));
1051:                result.defineFastMethod("name", callbackFactory
1052:                        .getFastMethod("name"));
1053:                result.defineFastMethod("simple_name", callbackFactory
1054:                        .getFastMethod("simple_name"));
1055:                result.defineFastMethod("to_s", callbackFactory
1056:                        .getFastMethod("name"));
1057:                result.defineFastMethod("superclass", callbackFactory
1058:                        .getFastMethod("superclass"));
1059:                result.defineFastMethod("<=>", callbackFactory.getFastMethod(
1060:                        "op_cmp", IRubyObject.class));
1061:                result.defineFastMethod("java_instance_methods",
1062:                        callbackFactory.getFastMethod("java_instance_methods"));
1063:                result.defineFastMethod("java_class_methods", callbackFactory
1064:                        .getFastMethod("java_class_methods"));
1065:                result.defineFastMethod("java_method", callbackFactory
1066:                        .getFastOptMethod("java_method"));
1067:                result.defineFastMethod("constructors", callbackFactory
1068:                        .getFastMethod("constructors"));
1069:                result.defineFastMethod("constructor", callbackFactory
1070:                        .getFastOptMethod("constructor"));
1071:                result.defineFastMethod("array_class", callbackFactory
1072:                        .getFastMethod("array_class"));
1073:                result.defineFastMethod("new_array", callbackFactory
1074:                        .getFastMethod("new_array", IRubyObject.class));
1075:                result.defineFastMethod("fields", callbackFactory
1076:                        .getFastMethod("fields"));
1077:                result.defineFastMethod("field", callbackFactory.getFastMethod(
1078:                        "field", IRubyObject.class));
1079:                result.defineFastMethod("interfaces", callbackFactory
1080:                        .getFastMethod("interfaces"));
1081:                result.defineFastMethod("primitive?", callbackFactory
1082:                        .getFastMethod("primitive_p"));
1083:                result.defineFastMethod("assignable_from?", callbackFactory
1084:                        .getFastMethod("assignable_from_p", IRubyObject.class));
1085:                result.defineFastMethod("component_type", callbackFactory
1086:                        .getFastMethod("component_type"));
1087:                result.defineFastMethod("declared_instance_methods",
1088:                        callbackFactory
1089:                                .getFastMethod("declared_instance_methods"));
1090:                result
1091:                        .defineFastMethod(
1092:                                "declared_class_methods",
1093:                                callbackFactory
1094:                                        .getFastMethod("declared_class_methods"));
1095:                result.defineFastMethod("declared_fields", callbackFactory
1096:                        .getFastMethod("declared_fields"));
1097:                result.defineFastMethod("declared_field", callbackFactory
1098:                        .getFastMethod("declared_field", IRubyObject.class));
1099:                result.defineFastMethod("declared_constructors",
1100:                        callbackFactory.getFastMethod("declared_constructors"));
1101:                result.defineFastMethod("declared_constructor", callbackFactory
1102:                        .getFastOptMethod("declared_constructor"));
1103:                result.defineFastMethod("declared_classes", callbackFactory
1104:                        .getFastMethod("declared_classes"));
1105:                result.defineFastMethod("declared_method", callbackFactory
1106:                        .getFastOptMethod("declared_method"));
1107:                result.defineFastMethod("define_instance_methods_for_proxy",
1108:                        callbackFactory.getFastMethod(
1109:                                "define_instance_methods_for_proxy",
1110:                                IRubyObject.class));
1111:
1112:                result.getMetaClass().undefineMethod("new");
1113:                result.getMetaClass().undefineMethod("allocate");
1114:
1115:                return result;
1116:            }
1117:
1118:            public static synchronized JavaClass forName(Ruby runtime,
1119:                    String className) {
1120:                Class klass = runtime.getJavaSupport().loadJavaClass(className);
1121:                return JavaClass.get(runtime, klass);
1122:            }
1123:
1124:            public static JavaClass for_name(IRubyObject recv, IRubyObject name) {
1125:                return forName(recv.getRuntime(), name.asSymbol());
1126:            }
1127:
1128:            // TODO: part of interim solution, can be removed soon
1129:            private Set getPublicFieldNames(boolean isStatic) {
1130:                // we're not checking for final here; since the purpose is to prevent
1131:                // shortcut property names from being created that conflict with
1132:                // field names, it won't make sense to allow the property setter (name=)
1133:                // to be created but not the getter.
1134:                int mask = Modifier.PUBLIC | Modifier.STATIC;
1135:                int want = isStatic ? Modifier.PUBLIC | Modifier.STATIC
1136:                        : Modifier.PUBLIC;
1137:                Set names = new HashSet();
1138:                names.add("class");
1139:                Field[] fields = ((Class) getValue()).getFields();
1140:                for (int i = fields.length; --i >= 0;) {
1141:                    if ((fields[i].getModifiers() & mask) == want) {
1142:                        names.add(fields[i].getName());
1143:                    }
1144:                }
1145:                return names;
1146:            }
1147:
1148:            /**
1149:             *  Get all methods grouped by name (e.g. 'new => {new(), new(int), new(int, int)}, ...')
1150:             *  @param isStatic determines whether you want static or instance methods from the class
1151:             */
1152:            private Map getMethodsClumped(boolean isStatic, Set assignedNames) {
1153:                System.out.println("JC.gmc");
1154:                Map map = new HashMap();
1155:                if (((Class) getValue()).isInterface()) {
1156:                    return map;
1157:                }
1158:
1159:                Method methods[] = javaClass().getMethods();
1160:
1161:                for (int i = 0; i < methods.length; i++) {
1162:                    if (isStatic != Modifier
1163:                            .isStatic(methods[i].getModifiers())) {
1164:                        continue;
1165:                    }
1166:
1167:                    String key = methods[i].getName();
1168:                    RubyArray methodsWithName = (RubyArray) map.get(key);
1169:
1170:                    if (methodsWithName == null) {
1171:                        methodsWithName = RubyArray.newArrayLight(getRuntime());
1172:                        map.put(key, methodsWithName);
1173:                        assignedNames.add(key);
1174:                    }
1175:
1176:                    methodsWithName.append(JavaMethod.create(getRuntime(),
1177:                            methods[i]));
1178:                }
1179:
1180:                return map;
1181:            }
1182:
1183:            private Map getPropertysClumped(Set assignedNames) {
1184:                System.out.println("JC.gpc");
1185:                Map map = new HashMap();
1186:                BeanInfo info;
1187:
1188:                try {
1189:                    info = Introspector.getBeanInfo(javaClass());
1190:                } catch (IntrospectionException e) {
1191:                    return map;
1192:                }
1193:
1194:                PropertyDescriptor[] descriptors = info
1195:                        .getPropertyDescriptors();
1196:                System.out.println("got bean info for class "
1197:                        + javaClass().getName() + ": " + descriptors.length);
1198:                for (int i = 0; i < descriptors.length; i++) {
1199:                    Method readMethod = descriptors[i].getReadMethod();
1200:
1201:                    if (readMethod != null) {
1202:                        String key = readMethod.getName();
1203:                        List aliases = (List) map.get(key);
1204:
1205:                        if (aliases == null) {
1206:                            aliases = new ArrayList();
1207:
1208:                            map.put(key, aliases);
1209:                        }
1210:
1211:                        if (readMethod.getReturnType() == Boolean.class
1212:                                || readMethod.getReturnType() == boolean.class) {
1213:                            aliases.add(descriptors[i].getName() + "?");
1214:                        }
1215:                        if (!assignedNames.contains(descriptors[i].getName())) {
1216:                            aliases.add(descriptors[i].getName());
1217:                        }
1218:                    }
1219:
1220:                    Method writeMethod = descriptors[i].getWriteMethod();
1221:
1222:                    if (writeMethod != null) {
1223:                        String key = writeMethod.getName();
1224:                        List aliases = (List) map.get(key);
1225:
1226:                        if (aliases == null) {
1227:                            aliases = new ArrayList();
1228:                            map.put(key, aliases);
1229:                        }
1230:
1231:                        if (!assignedNames.contains(descriptors[i].getName())) {
1232:                            aliases.add(descriptors[i].getName() + "=");
1233:                        }
1234:                    }
1235:                }
1236:
1237:                return map;
1238:            }
1239:
1240:            private void define_instance_method_for_proxy(
1241:                    final RubyClass proxy, List names, final RubyArray methods) {
1242:                final RubyModule javaUtilities = JAVA_UTILITIES;
1243:                Callback method;
1244:                if (methods.size() > 1) {
1245:                    method = new Callback() {
1246:                        private IntHashMap matchingMethods = new IntHashMap();
1247:
1248:                        public IRubyObject execute(IRubyObject self,
1249:                                IRubyObject[] args, Block block) {
1250:                            int len = args.length;
1251:                            IRubyObject[] argsArray = new IRubyObject[len + 1];
1252:
1253:                            argsArray[0] = self
1254:                                    .getInstanceVariable("@java_object");
1255:
1256:                            int argsTypeHash = 0;
1257:                            for (int j = 0; j < len; j++) {
1258:                                argsArray[j + 1] = Java.ruby_to_java(proxy,
1259:                                        args[j], Block.NULL_BLOCK);
1260:                                argsTypeHash += 3 * args[j].getMetaClass().id;
1261:                            }
1262:
1263:                            IRubyObject match = (IRubyObject) matchingMethods
1264:                                    .get(argsTypeHash);
1265:                            if (match == null) {
1266:                                match = Java.matching_method_internal(
1267:                                        javaUtilities, methods, argsArray, 1,
1268:                                        len);
1269:                                matchingMethods.put(argsTypeHash, match);
1270:                            }
1271:
1272:                            return Java.java_to_ruby(self, ((JavaMethod) match)
1273:                                    .invoke(argsArray), Block.NULL_BLOCK);
1274:                        }
1275:
1276:                        public Arity getArity() {
1277:                            return Arity.optional();
1278:                        }
1279:                    };
1280:                } else {
1281:                    final JavaMethod METHOD = (JavaMethod) methods
1282:                            .eltInternal(0);
1283:                    method = new Callback() {
1284:                        public IRubyObject execute(IRubyObject self,
1285:                                IRubyObject[] args, Block block) {
1286:                            int len = args.length;
1287:                            IRubyObject[] argsArray = new IRubyObject[len + 1];
1288:                            argsArray[0] = self
1289:                                    .getInstanceVariable("@java_object");
1290:                            for (int j = 0; j < len; j++) {
1291:                                argsArray[j + 1] = Java.ruby_to_java(proxy,
1292:                                        args[j], Block.NULL_BLOCK);
1293:                            }
1294:                            return Java.java_to_ruby(self, METHOD
1295:                                    .invoke(argsArray), Block.NULL_BLOCK);
1296:                        }
1297:
1298:                        public Arity getArity() {
1299:                            return Arity.optional();
1300:                        }
1301:                    };
1302:                }
1303:
1304:                for (Iterator iter = names.iterator(); iter.hasNext();) {
1305:                    String methodName = (String) iter.next();
1306:
1307:                    // We do not override class since it is too important to be overridden by getClass
1308:                    // short name.
1309:                    if (!methodName.equals("class")) {
1310:                        proxy.defineFastMethod(methodName, method);
1311:
1312:                        String rubyCasedName = getRubyCasedName(methodName);
1313:                        if (rubyCasedName != null) {
1314:                            proxy.defineAlias(rubyCasedName, methodName);
1315:                        }
1316:                    }
1317:                }
1318:            }
1319:
1320:            private static final Callback __jsend_method = new Callback() {
1321:                public IRubyObject execute(IRubyObject self,
1322:                        IRubyObject[] args, Block block) {
1323:                    String name = args[0].asSymbol();
1324:
1325:                    // FIXME: why newMethod ?
1326:                    RubyMethod method = (org.jruby.RubyMethod) self
1327:                            .getMetaClass().newMethod(self, name, true);
1328:                    int v = RubyNumeric.fix2int(method.arity());
1329:
1330:                    IRubyObject[] newArgs = new IRubyObject[args.length - 1];
1331:                    System.arraycopy(args, 1, newArgs, 0, newArgs.length);
1332:                    if (DEBUG)
1333:                        System.out.println("__jsend method => '" + name
1334:                                + "'; arity = " + v + ", args.length = "
1335:                                + newArgs.length);
1336:
1337:                    if (v < 0 || v == (newArgs.length)) {
1338:                        if (DEBUG)
1339:                            System.out.println("  calling self");
1340:                        return self.callMethod(self.getRuntime()
1341:                                .getCurrentContext(), name, newArgs,
1342:                                CallType.FUNCTIONAL, block);
1343:                    } else {
1344:                        if (DEBUG)
1345:                            System.out.println("  calling super");
1346:                        return self.callMethod(self.getRuntime()
1347:                                .getCurrentContext(), self.getMetaClass()
1348:                                .getSuperClass(), name, newArgs,
1349:                                CallType.SUPER, block);
1350:                    }
1351:                }
1352:
1353:                public Arity getArity() {
1354:                    return Arity.optional();
1355:                }
1356:            };
1357:
1358:            public IRubyObject define_instance_methods_for_proxy(IRubyObject arg) {
1359:                assert arg instanceof  RubyClass;
1360:                // shouldn't be getting called any more
1361:                System.out.println("JC.define_instance_methods_for_proxy");
1362:                Set assignedNames = getPublicFieldNames(false);
1363:                Map methodsClump = getMethodsClumped(false, assignedNames);
1364:                Map aliasesClump = getPropertysClumped(assignedNames);
1365:                RubyClass proxy = (RubyClass) arg;
1366:
1367:                proxy.defineFastMethod("__jsend!", __jsend_method);
1368:
1369:                for (Iterator iter = methodsClump.keySet().iterator(); iter
1370:                        .hasNext();) {
1371:                    String name = (String) iter.next();
1372:                    RubyArray methods = (RubyArray) methodsClump.get(name);
1373:                    List aliases = (List) aliasesClump.get(name);
1374:
1375:                    if (aliases == null) {
1376:                        aliases = new ArrayList();
1377:                    }
1378:
1379:                    aliases.add(name);
1380:
1381:                    define_instance_method_for_proxy(proxy, aliases, methods);
1382:                }
1383:
1384:                return getRuntime().getNil();
1385:            }
1386:
1387:            public RubyBoolean public_p() {
1388:                return getRuntime().newBoolean(
1389:                        Modifier.isPublic(javaClass().getModifiers()));
1390:            }
1391:
1392:            public RubyBoolean protected_p() {
1393:                return getRuntime().newBoolean(
1394:                        Modifier.isProtected(javaClass().getModifiers()));
1395:            }
1396:
1397:            public RubyBoolean private_p() {
1398:                return getRuntime().newBoolean(
1399:                        Modifier.isPrivate(javaClass().getModifiers()));
1400:            }
1401:
1402:            public Class javaClass() {
1403:                return (Class) getValue();
1404:            }
1405:
1406:            public RubyBoolean final_p() {
1407:                return getRuntime().newBoolean(
1408:                        Modifier.isFinal(javaClass().getModifiers()));
1409:            }
1410:
1411:            public RubyBoolean interface_p() {
1412:                return getRuntime().newBoolean(javaClass().isInterface());
1413:            }
1414:
1415:            public RubyBoolean array_p() {
1416:                return getRuntime().newBoolean(javaClass().isArray());
1417:            }
1418:
1419:            public RubyString name() {
1420:                return getRuntime().newString(javaClass().getName());
1421:            }
1422:
1423:            private static String getSimpleName(Class class_) {
1424:                if (class_.isArray()) {
1425:                    return getSimpleName(class_.getComponentType()) + "[]";
1426:                }
1427:
1428:                String className = class_.getName();
1429:
1430:                int i = className.lastIndexOf('$');
1431:                if (i != -1) {
1432:                    do {
1433:                        i++;
1434:                    } while (i < className.length()
1435:                            && Character.isDigit(className.charAt(i)));
1436:                    return className.substring(i);
1437:                }
1438:
1439:                return className.substring(className.lastIndexOf('.') + 1);
1440:            }
1441:
1442:            public RubyString simple_name() {
1443:                return getRuntime().newString(getSimpleName(javaClass()));
1444:            }
1445:
1446:            public IRubyObject super class() {
1447:                Class super class = javaClass().getSuperclass();
1448:                if (super class == null) {
1449:                    return getRuntime().getNil();
1450:                }
1451:                return JavaClass.get(getRuntime(), super class);
1452:            }
1453:
1454:            public RubyFixnum op_cmp(IRubyObject other) {
1455:                if (!(other instanceof  JavaClass)) {
1456:                    throw getRuntime().newTypeError(
1457:                            "<=> requires JavaClass (" + other.getType()
1458:                                    + " given)");
1459:                }
1460:                JavaClass otherClass = (JavaClass) other;
1461:                if (this .javaClass() == otherClass.javaClass()) {
1462:                    return getRuntime().newFixnum(0);
1463:                }
1464:                if (otherClass.javaClass().isAssignableFrom(this .javaClass())) {
1465:                    return getRuntime().newFixnum(-1);
1466:                }
1467:                return getRuntime().newFixnum(1);
1468:            }
1469:
1470:            public RubyArray java_instance_methods() {
1471:                return java_methods(javaClass().getMethods(), false);
1472:            }
1473:
1474:            public RubyArray declared_instance_methods() {
1475:                return java_methods(javaClass().getDeclaredMethods(), false);
1476:            }
1477:
1478:            private RubyArray java_methods(Method[] methods, boolean isStatic) {
1479:                RubyArray result = getRuntime().newArray(methods.length);
1480:                for (int i = 0; i < methods.length; i++) {
1481:                    Method method = methods[i];
1482:                    if (isStatic == Modifier.isStatic(method.getModifiers())) {
1483:                        result.append(JavaMethod.create(getRuntime(), method));
1484:                    }
1485:                }
1486:                return result;
1487:            }
1488:
1489:            public RubyArray java_class_methods() {
1490:                return java_methods(javaClass().getMethods(), true);
1491:            }
1492:
1493:            public RubyArray declared_class_methods() {
1494:                return java_methods(javaClass().getDeclaredMethods(), true);
1495:            }
1496:
1497:            public JavaMethod java_method(IRubyObject[] args)
1498:                    throws ClassNotFoundException {
1499:                String methodName = args[0].asSymbol();
1500:                Class[] argumentTypes = buildArgumentTypes(args);
1501:                return JavaMethod.create(getRuntime(), javaClass(), methodName,
1502:                        argumentTypes);
1503:            }
1504:
1505:            public JavaMethod declared_method(IRubyObject[] args)
1506:                    throws ClassNotFoundException {
1507:                String methodName = args[0].asSymbol();
1508:                Class[] argumentTypes = buildArgumentTypes(args);
1509:                return JavaMethod.createDeclared(getRuntime(), javaClass(),
1510:                        methodName, argumentTypes);
1511:            }
1512:
1513:            private Class[] buildArgumentTypes(IRubyObject[] args)
1514:                    throws ClassNotFoundException {
1515:                if (args.length < 1) {
1516:                    throw getRuntime().newArgumentError(args.length, 1);
1517:                }
1518:                Class[] argumentTypes = new Class[args.length - 1];
1519:                for (int i = 1; i < args.length; i++) {
1520:                    JavaClass type = for_name(this , args[i]);
1521:                    argumentTypes[i - 1] = type.javaClass();
1522:                }
1523:                return argumentTypes;
1524:            }
1525:
1526:            public RubyArray constructors() {
1527:                if (constructors == null) {
1528:                    constructors = buildConstructors(javaClass()
1529:                            .getConstructors());
1530:                }
1531:                return constructors;
1532:            }
1533:
1534:            public RubyArray declared_classes() {
1535:                // TODO: should be able to partially work around this by calling
1536:                // javaClass().getClasses, which will return any public inner classes.
1537:                if (Ruby.isSecurityRestricted()) // Can't even get inner classes?
1538:                    return getRuntime().newArray(0);
1539:                Class[] classes = javaClass().getDeclaredClasses();
1540:                List accessibleClasses = new ArrayList();
1541:                for (int i = 0; i < classes.length; i++) {
1542:                    if (Modifier.isPublic(classes[i].getModifiers())) {
1543:                        accessibleClasses.add(classes[i]);
1544:                    }
1545:                }
1546:                return buildClasses((Class[]) accessibleClasses
1547:                        .toArray(new Class[accessibleClasses.size()]));
1548:            }
1549:
1550:            private RubyArray buildClasses(Class[] classes) {
1551:                RubyArray result = getRuntime().newArray(classes.length);
1552:                for (int i = 0; i < classes.length; i++) {
1553:                    result.append(new JavaClass(getRuntime(), classes[i]));
1554:                }
1555:                return result;
1556:            }
1557:
1558:            public RubyArray declared_constructors() {
1559:                return buildConstructors(javaClass().getDeclaredConstructors());
1560:            }
1561:
1562:            private RubyArray buildConstructors(Constructor[] constructors) {
1563:                RubyArray result = getRuntime().newArray(constructors.length);
1564:                for (int i = 0; i < constructors.length; i++) {
1565:                    result.append(new JavaConstructor(getRuntime(),
1566:                            constructors[i]));
1567:                }
1568:                return result;
1569:            }
1570:
1571:            public JavaConstructor constructor(IRubyObject[] args) {
1572:                try {
1573:                    Class[] parameterTypes = buildClassArgs(args);
1574:                    Constructor constructor;
1575:                    constructor = javaClass().getConstructor(parameterTypes);
1576:                    return new JavaConstructor(getRuntime(), constructor);
1577:                } catch (NoSuchMethodException nsme) {
1578:                    throw getRuntime().newNameError(
1579:                            "no matching java constructor", null);
1580:                }
1581:            }
1582:
1583:            public JavaConstructor declared_constructor(IRubyObject[] args) {
1584:                try {
1585:                    Class[] parameterTypes = buildClassArgs(args);
1586:                    Constructor constructor;
1587:                    constructor = javaClass().getDeclaredConstructor(
1588:                            parameterTypes);
1589:                    return new JavaConstructor(getRuntime(), constructor);
1590:                } catch (NoSuchMethodException nsme) {
1591:                    throw getRuntime().newNameError(
1592:                            "no matching java constructor", null);
1593:                }
1594:            }
1595:
1596:            private Class[] buildClassArgs(IRubyObject[] args) {
1597:                Class[] parameterTypes = new Class[args.length];
1598:                for (int i = 0; i < args.length; i++) {
1599:                    String name = args[i].asSymbol();
1600:                    parameterTypes[i] = getRuntime().getJavaSupport()
1601:                            .loadJavaClass(name);
1602:                }
1603:                return parameterTypes;
1604:            }
1605:
1606:            public JavaClass array_class() {
1607:                return JavaClass.get(getRuntime(), Array.newInstance(
1608:                        javaClass(), 0).getClass());
1609:            }
1610:
1611:            public JavaObject new_array(IRubyObject lengthArgument) {
1612:                if (lengthArgument instanceof  RubyInteger) {
1613:                    // one-dimensional array
1614:                    int length = (int) ((RubyInteger) lengthArgument)
1615:                            .getLongValue();
1616:                    return new JavaArray(getRuntime(), Array.newInstance(
1617:                            javaClass(), length));
1618:                } else if (lengthArgument instanceof  RubyArray) {
1619:                    // n-dimensional array
1620:                    List list = ((RubyArray) lengthArgument).getList();
1621:                    int length = list.size();
1622:                    if (length == 0) {
1623:                        throw getRuntime().newArgumentError(
1624:                                "empty dimensions specifier for java array");
1625:                    }
1626:                    int[] dimensions = new int[length];
1627:                    for (int i = length; --i >= 0;) {
1628:                        IRubyObject dimensionLength = (IRubyObject) list.get(i);
1629:                        if (!(dimensionLength instanceof  RubyInteger)) {
1630:                            throw getRuntime().newTypeError(dimensionLength,
1631:                                    getRuntime().getClass("Integer"));
1632:                        }
1633:                        dimensions[i] = (int) ((RubyInteger) dimensionLength)
1634:                                .getLongValue();
1635:                    }
1636:                    return new JavaArray(getRuntime(), Array.newInstance(
1637:                            javaClass(), dimensions));
1638:                } else {
1639:                    throw getRuntime().newArgumentError(
1640:                            "invalid length or dimensions specifier for java array"
1641:                                    + " - must be Integer or Array of Integer");
1642:                }
1643:            }
1644:
1645:            public RubyArray fields() {
1646:                return buildFieldResults(javaClass().getFields());
1647:            }
1648:
1649:            public RubyArray declared_fields() {
1650:                return buildFieldResults(javaClass().getDeclaredFields());
1651:            }
1652:
1653:            private RubyArray buildFieldResults(Field[] fields) {
1654:                RubyArray result = getRuntime().newArray(fields.length);
1655:                for (int i = 0; i < fields.length; i++) {
1656:                    result.append(new JavaField(getRuntime(), fields[i]));
1657:                }
1658:                return result;
1659:            }
1660:
1661:            public JavaField field(IRubyObject name) {
1662:                String stringName = name.asSymbol();
1663:                try {
1664:                    Field field = javaClass().getField(stringName);
1665:                    return new JavaField(getRuntime(), field);
1666:                } catch (NoSuchFieldException nsfe) {
1667:                    throw undefinedFieldError(stringName);
1668:                }
1669:            }
1670:
1671:            public JavaField declared_field(IRubyObject name) {
1672:                String stringName = name.asSymbol();
1673:                try {
1674:                    Field field = javaClass().getDeclaredField(stringName);
1675:                    return new JavaField(getRuntime(), field);
1676:                } catch (NoSuchFieldException nsfe) {
1677:                    throw undefinedFieldError(stringName);
1678:                }
1679:            }
1680:
1681:            private RaiseException undefinedFieldError(String name) {
1682:                return getRuntime().newNameError(
1683:                        "undefined field '" + name + "' for class '"
1684:                                + javaClass().getName() + "'", name);
1685:            }
1686:
1687:            public RubyArray interfaces() {
1688:                Class[] interfaces = javaClass().getInterfaces();
1689:                RubyArray result = getRuntime().newArray(interfaces.length);
1690:                for (int i = 0; i < interfaces.length; i++) {
1691:                    result.append(JavaClass.get(getRuntime(), interfaces[i]));
1692:                }
1693:                return result;
1694:            }
1695:
1696:            public RubyBoolean primitive_p() {
1697:                return getRuntime().newBoolean(isPrimitive());
1698:            }
1699:
1700:            public RubyBoolean assignable_from_p(IRubyObject other) {
1701:                if (!(other instanceof  JavaClass)) {
1702:                    throw getRuntime().newTypeError(
1703:                            "assignable_from requires JavaClass ("
1704:                                    + other.getType() + " given)");
1705:                }
1706:
1707:                Class otherClass = ((JavaClass) other).javaClass();
1708:                return assignable(javaClass(), otherClass) ? getRuntime()
1709:                        .getTrue() : getRuntime().getFalse();
1710:            }
1711:
1712:            static boolean assignable(Class this Class, Class otherClass) {
1713:                if (!this Class.isPrimitive() && otherClass == Void.TYPE
1714:                        || this Class.isAssignableFrom(otherClass)) {
1715:                    return true;
1716:                }
1717:
1718:                otherClass = JavaUtil.primitiveToWrapper(otherClass);
1719:                this Class = JavaUtil.primitiveToWrapper(this Class);
1720:
1721:                if (this Class.isAssignableFrom(otherClass)) {
1722:                    return true;
1723:                }
1724:                if (Number.class.isAssignableFrom(this Class)) {
1725:                    if (Number.class.isAssignableFrom(otherClass)) {
1726:                        return true;
1727:                    }
1728:                    if (otherClass.equals(Character.class)) {
1729:                        return true;
1730:                    }
1731:                }
1732:                if (this Class.equals(Character.class)) {
1733:                    if (Number.class.isAssignableFrom(otherClass)) {
1734:                        return true;
1735:                    }
1736:                }
1737:                return false;
1738:            }
1739:
1740:            private boolean isPrimitive() {
1741:                return javaClass().isPrimitive();
1742:            }
1743:
1744:            public JavaClass component_type() {
1745:                if (!javaClass().isArray()) {
1746:                    throw getRuntime().newTypeError("not a java array-class");
1747:                }
1748:                return JavaClass.get(getRuntime(), javaClass()
1749:                        .getComponentType());
1750:            }
1751:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.