org.webswing.toolkit.jslink.WebJSObject Maven / Gradle / Ivy
package org.webswing.toolkit.jslink;
import java.applet.Applet;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeoutException;
import netscape.javascript.JSException;
import netscape.javascript.JSObject;
import org.webswing.Constants;
import org.webswing.model.jslink.JSObjectMsg;
import org.webswing.model.jslink.JavaEvalRequestMsgIn;
import org.webswing.model.s2c.AppFrameMsgOut;
import org.webswing.toolkit.util.DeamonThreadFactory;
import org.webswing.toolkit.util.JsLinkUtil;
import org.webswing.toolkit.util.Services;
import org.webswing.toolkit.util.WeakValueHashMap;
public class WebJSObject extends JSObject {
private static final Map> jsGarbageCollectionMap = new HashMap>();
private static final WeakValueHashMap javaReferences = new WeakValueHashMap();
private static boolean jsLinkAllowed = Boolean.getBoolean(Constants.SWING_START_SYS_PROP_ALLOW_JSLINK);
private static String jsLinkWhitelistProp = System.getProperty(Constants.SWING_START_SYS_PROP_JSLINK_WHITELIST, "");
private static List jsLinkWhitelist;
private static ScheduledExecutorService javaEvalThread = Executors.newSingleThreadScheduledExecutor(DeamonThreadFactory.getInstance("Webswing JsLink Processor"));
private JSObjectMsg jsThis;
static {
jsLinkWhitelist = new ArrayList<>();
jsLinkWhitelist = Arrays.asList(jsLinkWhitelistProp.split(","));
}
public WebJSObject(JSObjectMsg jsThis) {
this.jsThis = jsThis;
if (jsThis != null) {
synchronized (jsGarbageCollectionMap) {
jsGarbageCollectionMap.put(jsThis.getId() + "", new WeakReference(jsThis));
}
}
}
@Override
public Object call(String methodName, Object[] args) throws JSException {
AppFrameMsgOut msg = JsLinkUtil.generateCallRequest(jsThis, methodName, args);
return sendJsRequest(msg);
}
@Override
public Object eval(String s) throws JSException {
AppFrameMsgOut msg = JsLinkUtil.generateEvalRequest(jsThis, s);
return sendJsRequest(msg);
}
@Override
public Object getMember(String name) throws JSException {
AppFrameMsgOut msg = JsLinkUtil.generateGetMemberRequest(jsThis, name);
return sendJsRequest(msg);
}
@Override
public void setMember(String name, Object value) throws JSException {
AppFrameMsgOut msg = JsLinkUtil.generateSetMemberRequest(jsThis, name, value);
sendJsRequest(msg);
}
@Override
public void removeMember(String name) throws JSException {
AppFrameMsgOut msg = JsLinkUtil.generateRemoveMemberRequest(jsThis, name);
sendJsRequest(msg);
}
@Override
public Object getSlot(int index) throws JSException {
AppFrameMsgOut msg = JsLinkUtil.generateGetSlotRequest(jsThis, index);
return sendJsRequest(msg);
}
@Override
public void setSlot(int index, Object value) throws JSException {
AppFrameMsgOut msg = JsLinkUtil.generateSetSlotRequest(jsThis, index, value);
sendJsRequest(msg);
}
public static JSObject getWindow(Applet paramApplet) throws JSException {
return new WebJSObject(null);
}
private static Object sendJsRequest(AppFrameMsgOut msg) {
try {
Object result = Services.getConnectionService().sendObjectSync(msg, msg.getJsRequest().getCorrelationId());
Object parsedResult = JsLinkUtil.parseResponse(result);
return parsedResult;
} catch (TimeoutException e) {
throw new JSException(e.getMessage());
} catch (Exception e) {
throw new JSException(e.getMessage());
}
}
public static List getGarbage() {
ArrayList result = new ArrayList();
synchronized (jsGarbageCollectionMap) {
for (Iterator i = jsGarbageCollectionMap.keySet().iterator(); i.hasNext();) {
String key = i.next();
if (jsGarbageCollectionMap.get(key).isEnqueued()) {
result.add(key);
i.remove();
}
}
}
return result;
}
public JSObjectMsg getThisId() {
return jsThis;
}
public static String createJavaReference(Object arg) {
return createJavaReference(arg, UUID.randomUUID().toString());
}
public static String createJavaReference(Object arg, String newId) {
if (javaReferences.containsValue(arg)) {
String id = null;
for (String key : javaReferences.keySet()) {
if (javaReferences.get(key) == arg) {
id = key;
}
}
return id;
} else {
String id = newId;
javaReferences.put(id, arg);
return id;
}
}
public static Object getJavaReference(String id) {
Object o = javaReferences.get(id);
return o;
}
public static Future> evaluateJava(final JavaEvalRequestMsgIn javaReq) {
return javaEvalThread.submit(new Runnable() {
@Override
public void run() {
if (jsLinkAllowed) {
Object javaRef = javaReferences.get(javaReq.getObjectId());
AppFrameMsgOut result = JsLinkUtil.callMatchingMethod(javaReq, javaRef, jsLinkWhitelist);
Services.getConnectionService().sendObject(result);
} else {
Serializable result = JsLinkUtil.getErrorResponse(javaReq, "JsLink is not allowed for this application. Set the 'allowJsLink' to true in webswing.config to enable it.");
Services.getConnectionService().sendObject(result);
}
}
});
}
}