View Javadoc
1   package org.argeo.cms.ui.script;
2   
3   import java.io.IOException;
4   import java.io.InputStreamReader;
5   import java.io.Reader;
6   import java.net.URL;
7   
8   import javax.jcr.Repository;
9   import javax.script.ScriptEngine;
10  import javax.script.ScriptEngineManager;
11  import javax.script.ScriptException;
12  
13  import org.apache.commons.logging.Log;
14  import org.apache.commons.logging.LogFactory;
15  import org.argeo.cms.CmsException;
16  import org.eclipse.rap.rwt.application.Application;
17  import org.eclipse.rap.rwt.application.ApplicationConfiguration;
18  import org.osgi.framework.BundleContext;
19  import org.osgi.framework.BundleException;
20  import org.osgi.framework.wiring.BundleWiring;
21  
22  public class CmsScriptRwtApplication implements ApplicationConfiguration {
23  	public final static String APP = "APP";
24  	public final static String BC = "BC";
25  
26  	private final Log log = LogFactory.getLog(CmsScriptRwtApplication.class);
27  
28  	BundleContext bundleContext;
29  	Repository repository;
30  
31  	ScriptEngine engine;
32  
33  	public void init(BundleContext bundleContext) {
34  		this.bundleContext = bundleContext;
35  		ClassLoader bundleCl = bundleContext.getBundle().adapt(BundleWiring.class).getClassLoader();
36  		ClassLoader originalCcl = Thread.currentThread().getContextClassLoader();
37  		try {
38  //			Thread.currentThread().setContextClassLoader(bundleCl);// GraalVM needs it to be before creating manager
39  //			ScriptEngineManager scriptEngineManager = new ScriptEngineManager(bundleCl);
40  //			engine = scriptEngineManager.getEngineByName("JavaScript");
41  //			if (engine == null) {// Nashorn
42  //				Thread.currentThread().setContextClassLoader(originalCcl);
43  //				scriptEngineManager = new ScriptEngineManager();
44  //				Thread.currentThread().setContextClassLoader(bundleCl);
45  //				engine = scriptEngineManager.getEngineByName("JavaScript");
46  //			}
47  			engine = loadScriptEngine(originalCcl, bundleCl);
48  
49  			// Load script
50  			URL appUrl = bundleContext.getBundle().getEntry("cms/app.js");
51  			// System.out.println("Loading " + appUrl);
52  			// System.out.println("Loading " + appUrl.getHost());
53  			// System.out.println("Loading " + appUrl.getPath());
54  
55  			CmsScriptApp app = new CmsScriptApp(engine);
56  			engine.put(APP, app);
57  			engine.put(BC, bundleContext);
58  			try (Reader reader = new InputStreamReader(appUrl.openStream())) {
59  				engine.eval(reader);
60  			} catch (IOException | ScriptException e) {
61  				throw new CmsException("Cannot execute " + appUrl, e);
62  			}
63  
64  			if (log.isDebugEnabled())
65  				log.debug("CMS script app initialized from " + appUrl);
66  
67  		} catch (Exception e) {
68  			e.printStackTrace();
69  		} finally {
70  			Thread.currentThread().setContextClassLoader(originalCcl);
71  		}
72  	}
73  
74  	public void destroy(BundleContext bundleContext) {
75  		engine = null;
76  	}
77  
78  	@Override
79  	public void configure(Application application) {
80  		load(application);
81  	}
82  
83  	void load(Application application) {
84  		CmsScriptApp app = getApp();
85  		app.apply(bundleContext, repository, application);
86  		if (log.isDebugEnabled())
87  			log.debug("CMS script app loaded to " + app.getWebPath());
88  	}
89  
90  	CmsScriptApp getApp() {
91  		if (engine == null)
92  			throw new IllegalStateException("CMS script app is not initialized");
93  		return (CmsScriptApp) engine.get(APP);
94  	}
95  
96  	void update() {
97  
98  		try {
99  			bundleContext.getBundle().update();
100 		} catch (BundleException e) {
101 			e.printStackTrace();
102 		}
103 	}
104 
105 	public void setRepository(Repository repository) {
106 		this.repository = repository;
107 	}
108 
109 	private static ScriptEngine loadScriptEngine(ClassLoader originalCcl, ClassLoader bundleCl) {
110 		Thread.currentThread().setContextClassLoader(bundleCl);// GraalVM needs it to be before creating manager
111 		ScriptEngineManager scriptEngineManager = new ScriptEngineManager(bundleCl);
112 		ScriptEngine engine = scriptEngineManager.getEngineByName("JavaScript");
113 		if (engine == null) {// Nashorn
114 			Thread.currentThread().setContextClassLoader(originalCcl);
115 			scriptEngineManager = new ScriptEngineManager();
116 			Thread.currentThread().setContextClassLoader(bundleCl);
117 			engine = scriptEngineManager.getEngineByName("JavaScript");
118 		}
119 		return engine;
120 	}
121 }