11package jsq .fetcher .history ;
22
33import java .io .File ;
4- import java .io .FileInputStream ;
5- import java .io .InputStreamReader ;
4+ import java .io .FileReader ;
65import java .util .Calendar ;
76import java .util .Date ;
87import java .util .List ;
98
10- import javax .script .Invocable ;
11- import javax .script .ScriptEngine ;
12- import javax .script .ScriptEngineManager ;
13- import javax .script .ScriptException ;
14-
15- import jsq .config .Config ;
16- import jsq .fetch .factory .Factory ;
17-
189import org .htmlunit .SilentCssErrorHandler ;
1910import org .htmlunit .ThreadedRefreshHandler ;
2011import org .htmlunit .WebClient ;
12+ import org .mozilla .javascript .Context ;
13+ import org .mozilla .javascript .Function ;
14+ import org .mozilla .javascript .NativeJavaObject ;
15+ import org .mozilla .javascript .Scriptable ;
16+ import org .mozilla .javascript .ScriptableObject ;
2117
22- public class GenericJSFetcher extends BaseFetcher {
18+ import jsq .config .Config ;
19+ import jsq .fetch .factory .Factory ;
2320
24- private Invocable inv ;
25-
26-
21+ public class GenericJSFetcher extends BaseFetcher {
2722 private Calendar start ;
28- private Calendar stop ;
23+ private Calendar stop ;
24+
25+ private Scriptable scope ;
26+
27+ private File scriptFile ;
28+ private long modifiedTs ;
2929
3030 /**
3131 * Create a new generic fetcher from the JavaScript file passed in {@code filename}.
@@ -34,48 +34,80 @@ public class GenericJSFetcher extends BaseFetcher {
3434 */
3535 public GenericJSFetcher (String filename ) throws Exception {
3636 try {
37- File f = new File (filename );
38- ScriptEngineManager manager = new ScriptEngineManager (null );
39- ScriptEngine engine = manager .getEngineByName ("nashorn" );
40- engine .put ("fetcher" , this );
41- engine .eval ( new InputStreamReader (new FileInputStream (f ),"utf-8" ));
42-
43- inv = (Invocable ) engine ;
44-
37+ this .scriptFile = new File (filename );
38+ reloadScriptIfNeeded ();
4539 } catch (Exception e ) {
4640 e .printStackTrace ();
4741 throw e ;
4842 }
4943 }
44+
45+ private Context enterContext () {
46+ Context context = Context .enter ();
47+ context .setLanguageVersion (Context .VERSION_ES6 );
48+ context .setOptimizationLevel (-1 );
49+ context .getWrapFactory ().setJavaPrimitiveWrap (true );
50+ return context ;
51+ }
52+
53+ private void reloadScriptIfNeeded () throws Exception {
54+ if (scriptFile .lastModified () == modifiedTs )
55+ return ;
56+ modifiedTs = scriptFile .lastModified ();
57+
58+ Context context = enterContext ();
59+
60+ scope = context .initStandardObjects ();
61+ Object jsFetcher = Context .javaToJS (this , scope );
62+ ScriptableObject .putProperty (scope , "fetcher" , jsFetcher );
63+
64+
65+ // print function is not part of default rhino
66+ context .evaluateString (scope , "function print() { "
67+ + "Packages.jsq.fetcher.history.GenericJSFetcher.print(Array.from(arguments).map((x) => x.toString()).join(' '))"
68+ + "}" , "" , 1 , null );
69+
70+ FileReader reader = new FileReader (scriptFile );
71+ context .evaluateReader (scope , reader , scriptFile .getName (), 1 , null );
72+
73+ context .exit ();
74+ }
75+
76+ public static void print (Object o ) {
77+ System .out .println (o .toString ());
78+ }
79+
5080 @ Override
5181 public String getName () {
52- return (String ) callFunc ("getName" );
82+ return (String ) callFunc ("getName" , null );
5383 }
5484
5585 @ Override
5686 public String getURL () {
57- return (String ) callFunc ("getURL" );
87+ return (String ) callFunc ("getURL" , null );
5888 }
5989
6090 public String getAPIVersion () {
61- return (String ) callFunc ("getAPIVersion" );
91+ return (String ) callFunc ("getAPIVersion" , null );
6292 }
6393 public String getVersion () {
64- return (String ) callFunc ("getVersion" );
94+ return (String ) callFunc ("getVersion" , null );
6595 }
6696
6797 @ Override
6898 public void prepare (String search , int beginYear , int beginMon ,
6999 int beginDay , int stopYear , int stopMon , int stopDay ) throws Exception {
100+ reloadScriptIfNeeded ();
101+
70102 super .prepare (search , beginYear , beginMon , beginDay , stopYear , stopMon , stopDay );
71103 start = Calendar .getInstance ();
72104 start .setTime (getStartdate ());
73105 stop = Calendar .getInstance ();
74106 stop .setTime (getStopdate ());
75107 try {
76- Object x = inv . invokeFunction ("prepare" , this , search , beginYear , beginMon , beginDay , stopYear , stopMon , stopDay );
108+ Object x = callFunc ("prepare" , new Object [] { this , search , beginYear , beginMon , beginDay , stopYear , stopMon , stopDay } );
77109 setConfig ((List <Config >) x );
78- } catch (NoSuchMethodException | ScriptException e ) {
110+ } catch (Exception e ) {
79111 e .printStackTrace ();
80112 throw e ;
81113 }
@@ -86,8 +118,8 @@ public void prepare(String search, int beginYear, int beginMon,
86118 public void process (List <Config > options ) {
87119 super .process (options );
88120 try {
89- inv . invokeFunction ("process" , options );
90- } catch (NoSuchMethodException | ScriptException e ) {
121+ callFunc ("process" , new Object [] { options } );
122+ } catch (Exception e ) {
91123 // TODO Auto-generated catch block
92124 e .printStackTrace ();
93125 }
@@ -111,20 +143,33 @@ public boolean within(Date d) {
111143 (d .getTime () <= getStopdate ().getTime ());
112144 }
113145
114- public Object callFunc (String funcname ) {
146+ public Object callFunc (String funcname , Object [] args ) {
115147 try {
116- return inv .invokeFunction (funcname );
117- } catch (NoSuchMethodException | ScriptException e ) {
148+ Context context = enterContext ();
149+ if (args == null )
150+ args = new Object [0 ];
151+ Function f = (Function ) scope .get (funcname , scope );
152+ Object result = f .call (context , scope , f , args );
153+ if (result instanceof NativeJavaObject )
154+ result = ((NativeJavaObject ) result ).unwrap ();
155+ return result ;
156+ } catch (Exception e ) {
118157 e .printStackTrace ();
119- }
158+ } finally {
159+ Context .exit ();
160+ }
120161 return null ;
121162 }
122163 public void search (String string ) {
123164 try {
124- inv .invokeFunction ("search" , this , string );
125- } catch (NoSuchMethodException | ScriptException e ) {
165+ Context context = enterContext ();
166+ Function f = (Function ) scope .get ("search" , scope );
167+ f .call (context , scope , f , new Object [] { string });
168+ } catch (Exception e ) {
126169 // TODO Auto-generated catch block
127170 e .printStackTrace ();
171+ } finally {
172+ Context .exit ();
128173 }
129174 }
130175}
0 commit comments