KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > lobobrowser > js > JavaFunctionObject


1 /*
2     GNU LESSER GENERAL PUBLIC LICENSE
3     Copyright (C) 2006 The Lobo Project
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19     Contact info: xamjadmin@users.sourceforge.net
20 */

21 package org.lobobrowser.js;
22
23 import org.mozilla.javascript.*;
24 import java.lang.reflect.*;
25 import java.util.logging.*;
26 import java.util.*;
27 import org.lobobrowser.util.*;
28
29 public class JavaFunctionObject extends ScriptableObject implements Function {
30     private static final Logger logger = Logger.getLogger(JavaFunctionObject.class.getName());
31     private static final boolean loggableInfo = logger.isLoggable(Level.INFO);
32     private final String JavaDoc className;
33     private final ArrayList methods = new ArrayList();
34         
35     public JavaFunctionObject(String JavaDoc name) {
36         super();
37         this.className = name;
38     }
39
40     public void addMethod(Method m) {
41         this.methods.add(m);
42     }
43     
44     public String JavaDoc getClassName() {
45         return this.className;
46     }
47     
48     private String JavaDoc getTypeName(Object JavaDoc object) {
49         return object == null ? "[null]" : object.getClass().getName();
50     }
51
52     private Method getBestMethod(Object JavaDoc[] args) {
53         ArrayList methods = this.methods;
54         int size = methods.size();
55         int matchingNumParams = 0;
56         Method matchingMethod = null;
57         for(int i = 0; i < size; i++) {
58             Method m = (Method) methods.get(i);
59             Class JavaDoc[] parameterTypes = m.getParameterTypes();
60             if(args == null) {
61                 if(parameterTypes == null || parameterTypes.length == 0) {
62                     return m;
63                 }
64             }
65             else if(parameterTypes != null && args.length >= parameterTypes.length) {
66                 if(Objects.areAssignableTo(args, parameterTypes)) {
67                     return m;
68                 }
69                 if(matchingMethod == null || parameterTypes.length > matchingNumParams) {
70                     matchingNumParams = parameterTypes.length;
71                     matchingMethod = m;
72                 }
73             }
74         }
75         if(size == 0) {
76             throw new IllegalStateException JavaDoc("zero methods");
77         }
78         return matchingMethod;
79     }
80     
81     public Object JavaDoc call(Context cx, Scriptable scope, Scriptable thisObj,
82             Object JavaDoc[] args) {
83         JavaObjectWrapper jcw = (JavaObjectWrapper) thisObj;
84         Method method = this.getBestMethod(args);
85         if(method == null) {
86             throw new EvaluatorException("No method matching " + this.className + " with " + (args == null ? 0 : args.length) + " arguments.");
87         }
88         Class JavaDoc[] actualArgTypes = method.getParameterTypes();
89         int numParams = actualArgTypes.length;
90         Object JavaDoc[] actualArgs = args == null ? new Object JavaDoc[0] : new Object JavaDoc[numParams];
91         boolean linfo = loggableInfo;
92         if(linfo) {
93             Object JavaDoc javaObject = jcw.getJavaObject();
94             logger.info("call(): Calling method " + method.getName() + " on object " + javaObject + " of type " + this.getTypeName(javaObject));
95         }
96         JavaScript manager = JavaScript.getInstance();
97         for(int i = 0; i < numParams; i++) {
98             Object JavaDoc arg = args[i];
99             Object JavaDoc actualArg = manager.getJavaObject(arg, actualArgTypes[i]);
100             if(linfo) {
101                 logger.info("call(): For method=" + method.getName() + ": Converted arg=" + arg + " (type=" + this.getTypeName(arg) + ") into actualArg=" + actualArg + ". Type expected by method is " + actualArgTypes[i].getName() + ".");
102             }
103             actualArgs[i] = actualArg;
104         }
105         try {
106             Object JavaDoc raw = method.invoke(jcw.getJavaObject(), actualArgs);
107             return manager.getJavascriptObject(raw, scope);
108         } catch(IllegalAccessException JavaDoc iae) {
109             throw new IllegalStateException JavaDoc("Unable to call " + this.className + ".", iae);
110         } catch(InvocationTargetException ite) {
111             throw new WrappedException(new InvocationTargetException(ite.getCause(), "Unable to call " + this.className + " on " + jcw.getJavaObject() + "."));
112         } catch(IllegalArgumentException JavaDoc iae) {
113             StringBuffer JavaDoc argTypes = new StringBuffer JavaDoc();
114             for(int i = 0; i < actualArgs.length; i++) {
115                 if(i > 0) {
116                     argTypes.append(", ");
117                 }
118                 argTypes.append(actualArgs[i] == null ? "<null>" : actualArgs[i].getClass().getName());
119             }
120             throw new WrappedException(new IllegalArgumentException JavaDoc("Unable to call " + this.className + ". Argument types: " + argTypes + ".", iae));
121         }
122     }
123     
124     public java.lang.Object JavaDoc getDefaultValue(java.lang.Class JavaDoc hint) {
125         if(loggableInfo) {
126             logger.info("getDefaultValue(): hint=" + hint + ",this=" + this);
127         }
128         if(hint == null || String JavaDoc.class.equals(hint)) {
129             return "function " + this.className;
130         }
131         else {
132             return super.getDefaultValue(hint);
133         }
134     }
135     
136     public Scriptable construct(Context cx, Scriptable scope, Object JavaDoc[] args) {
137         throw new UnsupportedOperationException JavaDoc();
138     }
139 }
140
Popular Tags