Source Code Cross Referenced for NativeJavaObject.java in  » Scripting » rhino » org » mozilla » javascript » 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 » rhino » org.mozilla.javascript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002:         *
003:         * ***** BEGIN LICENSE BLOCK *****
004:         * Version: MPL 1.1/GPL 2.0
005:         *
006:         * The contents of this file are subject to the Mozilla Public License Version
007:         * 1.1 (the "License"); you may not use this file except in compliance with
008:         * the License. You may obtain a copy of the License at
009:         * http://www.mozilla.org/MPL/
010:         *
011:         * Software distributed under the License is distributed on an "AS IS" basis,
012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013:         * for the specific language governing rights and limitations under the
014:         * License.
015:         *
016:         * The Original Code is Rhino code, released
017:         * May 6, 1999.
018:         *
019:         * The Initial Developer of the Original Code is
020:         * Netscape Communications Corporation.
021:         * Portions created by the Initial Developer are Copyright (C) 1997-2000
022:         * the Initial Developer. All Rights Reserved.
023:         *
024:         * Contributor(s):
025:         *   Norris Boyd
026:         *   Igor Bukanov
027:         *   Frank Mitchell
028:         *   Mike Shaver
029:         *   Kemal Bayram
030:         *
031:         * Alternatively, the contents of this file may be used under the terms of
032:         * the GNU General Public License Version 2 or later (the "GPL"), in which
033:         * case the provisions of the GPL are applicable instead of those above. If
034:         * you wish to allow use of your version of this file only under the terms of
035:         * the GPL and not to allow others to use your version of this file under the
036:         * MPL, indicate your decision by deleting the provisions above and replacing
037:         * them with the notice and other provisions required by the GPL. If you do
038:         * not delete the provisions above, a recipient may use your version of this
039:         * file under either the MPL or the GPL.
040:         *
041:         * ***** END LICENSE BLOCK ***** */
042:
043:        package org.mozilla.javascript;
044:
045:        import java.io.*;
046:        import java.lang.reflect.*;
047:        import java.util.Hashtable;
048:        import java.util.Date;
049:
050:        /**
051:         * This class reflects non-Array Java objects into the JavaScript environment.  It
052:         * reflect fields directly, and uses NativeJavaMethod objects to reflect (possibly
053:         * overloaded) methods.<p>
054:         *
055:         * @author Mike Shaver
056:         * @see NativeJavaArray
057:         * @see NativeJavaPackage
058:         * @see NativeJavaClass
059:         */
060:
061:        public class NativeJavaObject implements  Scriptable, Wrapper,
062:                Serializable {
063:            static final long serialVersionUID = -6948590651130498591L;
064:
065:            public NativeJavaObject() {
066:            }
067:
068:            public NativeJavaObject(Scriptable scope, Object javaObject,
069:                    Class staticType) {
070:                this (scope, javaObject, staticType, false);
071:            }
072:
073:            public NativeJavaObject(Scriptable scope, Object javaObject,
074:                    Class staticType, boolean isAdapter) {
075:                this .parent = scope;
076:                this .javaObject = javaObject;
077:                this .staticType = staticType;
078:                this .isAdapter = isAdapter;
079:                initMembers();
080:            }
081:
082:            protected void initMembers() {
083:                Class dynamicType;
084:                if (javaObject != null) {
085:                    dynamicType = javaObject.getClass();
086:                } else {
087:                    dynamicType = staticType;
088:                }
089:                members = JavaMembers.lookupClass(parent, dynamicType,
090:                        staticType, isAdapter);
091:                fieldAndMethods = members.getFieldAndMethodsObjects(this ,
092:                        javaObject, false);
093:            }
094:
095:            public boolean has(String name, Scriptable start) {
096:                return members.has(name, false);
097:            }
098:
099:            public boolean has(int index, Scriptable start) {
100:                return false;
101:            }
102:
103:            public Object get(String name, Scriptable start) {
104:                if (fieldAndMethods != null) {
105:                    Object result = fieldAndMethods.get(name);
106:                    if (result != null) {
107:                        return result;
108:                    }
109:                }
110:                // TODO: passing 'this' as the scope is bogus since it has
111:                //  no parent scope
112:                return members.get(this , name, javaObject, false);
113:            }
114:
115:            public Object get(int index, Scriptable start) {
116:                throw members.reportMemberNotFound(Integer.toString(index));
117:            }
118:
119:            public void put(String name, Scriptable start, Object value) {
120:                // We could be asked to modify the value of a property in the
121:                // prototype. Since we can't add a property to a Java object,
122:                // we modify it in the prototype rather than copy it down.
123:                if (prototype == null || members.has(name, false))
124:                    members.put(this , name, javaObject, value, false);
125:                else
126:                    prototype.put(name, prototype, value);
127:            }
128:
129:            public void put(int index, Scriptable start, Object value) {
130:                throw members.reportMemberNotFound(Integer.toString(index));
131:            }
132:
133:            public boolean hasInstance(Scriptable value) {
134:                // This is an instance of a Java class, so always return false
135:                return false;
136:            }
137:
138:            public void delete(String name) {
139:            }
140:
141:            public void delete(int index) {
142:            }
143:
144:            public Scriptable getPrototype() {
145:                if (prototype == null && javaObject instanceof  String) {
146:                    return ScriptableObject.getClassPrototype(parent, "String");
147:                }
148:                return prototype;
149:            }
150:
151:            /**
152:             * Sets the prototype of the object.
153:             */
154:            public void setPrototype(Scriptable m) {
155:                prototype = m;
156:            }
157:
158:            /**
159:             * Returns the parent (enclosing) scope of the object.
160:             */
161:            public Scriptable getParentScope() {
162:                return parent;
163:            }
164:
165:            /**
166:             * Sets the parent (enclosing) scope of the object.
167:             */
168:            public void setParentScope(Scriptable m) {
169:                parent = m;
170:            }
171:
172:            public Object[] getIds() {
173:                return members.getIds(false);
174:            }
175:
176:            /**
177:             @deprecated Use {@link Context#getWrapFactory()} together with calling {@link
178:             WrapFactory#wrap(Context, Scriptable, Object, Class)}
179:             */
180:            public static Object wrap(Scriptable scope, Object obj,
181:                    Class staticType) {
182:
183:                Context cx = Context.getContext();
184:                return cx.getWrapFactory().wrap(cx, scope, obj, staticType);
185:            }
186:
187:            public Object unwrap() {
188:                return javaObject;
189:            }
190:
191:            public String getClassName() {
192:                return "JavaObject";
193:            }
194:
195:            public Object getDefaultValue(Class hint) {
196:                Object value;
197:                if (hint == null) {
198:                    if (javaObject instanceof  Boolean) {
199:                        hint = ScriptRuntime.BooleanClass;
200:                    }
201:                }
202:                if (hint == null || hint == ScriptRuntime.StringClass) {
203:                    value = javaObject.toString();
204:                } else {
205:                    String converterName;
206:                    if (hint == ScriptRuntime.BooleanClass) {
207:                        converterName = "booleanValue";
208:                    } else if (hint == ScriptRuntime.NumberClass) {
209:                        converterName = "doubleValue";
210:                    } else {
211:                        throw Context.reportRuntimeError0("msg.default.value");
212:                    }
213:                    Object converterObject = get(converterName, this );
214:                    if (converterObject instanceof  Function) {
215:                        Function f = (Function) converterObject;
216:                        value = f.call(Context.getContext(),
217:                                f.getParentScope(), this ,
218:                                ScriptRuntime.emptyArgs);
219:                    } else {
220:                        if (hint == ScriptRuntime.NumberClass
221:                                && javaObject instanceof  Boolean) {
222:                            boolean b = ((Boolean) javaObject).booleanValue();
223:                            value = ScriptRuntime.wrapNumber(b ? 1.0 : 0.0);
224:                        } else {
225:                            value = javaObject.toString();
226:                        }
227:                    }
228:                }
229:                return value;
230:            }
231:
232:            /**
233:             * Determine whether we can/should convert between the given type and the
234:             * desired one.  This should be superceded by a conversion-cost calculation
235:             * function, but for now I'll hide behind precedent.
236:             */
237:            public static boolean canConvert(Object fromObj, Class to) {
238:                int weight = getConversionWeight(fromObj, to);
239:
240:                return (weight < CONVERSION_NONE);
241:            }
242:
243:            private static final int JSTYPE_UNDEFINED = 0; // undefined type
244:            private static final int JSTYPE_NULL = 1; // null
245:            private static final int JSTYPE_BOOLEAN = 2; // boolean
246:            private static final int JSTYPE_NUMBER = 3; // number
247:            private static final int JSTYPE_STRING = 4; // string
248:            private static final int JSTYPE_JAVA_CLASS = 5; // JavaClass
249:            private static final int JSTYPE_JAVA_OBJECT = 6; // JavaObject
250:            private static final int JSTYPE_JAVA_ARRAY = 7; // JavaArray
251:            private static final int JSTYPE_OBJECT = 8; // Scriptable
252:
253:            static final byte CONVERSION_TRIVIAL = 1;
254:            static final byte CONVERSION_NONTRIVIAL = 0;
255:            static final byte CONVERSION_NONE = 99;
256:
257:            /**
258:             * Derive a ranking based on how "natural" the conversion is.
259:             * The special value CONVERSION_NONE means no conversion is possible,
260:             * and CONVERSION_NONTRIVIAL signals that more type conformance testing
261:             * is required.
262:             * Based on
263:             * <a href="http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html">
264:             * "preferred method conversions" from Live Connect 3</a>
265:             */
266:            static int getConversionWeight(Object fromObj, Class to) {
267:                int fromCode = getJSTypeCode(fromObj);
268:
269:                switch (fromCode) {
270:
271:                case JSTYPE_UNDEFINED:
272:                    if (to == ScriptRuntime.StringClass
273:                            || to == ScriptRuntime.ObjectClass) {
274:                        return 1;
275:                    }
276:                    break;
277:
278:                case JSTYPE_NULL:
279:                    if (!to.isPrimitive()) {
280:                        return 1;
281:                    }
282:                    break;
283:
284:                case JSTYPE_BOOLEAN:
285:                    // "boolean" is #1
286:                    if (to == Boolean.TYPE) {
287:                        return 1;
288:                    } else if (to == ScriptRuntime.BooleanClass) {
289:                        return 2;
290:                    } else if (to == ScriptRuntime.ObjectClass) {
291:                        return 3;
292:                    } else if (to == ScriptRuntime.StringClass) {
293:                        return 4;
294:                    }
295:                    break;
296:
297:                case JSTYPE_NUMBER:
298:                    if (to.isPrimitive()) {
299:                        if (to == Double.TYPE) {
300:                            return 1;
301:                        } else if (to != Boolean.TYPE) {
302:                            return 1 + getSizeRank(to);
303:                        }
304:                    } else {
305:                        if (to == ScriptRuntime.StringClass) {
306:                            // native numbers are #1-8
307:                            return 9;
308:                        } else if (to == ScriptRuntime.ObjectClass) {
309:                            return 10;
310:                        } else if (ScriptRuntime.NumberClass
311:                                .isAssignableFrom(to)) {
312:                            // "double" is #1
313:                            return 2;
314:                        }
315:                    }
316:                    break;
317:
318:                case JSTYPE_STRING:
319:                    if (to == ScriptRuntime.StringClass) {
320:                        return 1;
321:                    } else if (to.isInstance(fromObj)) {
322:                        return 2;
323:                    } else if (to.isPrimitive()) {
324:                        if (to == Character.TYPE) {
325:                            return 3;
326:                        } else if (to != Boolean.TYPE) {
327:                            return 4;
328:                        }
329:                    }
330:                    break;
331:
332:                case JSTYPE_JAVA_CLASS:
333:                    if (to == ScriptRuntime.ClassClass) {
334:                        return 1;
335:                    } else if (to == ScriptRuntime.ObjectClass) {
336:                        return 3;
337:                    } else if (to == ScriptRuntime.StringClass) {
338:                        return 4;
339:                    }
340:                    break;
341:
342:                case JSTYPE_JAVA_OBJECT:
343:                case JSTYPE_JAVA_ARRAY:
344:                    Object javaObj = fromObj;
345:                    if (javaObj instanceof  Wrapper) {
346:                        javaObj = ((Wrapper) javaObj).unwrap();
347:                    }
348:                    if (to.isInstance(javaObj)) {
349:                        return CONVERSION_NONTRIVIAL;
350:                    }
351:                    if (to == ScriptRuntime.StringClass) {
352:                        return 2;
353:                    } else if (to.isPrimitive() && to != Boolean.TYPE) {
354:                        return (fromCode == JSTYPE_JAVA_ARRAY) ? CONVERSION_NONE
355:                                : 2 + getSizeRank(to);
356:                    }
357:                    break;
358:
359:                case JSTYPE_OBJECT:
360:                    // Other objects takes #1-#3 spots
361:                    if (to == fromObj.getClass()) {
362:                        // No conversion required
363:                        return 1;
364:                    }
365:                    if (to.isArray()) {
366:                        if (fromObj instanceof  NativeArray) {
367:                            // This is a native array conversion to a java array
368:                            // Array conversions are all equal, and preferable to object
369:                            // and string conversion, per LC3.
370:                            return 1;
371:                        }
372:                    } else if (to == ScriptRuntime.ObjectClass) {
373:                        return 2;
374:                    } else if (to == ScriptRuntime.StringClass) {
375:                        return 3;
376:                    } else if (to == ScriptRuntime.DateClass) {
377:                        if (fromObj instanceof  NativeDate) {
378:                            // This is a native date to java date conversion
379:                            return 1;
380:                        }
381:                    } else if (to.isInterface()) {
382:                        if (fromObj instanceof  Function) {
383:                            // See comments in coerceType
384:                            if (to.getMethods().length == 1) {
385:                                return 1;
386:                            }
387:                        }
388:                        return 11;
389:                    } else if (to.isPrimitive() && to != Boolean.TYPE) {
390:                        return 3 + getSizeRank(to);
391:                    }
392:                    break;
393:                }
394:
395:                return CONVERSION_NONE;
396:            }
397:
398:            static int getSizeRank(Class aType) {
399:                if (aType == Double.TYPE) {
400:                    return 1;
401:                } else if (aType == Float.TYPE) {
402:                    return 2;
403:                } else if (aType == Long.TYPE) {
404:                    return 3;
405:                } else if (aType == Integer.TYPE) {
406:                    return 4;
407:                } else if (aType == Short.TYPE) {
408:                    return 5;
409:                } else if (aType == Character.TYPE) {
410:                    return 6;
411:                } else if (aType == Byte.TYPE) {
412:                    return 7;
413:                } else if (aType == Boolean.TYPE) {
414:                    return CONVERSION_NONE;
415:                } else {
416:                    return 8;
417:                }
418:            }
419:
420:            private static int getJSTypeCode(Object value) {
421:                if (value == null) {
422:                    return JSTYPE_NULL;
423:                } else if (value == Undefined.instance) {
424:                    return JSTYPE_UNDEFINED;
425:                } else if (value instanceof  String) {
426:                    return JSTYPE_STRING;
427:                } else if (value instanceof  Number) {
428:                    return JSTYPE_NUMBER;
429:                } else if (value instanceof  Boolean) {
430:                    return JSTYPE_BOOLEAN;
431:                } else if (value instanceof  Scriptable) {
432:                    if (value instanceof  NativeJavaClass) {
433:                        return JSTYPE_JAVA_CLASS;
434:                    } else if (value instanceof  NativeJavaArray) {
435:                        return JSTYPE_JAVA_ARRAY;
436:                    } else if (value instanceof  Wrapper) {
437:                        return JSTYPE_JAVA_OBJECT;
438:                    } else {
439:                        return JSTYPE_OBJECT;
440:                    }
441:                } else if (value instanceof  Class) {
442:                    return JSTYPE_JAVA_CLASS;
443:                } else {
444:                    Class valueClass = value.getClass();
445:                    if (valueClass.isArray()) {
446:                        return JSTYPE_JAVA_ARRAY;
447:                    } else {
448:                        return JSTYPE_JAVA_OBJECT;
449:                    }
450:                }
451:            }
452:
453:            /**
454:             * Not intended for public use. Callers should use the
455:             * public API Context.toType.
456:             * @deprecated as of 1.5 Release 4
457:             * @see org.mozilla.javascript.Context#jsToJava(Object, Class)
458:             */
459:            public static Object coerceType(Class type, Object value) {
460:                return coerceTypeImpl(type, value);
461:            }
462:
463:            /**
464:             * Type-munging for field setting and method invocation.
465:             * Conforms to LC3 specification
466:             */
467:            static Object coerceTypeImpl(Class type, Object value) {
468:                if (value != null && value.getClass() == type) {
469:                    return value;
470:                }
471:
472:                switch (getJSTypeCode(value)) {
473:
474:                case JSTYPE_NULL:
475:                    // raise error if type.isPrimitive()
476:                    if (type.isPrimitive()) {
477:                        reportConversionError(value, type);
478:                    }
479:                    return null;
480:
481:                case JSTYPE_UNDEFINED:
482:                    if (type == ScriptRuntime.StringClass
483:                            || type == ScriptRuntime.ObjectClass) {
484:                        return "undefined";
485:                    } else {
486:                        reportConversionError("undefined", type);
487:                    }
488:                    break;
489:
490:                case JSTYPE_BOOLEAN:
491:                    // Under LC3, only JS Booleans can be coerced into a Boolean value
492:                    if (type == Boolean.TYPE
493:                            || type == ScriptRuntime.BooleanClass
494:                            || type == ScriptRuntime.ObjectClass) {
495:                        return value;
496:                    } else if (type == ScriptRuntime.StringClass) {
497:                        return value.toString();
498:                    } else {
499:                        reportConversionError(value, type);
500:                    }
501:                    break;
502:
503:                case JSTYPE_NUMBER:
504:                    if (type == ScriptRuntime.StringClass) {
505:                        return ScriptRuntime.toString(value);
506:                    } else if (type == ScriptRuntime.ObjectClass) {
507:                        return coerceToNumber(Double.TYPE, value);
508:                    } else if ((type.isPrimitive() && type != Boolean.TYPE)
509:                            || ScriptRuntime.NumberClass.isAssignableFrom(type)) {
510:                        return coerceToNumber(type, value);
511:                    } else {
512:                        reportConversionError(value, type);
513:                    }
514:                    break;
515:
516:                case JSTYPE_STRING:
517:                    if (type == ScriptRuntime.StringClass
518:                            || type.isInstance(value)) {
519:                        return value;
520:                    } else if (type == Character.TYPE
521:                            || type == ScriptRuntime.CharacterClass) {
522:                        // Special case for converting a single char string to a
523:                        // character
524:                        // Placed here because it applies *only* to JS strings,
525:                        // not other JS objects converted to strings
526:                        if (((String) value).length() == 1) {
527:                            return new Character(((String) value).charAt(0));
528:                        } else {
529:                            return coerceToNumber(type, value);
530:                        }
531:                    } else if ((type.isPrimitive() && type != Boolean.TYPE)
532:                            || ScriptRuntime.NumberClass.isAssignableFrom(type)) {
533:                        return coerceToNumber(type, value);
534:                    } else {
535:                        reportConversionError(value, type);
536:                    }
537:                    break;
538:
539:                case JSTYPE_JAVA_CLASS:
540:                    if (value instanceof  Wrapper) {
541:                        value = ((Wrapper) value).unwrap();
542:                    }
543:
544:                    if (type == ScriptRuntime.ClassClass
545:                            || type == ScriptRuntime.ObjectClass) {
546:                        return value;
547:                    } else if (type == ScriptRuntime.StringClass) {
548:                        return value.toString();
549:                    } else {
550:                        reportConversionError(value, type);
551:                    }
552:                    break;
553:
554:                case JSTYPE_JAVA_OBJECT:
555:                case JSTYPE_JAVA_ARRAY:
556:                    if (value instanceof  Wrapper) {
557:                        value = ((Wrapper) value).unwrap();
558:                    }
559:                    if (type.isPrimitive()) {
560:                        if (type == Boolean.TYPE) {
561:                            reportConversionError(value, type);
562:                        }
563:                        return coerceToNumber(type, value);
564:                    } else {
565:                        if (type == ScriptRuntime.StringClass) {
566:                            return value.toString();
567:                        } else {
568:                            if (type.isInstance(value)) {
569:                                return value;
570:                            } else {
571:                                reportConversionError(value, type);
572:                            }
573:                        }
574:                    }
575:                    break;
576:
577:                case JSTYPE_OBJECT:
578:                    if (type == ScriptRuntime.StringClass) {
579:                        return ScriptRuntime.toString(value);
580:                    } else if (type.isPrimitive()) {
581:                        if (type == Boolean.TYPE) {
582:                            reportConversionError(value, type);
583:                        }
584:                        return coerceToNumber(type, value);
585:                    } else if (type.isInstance(value)) {
586:                        return value;
587:                    } else if (type == ScriptRuntime.DateClass
588:                            && value instanceof  NativeDate) {
589:                        double time = ((NativeDate) value).getJSTimeValue();
590:                        // XXX: This will replace NaN by 0
591:                        return new Date((long) time);
592:                    } else if (type.isArray() && value instanceof  NativeArray) {
593:                        // Make a new java array, and coerce the JS array components
594:                        // to the target (component) type.
595:                        NativeArray array = (NativeArray) value;
596:                        long length = array.getLength();
597:                        Class arrayType = type.getComponentType();
598:                        Object Result = Array.newInstance(arrayType,
599:                                (int) length);
600:                        for (int i = 0; i < length; ++i) {
601:                            try {
602:                                Array.set(Result, i, coerceType(arrayType,
603:                                        array.get(i, array)));
604:                            } catch (EvaluatorException ee) {
605:                                reportConversionError(value, type);
606:                            }
607:                        }
608:
609:                        return Result;
610:                    } else if (value instanceof  Wrapper) {
611:                        value = ((Wrapper) value).unwrap();
612:                        if (type.isInstance(value))
613:                            return value;
614:                        reportConversionError(value, type);
615:                    } else if (type.isInterface() && value instanceof  Callable) {
616:                        // Try to use function as implementation of Java interface.
617:                        //
618:                        // XXX: Curently only instances of ScriptableObject are
619:                        // supported since the resulting interface proxies should
620:                        // be reused next time conversion is made and generic
621:                        // Callable has no storage for it. Weak references can
622:                        // address it but for now use this restriction.
623:                        if (value instanceof  ScriptableObject) {
624:                            ScriptableObject so = (ScriptableObject) value;
625:                            Object key = Kit.makeHashKeyFromPair(
626:                                    COERCED_INTERFACE_KEY, type);
627:                            Object old = so.getAssociatedValue(key);
628:                            if (old != null) {
629:                                // Function was already wrapped
630:                                return old;
631:                            }
632:                            Context cx = Context.getContext();
633:                            Object glue = InterfaceAdapter.create(cx, type,
634:                                    (Callable) value);
635:                            // Store for later retrival
636:                            glue = so.associateValue(key, glue);
637:                            return glue;
638:                        }
639:                        reportConversionError(value, type);
640:                    } else {
641:                        reportConversionError(value, type);
642:                    }
643:                    break;
644:                }
645:
646:                return value;
647:            }
648:
649:            private static Object coerceToNumber(Class type, Object value) {
650:                Class valueClass = value.getClass();
651:
652:                // Character
653:                if (type == Character.TYPE
654:                        || type == ScriptRuntime.CharacterClass) {
655:                    if (valueClass == ScriptRuntime.CharacterClass) {
656:                        return value;
657:                    }
658:                    return new Character((char) toInteger(value,
659:                            ScriptRuntime.CharacterClass, Character.MIN_VALUE,
660:                            Character.MAX_VALUE));
661:                }
662:
663:                // Double, Float
664:                if (type == ScriptRuntime.ObjectClass
665:                        || type == ScriptRuntime.DoubleClass
666:                        || type == Double.TYPE) {
667:                    return valueClass == ScriptRuntime.DoubleClass ? value
668:                            : new Double(toDouble(value));
669:                }
670:
671:                if (type == ScriptRuntime.FloatClass || type == Float.TYPE) {
672:                    if (valueClass == ScriptRuntime.FloatClass) {
673:                        return value;
674:                    } else {
675:                        double number = toDouble(value);
676:                        if (Double.isInfinite(number) || Double.isNaN(number)
677:                                || number == 0.0) {
678:                            return new Float((float) number);
679:                        } else {
680:                            double absNumber = Math.abs(number);
681:                            if (absNumber < Float.MIN_VALUE) {
682:                                return new Float((number > 0.0) ? +0.0 : -0.0);
683:                            } else if (absNumber > Float.MAX_VALUE) {
684:                                return new Float(
685:                                        (number > 0.0) ? Float.POSITIVE_INFINITY
686:                                                : Float.NEGATIVE_INFINITY);
687:                            } else {
688:                                return new Float((float) number);
689:                            }
690:                        }
691:                    }
692:                }
693:
694:                // Integer, Long, Short, Byte
695:                if (type == ScriptRuntime.IntegerClass || type == Integer.TYPE) {
696:                    if (valueClass == ScriptRuntime.IntegerClass) {
697:                        return value;
698:                    } else {
699:                        return new Integer((int) toInteger(value,
700:                                ScriptRuntime.IntegerClass, Integer.MIN_VALUE,
701:                                Integer.MAX_VALUE));
702:                    }
703:                }
704:
705:                if (type == ScriptRuntime.LongClass || type == Long.TYPE) {
706:                    if (valueClass == ScriptRuntime.LongClass) {
707:                        return value;
708:                    } else {
709:                        /* Long values cannot be expressed exactly in doubles.
710:                         * We thus use the largest and smallest double value that
711:                         * has a value expressible as a long value. We build these
712:                         * numerical values from their hexidecimal representations
713:                         * to avoid any problems caused by attempting to parse a
714:                         * decimal representation.
715:                         */
716:                        final double max = Double
717:                                .longBitsToDouble(0x43dfffffffffffffL);
718:                        final double min = Double
719:                                .longBitsToDouble(0xc3e0000000000000L);
720:                        return new Long(toInteger(value,
721:                                ScriptRuntime.LongClass, min, max));
722:                    }
723:                }
724:
725:                if (type == ScriptRuntime.ShortClass || type == Short.TYPE) {
726:                    if (valueClass == ScriptRuntime.ShortClass) {
727:                        return value;
728:                    } else {
729:                        return new Short((short) toInteger(value,
730:                                ScriptRuntime.ShortClass, Short.MIN_VALUE,
731:                                Short.MAX_VALUE));
732:                    }
733:                }
734:
735:                if (type == ScriptRuntime.ByteClass || type == Byte.TYPE) {
736:                    if (valueClass == ScriptRuntime.ByteClass) {
737:                        return value;
738:                    } else {
739:                        return new Byte((byte) toInteger(value,
740:                                ScriptRuntime.ByteClass, Byte.MIN_VALUE,
741:                                Byte.MAX_VALUE));
742:                    }
743:                }
744:
745:                return new Double(toDouble(value));
746:            }
747:
748:            private static double toDouble(Object value) {
749:                if (value instanceof  Number) {
750:                    return ((Number) value).doubleValue();
751:                } else if (value instanceof  String) {
752:                    return ScriptRuntime.toNumber((String) value);
753:                } else if (value instanceof  Scriptable) {
754:                    if (value instanceof  Wrapper) {
755:                        // XXX: optimize tail-recursion?
756:                        return toDouble(((Wrapper) value).unwrap());
757:                    } else {
758:                        return ScriptRuntime.toNumber(value);
759:                    }
760:                } else {
761:                    Method meth;
762:                    try {
763:                        meth = value.getClass().getMethod("doubleValue",
764:                                (Class[]) null);
765:                    } catch (NoSuchMethodException e) {
766:                        meth = null;
767:                    } catch (SecurityException e) {
768:                        meth = null;
769:                    }
770:                    if (meth != null) {
771:                        try {
772:                            return ((Number) meth
773:                                    .invoke(value, (Object[]) null))
774:                                    .doubleValue();
775:                        } catch (IllegalAccessException e) {
776:                            // XXX: ignore, or error message?
777:                            reportConversionError(value, Double.TYPE);
778:                        } catch (InvocationTargetException e) {
779:                            // XXX: ignore, or error message?
780:                            reportConversionError(value, Double.TYPE);
781:                        }
782:                    }
783:                    return ScriptRuntime.toNumber(value.toString());
784:                }
785:            }
786:
787:            private static long toInteger(Object value, Class type, double min,
788:                    double max) {
789:                double d = toDouble(value);
790:
791:                if (Double.isInfinite(d) || Double.isNaN(d)) {
792:                    // Convert to string first, for more readable message
793:                    reportConversionError(ScriptRuntime.toString(value), type);
794:                }
795:
796:                if (d > 0.0) {
797:                    d = Math.floor(d);
798:                } else {
799:                    d = Math.ceil(d);
800:                }
801:
802:                if (d < min || d > max) {
803:                    // Convert to string first, for more readable message
804:                    reportConversionError(ScriptRuntime.toString(value), type);
805:                }
806:                return (long) d;
807:            }
808:
809:            static void reportConversionError(Object value, Class type) {
810:                // It uses String.valueOf(value), not value.toString() since
811:                // value can be null, bug 282447.
812:                throw Context.reportRuntimeError2("msg.conversion.not.allowed",
813:                        String.valueOf(value), JavaMembers.javaSignature(type));
814:            }
815:
816:            private void writeObject(ObjectOutputStream out) throws IOException {
817:                out.defaultWriteObject();
818:
819:                out.writeBoolean(isAdapter);
820:                if (isAdapter) {
821:                    if (adapter_writeAdapterObject == null) {
822:                        throw new IOException();
823:                    }
824:                    Object[] args = { javaObject, out };
825:                    try {
826:                        adapter_writeAdapterObject.invoke(null, args);
827:                    } catch (Exception ex) {
828:                        throw new IOException();
829:                    }
830:                } else {
831:                    out.writeObject(javaObject);
832:                }
833:
834:                if (staticType != null) {
835:                    out.writeObject(staticType.getClass().getName());
836:                } else {
837:                    out.writeObject(null);
838:                }
839:            }
840:
841:            private void readObject(ObjectInputStream in) throws IOException,
842:                    ClassNotFoundException {
843:                in.defaultReadObject();
844:
845:                isAdapter = in.readBoolean();
846:                if (isAdapter) {
847:                    if (adapter_readAdapterObject == null)
848:                        throw new ClassNotFoundException();
849:                    Object[] args = { this , in };
850:                    try {
851:                        javaObject = adapter_readAdapterObject.invoke(null,
852:                                args);
853:                    } catch (Exception ex) {
854:                        throw new IOException();
855:                    }
856:                } else {
857:                    javaObject = in.readObject();
858:                }
859:
860:                String className = (String) in.readObject();
861:                if (className != null) {
862:                    staticType = Class.forName(className);
863:                } else {
864:                    staticType = null;
865:                }
866:
867:                initMembers();
868:            }
869:
870:            /**
871:             * The prototype of this object.
872:             */
873:            protected Scriptable prototype;
874:
875:            /**
876:             * The parent scope of this object.
877:             */
878:            protected Scriptable parent;
879:
880:            protected transient Object javaObject;
881:
882:            protected transient Class staticType;
883:            protected transient JavaMembers members;
884:            private transient Hashtable fieldAndMethods;
885:            private transient boolean isAdapter;
886:
887:            private static final Object COERCED_INTERFACE_KEY = new Object();
888:            private static Method adapter_writeAdapterObject;
889:            private static Method adapter_readAdapterObject;
890:
891:            static {
892:                // Reflection in java is verbose
893:                Class[] sig2 = new Class[2];
894:                Class cl = Kit
895:                        .classOrNull("org.mozilla.javascript.JavaAdapter");
896:                if (cl != null) {
897:                    try {
898:                        sig2[0] = ScriptRuntime.ObjectClass;
899:                        sig2[1] = Kit.classOrNull("java.io.ObjectOutputStream");
900:                        adapter_writeAdapterObject = cl.getMethod(
901:                                "writeAdapterObject", sig2);
902:
903:                        sig2[0] = ScriptRuntime.ScriptableClass;
904:                        sig2[1] = Kit.classOrNull("java.io.ObjectInputStream");
905:                        adapter_readAdapterObject = cl.getMethod(
906:                                "readAdapterObject", sig2);
907:
908:                    } catch (Exception ex) {
909:                        adapter_writeAdapterObject = null;
910:                        adapter_readAdapterObject = null;
911:                    }
912:                }
913:            }
914:
915:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.