2009-07-03 13 views
7

En un programa Java que estoy invocando un programa JavaScript definida por el usuario:Java ScriptEngine: ¿usa valor en el lado de Java?

File userJSFile=...; 
javax.script.ScriptEngineManager mgr=new ScriptEngineManager(); 
javax.script.ScriptEngine scripEngine= mgr.getEngineByExtension("js"); 
Object result=scripEngine.eval(new java.io.FileReader(userJSFile)); 

Ahora me gustaría utilizar 'resultado': ¿cómo puedo tener un acceso a ella? ¿Puedo identificarlo como una matriz (puedo iterar lanzar sus miembros), un String, un Integer, etc ...?

Gracias

EDITADO: Sólo sé que mi usuario me dio un guión devolver el último valor. No sé nada sobre este valor. ¿Es String, una matriz, etc.? No lo sé, pero quiero usarlo.

Respuesta

0

Esto link puede ser útil. Parece que lo mejor que puede hacer es confiar en una clase específica de implementación.

9

Excepto tal vez por valores simples, prefiero dejar que el motor de secuencias de comandos forzar sus valores a los tipos de Java.

public class ScriptDemo { 

    static class Result { 
    private String[] words; 

    public void setWords(String[] words) { 
     this.words = words; 
    } 
    } 

    static final String SCRIPT = "var foo = 'Hello World!';\n" 
     + "result.setWords(foo.split(' '));"; 

    public static void main(String[] args) 
     throws ScriptException { 
    Result result = new Result(); 
    javax.script.ScriptEngineManager mgr = new ScriptEngineManager(); 
    javax.script.ScriptEngine scripEngine = mgr 
     .getEngineByExtension("js"); 
    scripEngine.getContext().setAttribute("result", result, 
     ScriptContext.ENGINE_SCOPE); 
    scripEngine.eval(SCRIPT); 
    System.out.println(Arrays.toString(result.words)); 
    } 

} 

Incluso si no se puede editar el script, se puede tomar el valor de retorno y pasarlo a través de su propia secuencia de comandos generada para hacer la coerción. Esto supone que sabes algo sobre el valor que se devuelve.


EDIT: ya que nada se sabe sobre el valor de retorno, me gustaría probar primero que el uso de Java (getClass()) para ver si se trataba de uno de los tipos de java.lang. Si el objeto devuelto es de una API privada a la biblioteca, lo introspecho usando el lenguaje de scripting (en este caso JavaScript), posiblemente forzándolo a un tipo de Java o insertando sus propiedades en alguna estructura de datos de Java durante el proceso.

Mi JavaScript es oxidado, pero el tutorial de John Leach se ve bastante bien: JavaScript Introspection.

(Es posible que pueda utilizar la reflexión de Java, pero ya que la implementación del motor podría variar entre Java JRE versiones/motores/JavaScript, yo no confiar en ella.) Hace

2

edades fue hecho esta pregunta, pero las respuestas aún parecían correctas. En caso de que sea de interés para cualquier otra persona que intente pasar objetos complejos entre Java y Javascript, quería presentar mi solución.

Escribí un script que convierte NativeObject en objetos JSON (en memoria) (en realidad utilizo objetos basados ​​en BSON de MongoDB, pero solo debería poder sustituir 1-1 por JSONArray y JSONObject en el código de ejemplo siguiente)

Así, por ejemplo, decir que tengo una (usuario) guión "create_object_script", que "devuelve" algún objeto o conjunto de intereses, entonces pueden convertirlo en JSON (es decir, una lista de HashMaps) de la siguiente manera:

Object returnVal = engine.eval(create_object_script); 
engine.put("output", returnVal); 
BasicDBObject objFactory = new BasicDBObject(); // (or JSON equivalent) 
BasicDBList listFactory = new BasicDBList(); // (or JSON equivalent) 
BasicDBList outList = new BasicDBList(); // (or JSON equivalent) 
engine.put("objFactory", objFactory); 
engine.put("listFactory", listFactory); 
engine.put("outList", outList); 
engine.eval(parsing_script); // (described below) 
// "outList" is now populated with (in-memory) JSON representations of "returnVal" 

Obviamente, si tiene control sobre el script "create_object_script" puede hacerlo en un solo paso; mis scripts son generados por el usuario, por lo que es necesario ocultar esta complejidad: los usuarios solo escriben scripts donde el "valor de retorno" es la última línea.

He escrito el "sintáctico_de_datos" here para mantener la longitud de esta publicación.

Funcionalmente esto funciona muy bien; No he desarrollado mucho en JS, así que es posible que haya formas más eficientes de hacerlo. (Nota: siempre necesito mis resultados en una lista, si no lo hace, podría pasar un "outObj" de BasicDBObject y escribir en ese caso en el caso de singleton).

Espero que esto ayude a alguien que se encuentre en mi situación a la 1 de la madrugada.