Coverage Report - com.sun.tools.javafx.script.JavaFXScriptEngineImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
JavaFXScriptEngineImpl
76%
202/265
60%
72/120
0
JavaFXScriptEngineImpl$1
100%
5/5
100%
2/2
0
JavaFXScriptEngineImpl$2
0%
0/4
0%
0/2
0
JavaFXScriptEngineImpl$JavafxScriptCompiledScript
83%
5/6
N/A
0
 
 1  
 /*
 2  
  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
 3  
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  
  *
 5  
  * This code is free software; you can redistribute it and/or modify it
 6  
  * under the terms of the GNU General Public License version 2 only, as
 7  
  * published by the Free Software Foundation.  Sun designates this
 8  
  * particular file as subject to the "Classpath" exception as provided
 9  
  * by Sun in the LICENSE file that accompanied this code.
 10  
  *
 11  
  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  
  * version 2 for more details (a copy is included in the LICENSE file that
 15  
  * accompanied this code).
 16  
  *
 17  
  * You should have received a copy of the GNU General Public License version
 18  
  * 2 along with this work; if not, write to the Free Software Foundation,
 19  
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  
  *
 21  
  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 22  
  * CA 95054 USA or visit www.sun.com if you need additional information or
 23  
  * have any questions.
 24  
  */
 25  
 
 26  
 package com.sun.tools.javafx.script;
 27  
 
 28  
 import com.sun.javafx.api.JavaFXScriptEngine;
 29  
 import com.sun.javafx.api.JavafxcTask;
 30  
 import com.sun.javafx.runtime.Entry;
 31  
 import com.sun.tools.javac.util.JCDiagnostic;
 32  
 import java.io.*;
 33  
 import java.lang.reflect.*;
 34  
 import java.util.*;
 35  
 import javax.script.*;
 36  
 import javax.tools.Diagnostic;
 37  
 import javax.tools.DiagnosticCollector;
 38  
 import javax.tools.DiagnosticListener;
 39  
 import javax.tools.JavaFileObject;
 40  
 import com.sun.javafx.runtime.sequence.Sequence;
 41  
 import com.sun.javafx.runtime.sequence.Sequences;
 42  
 import com.sun.source.tree.CompilationUnitTree;
 43  
 import com.sun.source.tree.ExpressionTree;
 44  
 import com.sun.source.util.SourcePositions;
 45  
 import com.sun.tools.javac.tree.JCTree;
 46  
 import com.sun.tools.javafx.api.JavafxcTool;
 47  
 import com.sun.tools.javafx.api.JavafxcTrees;
 48  
 import java.net.MalformedURLException;
 49  
 import java.net.URL;
 50  
 
 51  
 /**
 52  
  * This is script engine for the JavaFX Script language, based on
 53  
  * the https://scripting.dev.java.net Java language script engine by
 54  
  * A. Sundararajan.
 55  
  */
 56  8
 public class JavaFXScriptEngineImpl extends AbstractScriptEngine
 57  
         implements JavaFXScriptEngine {
 58  
 
 59  
     private static final String SCRIPT_CONTEXT_NAME = "javafx$ctx";
 60  
     
 61  
     // Java compiler
 62  
     private JavaFXScriptCompiler compiler;
 63  
 
 64  
     // Scripts parsed by this engine
 65  26
     private LinkedList<Class> scripts = new LinkedList<Class>();
 66  
 
 67  26
     public JavaFXScriptEngineImpl() {
 68  26
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
 69  26
         if (cl != null) {
 70  26
             parentClassLoader = cl;
 71  
         }
 72  26
         compiler = new JavaFXScriptCompiler(parentClassLoader);
 73  26
     }
 74  
 
 75  
     // my factory, may be null
 76  
     private ScriptEngineFactory factory;
 77  
 
 78  
     private DiagnosticCollector<JavaFileObject> diagnostics;
 79  
     
 80  26
     private ClassLoader parentClassLoader = getClass().getClassLoader();
 81  
 
 82  
     public List<Diagnostic<? extends JavaFileObject>> getLastDiagnostics() {
 83  0
         return diagnostics == null ? null : diagnostics.getDiagnostics();
 84  
     }
 85  
 
 86  
     // my implementation for CompiledScript
 87  
     private class JavafxScriptCompiledScript extends CompiledScript {
 88  
         private Class clazz;
 89  
 
 90  4
         JavafxScriptCompiledScript(Class clazz) {
 91  4
             this.clazz = clazz;
 92  4
         }
 93  
 
 94  
         public ScriptEngine getEngine() {
 95  1
             return JavaFXScriptEngineImpl.this;
 96  
         }
 97  
 
 98  
         public Object eval(ScriptContext ctx) throws ScriptException {
 99  1
             return evalClass(clazz, ctx);
 100  
         }
 101  
 
 102  
         public String getName() {
 103  0
             return clazz.getName();
 104  
         }
 105  
     }
 106  
 
 107  
     public CompiledScript compile(String script) throws ScriptException {
 108  4
         return compile(script, null);
 109  
     }
 110  
 
 111  
     public CompiledScript compile(Reader reader) throws ScriptException {
 112  0
         return compile(readFully(reader));
 113  
     }
 114  
 
 115  
     public CompiledScript compile(String script, DiagnosticListener<JavaFileObject> listener)
 116  
             throws ScriptException {
 117  4
         Class clazz = parse(script, context, listener, true);
 118  4
         scripts.addFirst(clazz);  // most recent scripts get referenced first
 119  4
         return new JavafxScriptCompiledScript(clazz);
 120  
     }
 121  
 
 122  
     public CompiledScript compile(Reader script, DiagnosticListener<JavaFileObject> listener)
 123  
             throws ScriptException {
 124  0
         return compile(readFully(script), listener);
 125  
     }
 126  
     
 127  
     public Object eval(String script, DiagnosticListener<JavaFileObject> listener) 
 128  
             throws ScriptException {
 129  1
         return eval(script, getContext(), listener);
 130  
     }
 131  
 
 132  
     public Object eval(Reader script, DiagnosticListener<JavaFileObject> listener) throws ScriptException {
 133  0
         return eval(script, getContext(), listener);
 134  
     }
 135  
 
 136  
     public Object eval(String str, ScriptContext ctx)
 137  
             throws ScriptException {
 138  15
         return eval(str, ctx, null);
 139  
     }
 140  
 
 141  
     public Object eval(Reader reader, ScriptContext ctx)
 142  
             throws ScriptException {
 143  2
         return eval(readFully(reader), ctx);
 144  
     }
 145  
 
 146  
     public Object eval(String script, ScriptContext context, DiagnosticListener<JavaFileObject> listener) throws ScriptException {
 147  17
         Class clazz = parse(script, context, listener, false);
 148  14
         scripts.addFirst(clazz);  // most recent scripts get referenced first
 149  14
         return evalClass(clazz, context);
 150  
     }
 151  
 
 152  
     public Object eval(Reader reader, ScriptContext context, DiagnosticListener<JavaFileObject> listener) throws ScriptException {
 153  0
         return eval(readFully(reader), context, listener);
 154  
     }
 155  
 
 156  
     public Object eval(String script, Bindings bindings, DiagnosticListener<JavaFileObject> listener) throws ScriptException {
 157  1
         ScriptContext ctx = getContext();
 158  1
         ctx.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
 159  1
         return eval(script, ctx, listener);
 160  
     }
 161  
 
 162  
     public Object eval(Reader reader, Bindings bindings, DiagnosticListener<JavaFileObject> listener) throws ScriptException {
 163  0
         ScriptContext ctx = getContext();
 164  0
         ctx.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
 165  0
         return eval(reader, ctx, listener);
 166  
     }
 167  
 
 168  
     public ScriptEngineFactory getFactory() {
 169  0
         if (factory == null) {
 170  0
             factory = new JavaFXScriptEngineFactory();
 171  
         }
 172  0
         return factory;
 173  
     }
 174  
 
 175  
     public Bindings createBindings() {
 176  0
         return new SimpleBindings();
 177  
     }
 178  
 
 179  
     void setFactory(ScriptEngineFactory factory) {
 180  26
         this.factory = factory;
 181  26
     }
 182  
 
 183  
     // Internals only below this point
 184  
 
 185  
     private Class parse(String str, ScriptContext ctx, 
 186  
             final DiagnosticListener<JavaFileObject> listener,
 187  
             boolean inferBindings) throws ScriptException {
 188  21
         String fileName = getFileName(ctx);
 189  21
         String sourcePath = getSourcePath(ctx);
 190  21
         String classPath = getClassPath(ctx);
 191  21
         String script = str;
 192  21
         diagnostics = new DiagnosticCollector<JavaFileObject>();
 193  
         DiagnosticListener<JavaFileObject> 
 194  21
             diagnosticListener = new DiagnosticListener<JavaFileObject>() {
 195  
             public void report(Diagnostic<? extends JavaFileObject> rep) {
 196  3
                 if (listener != null)
 197  2
                     listener.report(rep);
 198  3
                 diagnostics.report(rep);
 199  3
             }
 200  
         };
 201  21
         DiagnosticCollector<JavaFileObject> firstCollector = 
 202  
                 new DiagnosticCollector<JavaFileObject>();
 203  
 
 204  21
         Map<String, byte[]> classBytes = compiler.compile(fileName, script,
 205  
                 ctx.getErrorWriter(), sourcePath, classPath, firstCollector, false);
 206  
 
 207  21
         if (firstCollector.getDiagnostics().size() > 0) {
 208  
             // check for unresolved variables, add to context, and retry
 209  9
             boolean recompile = false;
 210  9
             Set<String> attrs = new HashSet<String>();
 211  9
             for (Diagnostic d : firstCollector.getDiagnostics()) {
 212  13
                 if (d.getCode().equals("compiler.err.cant.resolve.location")) {
 213  11
                     Object[] args = ((JCDiagnostic) d).getArgs();
 214  11
                     if (args.length >= 2 && args[1] instanceof String) {
 215  11
                         attrs.add((String) args[1]);
 216  11
                         recompile = true;
 217  
                     }
 218  13
                 }
 219  
             }
 220  9
             if (recompile) {
 221  8
                 String binding = makeBindingStatement(ctx, attrs, inferBindings);
 222  8
                 int bindingInsert = 0;  // insert binding in front of script
 223  
                 try {
 224  
                     // parse script to find any package statement
 225  8
                     JavafxcTool tool = JavafxcTool.create();
 226  8
                     MemoryFileManager manager = new MemoryFileManager(tool.getStandardFileManager(diagnostics, null, null), parentClassLoader);
 227  8
                     List<JavaFileObject> compUnits = new ArrayList<JavaFileObject>(1);
 228  8
                     compUnits.add(manager.makeStringSource(fileName, script));
 229  8
                     JavafxcTask task = tool.getTask(null, manager, diagnostics, null, compUnits);
 230  8
                     Iterable<? extends CompilationUnitTree> units = task.parse();
 231  8
                     if (units.iterator().hasNext()) {
 232  8
                         CompilationUnitTree unit = units.iterator().next();
 233  8
                         ExpressionTree pkg = unit.getPackageName();
 234  8
                         if (pkg != null) {
 235  
                             // insert bindings after package and before first unit member
 236  1
                             SourcePositions positions = JavafxcTrees.instance(task).getSourcePositions();
 237  1
                             JCTree firstDef = ((JCTree.JCCompilationUnit)unit).defs.head;
 238  1
                             bindingInsert = (int)positions.getStartPosition(unit, firstDef);
 239  
                         }
 240  
                     }
 241  0
                 } catch (IOException e) {
 242  
                     // should never happen with a MemoryFileManager file object
 243  0
                     throw new AssertionError(e);                            
 244  8
                 }
 245  8
                 script = str.substring(0, bindingInsert) + binding + str.substring(bindingInsert);
 246  8
                 classBytes = compiler.compile(fileName, script,
 247  
                         ctx.getErrorWriter(), sourcePath, classPath,
 248  
                         diagnosticListener, true);
 249  8
             } else {
 250  1
                 for (Diagnostic<? extends JavaFileObject> d : firstCollector.getDiagnostics())
 251  1
                     diagnosticListener.report(d);
 252  1
                 JavaFXScriptCompiler.printDiagnostics(diagnostics, ctx.getErrorWriter());
 253  
             }
 254  
         }
 255  
 
 256  21
         if (classBytes == null) {
 257  3
             throw new ScriptException("compilation failed");
 258  
         }
 259  18
         URL sourceURL = null;
 260  18
         if (fileName != null) try {
 261  18
             sourceURL = new File(fileName).toURI().toURL();
 262  18
         } catch (MalformedURLException mue) {}
 263  
 
 264  
         // create a ClassLoader to load classes from MemoryJavaFileManager
 265  18
         MemoryClassLoader loader = new MemoryClassLoader(sourceURL,
 266  
                 classBytes, classPath, parentClassLoader);
 267  
 
 268  
         Iterable<Class> classes;
 269  
         try {
 270  18
             classes = loader.loadAll();
 271  0
         } catch (ClassNotFoundException exp) {
 272  0
             throw new ScriptException(exp);
 273  18
         }
 274  
 
 275  
         // search for class with main method
 276  18
         Class c = findMainClass(classes);
 277  18
         if (c == null) {
 278  0
             throw new ScriptException("no main class found");
 279  
         }
 280  18
         return c;
 281  
     }
 282  
 
 283  
     private static Class findMainClass(Iterable<Class> classes) {
 284  
         // find a public class with public static main method
 285  18
         for (Class clazz : classes) {
 286  36
             int modifiers = clazz.getModifiers();
 287  36
             if (Modifier.isPublic(modifiers)) {
 288  36
                 Method mainMethod = findMainMethod(clazz);
 289  36
                 if (mainMethod != null) {
 290  18
                     return clazz;
 291  
                 }
 292  
             }
 293  18
         }
 294  
 
 295  
         // okay, try to find package private class that
 296  
         // has public static main method
 297  0
         for (Class clazz : classes) {
 298  0
             Method mainMethod = findMainMethod(clazz);
 299  0
             if (mainMethod != null) {
 300  0
                 return clazz;
 301  
             }
 302  0
         }
 303  
 
 304  
         // no main class found!
 305  0
         return null;
 306  
     }
 307  
 
 308  
     // find public static void main(String[]) method, if any
 309  
     private static Method findMainMethod(Class clazz) {
 310  
         try {
 311  51
             Method mainMethod = clazz.getMethod(Entry.entryMethodName(), Sequence.class);
 312  33
             int modifiers = mainMethod.getModifiers();
 313  33
             if (Modifier.isPublic(modifiers) &&
 314  
                     Modifier.isStatic(modifiers)) {
 315  33
                 return mainMethod;
 316  
             }
 317  18
         } catch (NoSuchMethodException nsme) {
 318  18
             assert false : nsme;
 319  0
         }
 320  18
         return null;
 321  
     }
 322  
     
 323  
     private static String getFileName(ScriptContext ctx) {
 324  21
         int scope = ctx.getAttributesScope(ScriptEngine.FILENAME);
 325  21
         if (scope != -1) {
 326  1
             return ctx.getAttribute(ScriptEngine.FILENAME, scope).toString();
 327  
         } else {
 328  20
             return "___FX_SCRIPT___.fx";
 329  
         }
 330  
     }
 331  
 
 332  
     private static String getScriptKey(ScriptContext ctx) {
 333  23
         return "script-context";
 334  
     }
 335  
 
 336  
     // for certain variables, we look for System properties. This is
 337  
     // the prefix used for such System properties
 338  
     private static final String SYSPROP_PREFIX = "com.sun.tools.javafx.script.";
 339  
 
 340  
     private static final String SOURCEPATH = "sourcepath";
 341  
     private static String getSourcePath(ScriptContext ctx) {
 342  21
         int scope = ctx.getAttributesScope(SOURCEPATH);
 343  21
         if (scope != -1) {
 344  0
             return ctx.getAttribute(SOURCEPATH).toString();
 345  
         } else {
 346  
             // look for "com.sun.tools.javafx.script.sourcepath"
 347  21
             return System.getProperty(SYSPROP_PREFIX + SOURCEPATH);
 348  
         }
 349  
     }
 350  
 
 351  
     private static final String CLASSPATH = "classpath";
 352  
     private static String getClassPath(ScriptContext ctx) {
 353  21
         int scope = ctx.getAttributesScope(CLASSPATH);
 354  21
         if (scope != -1) {
 355  0
             return ctx.getAttribute(CLASSPATH).toString();
 356  
         } else {
 357  
             // look for "com.sun.tools.javafx.script.classpath"
 358  21
             String res = System.getProperty(SYSPROP_PREFIX + CLASSPATH);
 359  21
             if (res == null) {
 360  21
                 res = System.getProperty("java.class.path");
 361  
             }
 362  21
             return res;
 363  
         }
 364  
     }
 365  
 
 366  
     private static Object evalClass(Class clazz, ScriptContext ctx)
 367  
             throws ScriptException {
 368  
         // JSR-223 requirement
 369  15
         ctx.setAttribute("context", ctx, ScriptContext.ENGINE_SCOPE);
 370  15
         if (clazz == null) {
 371  0
             return null;
 372  
         }
 373  15
         String scriptKey = getScriptKey(ctx);
 374  
         try {
 375  15
             ScriptContextManager.putContext(scriptKey, ctx);
 376  15
             Object result = null;
 377  
 
 378  
             // find the main method
 379  15
             Method mainMethod = findMainMethod(clazz);
 380  15
             if (mainMethod != null) {
 381  15
                 boolean isPublicClazz = Modifier.isPublic(clazz.getModifiers());
 382  15
                 if (!isPublicClazz) {
 383  
                     // try to relax access
 384  0
                     mainMethod.setAccessible(true);
 385  
                 }
 386  
 
 387  
                 // call main method
 388  15
                 Object args = Sequences.emptySequence(String.class);
 389  15
                 result = mainMethod.invoke(null, args);
 390  
             }
 391  
 
 392  15
             return result;
 393  0
         } catch (Exception exp) {
 394  0
             exp.printStackTrace();
 395  0
             Throwable cause = exp.getCause();
 396  0
             if (cause != null) {
 397  0
                 System.err.println("Cause:");
 398  0
                 cause.printStackTrace();
 399  
             }
 400  0
             throw new ScriptException(exp);
 401  
         } finally {
 402  15
             ScriptContextManager.removeContext(scriptKey);
 403  
         }
 404  
     }
 405  
 
 406  
     // read a Reader fully and return the content as string
 407  
     private String readFully(Reader reader) throws ScriptException {
 408  2
         char[] arr = new char[8*1024]; // 8K at a time
 409  2
         StringBuilder buf = new StringBuilder();
 410  
         int numChars;
 411  
         try {
 412  4
             while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
 413  2
                 buf.append(arr, 0, numChars);
 414  
             }
 415  0
         } catch (IOException exp) {
 416  0
             throw new ScriptException(exp);
 417  2
         }
 418  2
         return buf.toString();
 419  
     }
 420  
 
 421  
     private String makeBindingStatement(ScriptContext ctx, Set<String> attrs, boolean inferBindings) {
 422  
         // Merge attribute names from all scopes in context into single set.
 423  8
         if (attrs.isEmpty()) {
 424  0
             return "";
 425  
         }
 426  
 
 427  
         // Define ScriptContext variable.
 428  8
         StringBuilder sb = new StringBuilder();
 429  8
         sb.append("var ");
 430  8
         sb.append(SCRIPT_CONTEXT_NAME);
 431  8
         sb.append(":javax.script.ScriptContext = ");
 432  8
         sb.append("com.sun.tools.javafx.script.ScriptContextManager.getContext(\"");
 433  8
         sb.append(getScriptKey(ctx));
 434  8
         sb.append("\"); ");
 435  
 
 436  
         // Define attributes as module variables.
 437  8
         for (String attr : attrs) {
 438  11
             Object value = ctx.getAttribute(attr);
 439  11
             if (value != null || inferBindings) { // value==null when compiling scripts
 440  10
                 sb.append("var ");
 441  10
                 sb.append(attr);
 442  10
                 String type = null;
 443  10
                 if (value != null) {
 444  9
                     type = value.getClass().getCanonicalName();
 445  9
                     if (type != null) {
 446  9
                         sb.append(':');
 447  9
                         sb.append(type);
 448  
                     }
 449  
                 }
 450  10
                 sb.append(" = ");
 451  10
                 sb.append(SCRIPT_CONTEXT_NAME);
 452  10
                 sb.append(".getAttribute(\"");
 453  10
                 sb.append(attr);
 454  10
                 sb.append("\")");
 455  10
                 if (value != null) {
 456  9
                     sb.append(" as ");
 457  9
                     sb.append(type);
 458  
                 }
 459  10
                 sb.append("; ");
 460  
             }
 461  11
         }
 462  
 
 463  8
         return sb.toString();
 464  
     }
 465  
 
 466  
     public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException {
 467  2
         if (thiz == null)
 468  0
             throw new ScriptException("target object not specified");
 469  2
         if (name == null)
 470  0
             throw new ScriptException("method name not specified");
 471  2
         Method method = findMethod(thiz.getClass(), name, args);
 472  2
         if (method == null)
 473  0
             throw new ScriptException(new NoSuchMethodException());
 474  
         try {
 475  2
             method.setAccessible(true);
 476  2
             return method.invoke(thiz, args);
 477  0
         } catch (Exception e) {
 478  0
             throw new ScriptException(e);
 479  
         }
 480  
     }
 481  
 
 482  
     public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException {
 483  3
         if (name == null)
 484  0
             throw new ScriptException("method name not specified");
 485  3
         for (Class script : scripts) {
 486  3
             Method method = findMethod(script, name, args);
 487  3
             if (method != null) {
 488  
                 try {
 489  3
                     Constructor cons = findDefaultConstructor(script);
 490  3
                     cons.setAccessible(true);
 491  3
                     Object instance = cons.newInstance();
 492  3
                     method.setAccessible(true);
 493  3
                     return method.invoke(instance, args);
 494  0
                 } catch (Exception e) {
 495  0
                     throw new ScriptException(e);
 496  
                 }
 497  
 
 498  
             }
 499  0
         }
 500  0
         throw new ScriptException(new NoSuchMethodException(name));
 501  
     }
 502  
 
 503  
     private static Method findMethod(Class clazz, String name, Object[] args) {
 504  5
         Class[] argTypes = new Class[args.length];
 505  8
         for (int i = 0; i < args.length; i++)
 506  3
             argTypes[i] = args[i].getClass();
 507  
 
 508  
         try {
 509  5
             return clazz.getMethod(name, argTypes);
 510  2
         } catch (NoSuchMethodException e) {
 511  
         // fall-through
 512  
         }
 513  
 
 514  3
         for (Method m : clazz.getMethods()) {
 515  3
             if (m.getName().equals(name)) {
 516  2
                 if (m.isVarArgs())
 517  0
                     return m;
 518  2
                 Class[] parameters = m.getParameterTypes();
 519  2
                 if (args.length != parameters.length)
 520  0
                     continue;
 521  2
                 if (argsMatch(argTypes, parameters))
 522  2
                     return m;
 523  
                 }
 524  
             }
 525  0
         return null;
 526  
     }
 527  
 
 528  
     private Constructor findDefaultConstructor(Class script) throws NoSuchMethodException {
 529  3
         Constructor[] cs = script.getDeclaredConstructors();
 530  6
         for (Constructor c : cs) {
 531  6
             if (c.getParameterTypes().length == 0) {
 532  3
                 return c;
 533  
             }
 534  
         }
 535  0
         throw new NoSuchMethodException("default constructor");
 536  
     }
 537  
 
 538  
     private static boolean argsMatch(Class[] argTypes, Class[] parameterTypes) {
 539  5
         for (int i = 0; i < argTypes.length; i++) {
 540  3
             Class arg = argTypes[i];
 541  3
             Class param = parameterTypes[i];
 542  3
             if (param.isPrimitive())
 543  2
                 param = wrappers.get(param);
 544  3
             if (param == null || !(param.isAssignableFrom(arg)))
 545  0
                 return false;
 546  
             }
 547  2
         return true;
 548  
     }
 549  
 
 550  4
     private static Map<Class,Class> wrappers = new HashMap<Class,Class>();
 551  
     static {
 552  4
         wrappers.put(boolean.class, Boolean.class);
 553  4
         wrappers.put(byte.class, Byte.class);
 554  4
         wrappers.put(char.class, Character.class);
 555  4
         wrappers.put(double.class, Double.class);
 556  4
         wrappers.put(float.class, Float.class);
 557  4
         wrappers.put(int.class, Integer.class);
 558  4
         wrappers.put(long.class, Long.class);
 559  4
         wrappers.put(short.class, Short.class);
 560  4
     }
 561  
 
 562  
     public <T> T getInterface(Class<T> clazz) {
 563  0
         return makeInterface(null, clazz);
 564  
     }
 565  
 
 566  
     public <T> T getInterface(Object thiz, Class<T> clazz) {
 567  0
         if (thiz == null) {
 568  0
             throw new IllegalArgumentException("script object is null");
 569  
         }
 570  0
         return makeInterface(thiz, clazz);
 571  
     }
 572  
 
 573  
     private <T> T makeInterface(Object obj, Class<T> clazz) {
 574  0
         final Object thiz = obj;
 575  0
         if (clazz == null || !clazz.isInterface()) {
 576  0
             throw new IllegalArgumentException("interface Class expected");
 577  
         }
 578  0
         return (T) Proxy.newProxyInstance(
 579  
             clazz.getClassLoader(),
 580  
             new Class[] { clazz },
 581  0
                 new InvocationHandler() {
 582  
                     public Object invoke(Object proxy, Method m, Object[] args)
 583  
                             throws Throwable {
 584  0
                     if (thiz == null)
 585  0
                             return invokeFunction(m.getName(), args);
 586  0
                         return invokeMethod(thiz, m.getName(), args);
 587  
                     }
 588  
                 });
 589  
     }
 590  
 
 591  
     // Workarounds for backward compatibility with old JSR-223 api on mac os
 592  
 
 593  
     public Object invoke(String name, Object...args) throws ScriptException, NoSuchMethodException
 594  
     {
 595  0
         return invokeFunction(name, args);
 596  
     }
 597  
 
 598  
     public Object invoke(Object thiz, String name, Object...args) throws ScriptException, NoSuchMethodException {
 599  0
         return invokeMethod(thiz, name, args);
 600  
     }
 601  
 
 602  
 }