2009-07-03 13 views
7

In un programma Java che sto invocando un programma JavaScript definito dall'utente:Java ScriptEngine: utilizzo del valore sul lato 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)); 

Ora vorrei usare 'risultato': come posso avere un accesso ad esso? Posso identificarlo come un array (Posso iterare i suoi membri), un String, uno Integer, ecc ...?

Grazie

CURA: So solo che il mio utente mi ha dato uno script restituire l'ultimo valore. Non so nulla di questo valore. È un String, un array, ecc.? Non lo so, ma voglio usarlo.

risposta

0

Questo link può essere utile. Sembra che il meglio che puoi fare sia fare affidamento su una classe specifica per l'implementazione.

9

Tranne forse per valori semplici, preferirei che il motore di scripting costringesse i suoi valori su tipi 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)); 
    } 

} 

Anche se non è possibile modificare lo script, si può prendere il valore di ritorno e passare attraverso il proprio script generato per fare la coercizione. Questo presuppone che tu sappia qualcosa sul valore restituito.


EDIT: dal momento che non si sa nulla circa il valore di ritorno, vorrei prima testarlo utilizzando Java (getClass()) per vedere se era uno dei tipi java.lang. Se l'oggetto restituito proviene da un'API privata alla libreria, vorrei introspettarlo usando il linguaggio di scripting (in questo caso JavaScript), eventualmente costringendolo a un tipo Java o spingendo le sue proprietà in una struttura dati Java durante il processo.

Il mio JavaScript è arrugginito, ma il tutorial di John Leach sembra abbastanza buono: JavaScript Introspection.

(Si può essere in grado di utilizzare Java riflessione, ma dal momento che l'attuazione motore potrebbe variare tra versioni/JRE/motori JavaScript Java, non vorrei contare su di esso.)

2

età Questa domanda è stato chiesto prima, ma le risposte sembravano ancora corrette. Nel caso in cui sia interessante per chiunque altro cerchi di passare oggetti complessi tra Java e Javascript, ho voluto presentare la mia soluzione.

Ho scritto uno script che converte il NativeObject in oggetti JSON (in memoria) (in realtà utilizzo gli oggetti basati su BSON di MongoDB, ma dovresti essere in grado di sostituire 1-1 per JSONArray e JSONObject nel codice di esempio seguente).

Così, per esempio, dire che ho un (utente) script "create_object_script", che "restituisce" un oggetto o un array di interesse, allora posso convertirlo in JSON (cioè un elenco di HashMaps) come segue:

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" 

Ovviamente se si ha il controllo sullo script "create_object_script" è possibile farlo in un unico passaggio; i miei script sono generati dall'utente, quindi è necessario nascondere questa complessità: gli utenti scrivono solo script in cui il "valore di ritorno" è la linea finale.

Ho irrigidito lo "parsing_script" here per mantenere la lunghezza di questo post in basso.

Funzionalmente funziona molto bene; Non ho sviluppato in JS tanto è possibile che ci siano modi più efficienti per farlo. (Nota ho sempre bisogno dei miei risultati in una lista, se non lo fai allora potresti passare in un BasicDBObject "outObj" e scrivere a quello invece nel caso singleton).

Spero che questo aiuti qualcuno che si trova nella mia situazione all'una di notte scorsa!

Problemi correlati