jaroslav@1189: /** jaroslav@1227: * Back 2 Browser Bytecode Translator jaroslav@1227: * Copyright (C) 2012 Jaroslav Tulach jaroslav@1189: * jaroslav@1189: * This program is free software: you can redistribute it and/or modify jaroslav@1189: * it under the terms of the GNU General Public License as published by jaroslav@1189: * the Free Software Foundation, version 2 of the License. jaroslav@1189: * jaroslav@1189: * This program is distributed in the hope that it will be useful, jaroslav@1189: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@1189: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@1227: * GNU General Public License for more details. jaroslav@1189: * jaroslav@1189: * You should have received a copy of the GNU General Public License jaroslav@1189: * along with this program. Look for COPYING file in the top folder. jaroslav@1227: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@1189: */ jaroslav@1228: package org.apidesign.bck2brwsr.ko2brwsr; jaroslav@1189: jaroslav@1199: import java.io.ByteArrayOutputStream; jaroslav@1196: import java.io.IOException; jaroslav@1196: import java.io.InputStream; jaroslav@1196: import java.io.InputStreamReader; jaroslav@1425: import org.apidesign.bck2brwsr.core.JavaScriptBody; jaroslav@1189: import org.apidesign.html.json.spi.JSONCall; jaroslav@1189: import org.apidesign.html.json.spi.Transfer; jaroslav@1253: import org.apidesign.html.json.spi.WSTransfer; jaroslav@1189: jaroslav@1189: /** jaroslav@1189: * jaroslav@1189: * @author Jaroslav Tulach jaroslav@1189: */ jaroslav@1420: final class BrwsrCtxImpl implements Transfer, WSTransfer { jaroslav@1220: private BrwsrCtxImpl() {} jaroslav@1189: jaroslav@1220: public static final BrwsrCtxImpl DEFAULT = new BrwsrCtxImpl(); jaroslav@1189: jaroslav@1189: @Override jaroslav@1189: public void extract(Object obj, String[] props, Object[] values) { jaroslav@1425: extractJSON(obj, props, values); jaroslav@1189: } jaroslav@1189: jaroslav@1189: @Override jaroslav@1189: public void loadJSON(final JSONCall call) { jaroslav@1189: class R implements Runnable { jaroslav@1254: final boolean success; jaroslav@1254: jaroslav@1254: public R(boolean success) { jaroslav@1254: this.success = success; jaroslav@1254: } jaroslav@1254: jaroslav@1189: Object[] arr = { null }; jaroslav@1189: @Override jaroslav@1189: public void run() { jaroslav@1254: if (success) { jaroslav@1254: call.notifySuccess(arr[0]); jaroslav@1254: } else { jaroslav@1254: Throwable t; jaroslav@1254: if (arr[0] instanceof Throwable) { jaroslav@1254: t = (Throwable) arr[0]; jaroslav@1254: } else { jaroslav@1254: if (arr[0] == null) { jaroslav@1254: t = new IOException(); jaroslav@1254: } else { jaroslav@1254: t = new IOException(arr[0].toString()); jaroslav@1254: } jaroslav@1254: } jaroslav@1254: call.notifyError(t); jaroslav@1254: } jaroslav@1189: } jaroslav@1189: } jaroslav@1254: R success = new R(true); jaroslav@1254: R failure = new R(false); jaroslav@1189: if (call.isJSONP()) { jaroslav@1425: String me = createJSONP(success.arr, success); jaroslav@1425: loadJSONP(call.composeURL(me), me); jaroslav@1189: } else { jaroslav@1199: String data = null; jaroslav@1199: if (call.isDoOutput()) { jaroslav@1199: try { jaroslav@1199: ByteArrayOutputStream bos = new ByteArrayOutputStream(); jaroslav@1199: call.writeData(bos); jaroslav@1199: data = new String(bos.toByteArray(), "UTF-8"); jaroslav@1199: } catch (IOException ex) { jaroslav@1199: call.notifyError(ex); jaroslav@1199: } jaroslav@1199: } jaroslav@1425: loadJSON(call.composeURL(null), success.arr, success, failure, call.getMethod(), data); jaroslav@1189: } jaroslav@1189: } jaroslav@1189: jaroslav@1189: @Override jaroslav@1196: public Object toJSON(InputStream is) throws IOException { jaroslav@1196: StringBuilder sb = new StringBuilder(); jaroslav@1196: InputStreamReader r = new InputStreamReader(is); jaroslav@1196: for (;;) { jaroslav@1196: int ch = r.read(); jaroslav@1196: if (ch == -1) { jaroslav@1196: break; jaroslav@1196: } jaroslav@1196: sb.append((char)ch); jaroslav@1196: } jaroslav@1425: return parse(sb.toString()); jaroslav@1196: } jaroslav@1249: jaroslav@1249: @Override jaroslav@1253: public LoadWS open(String url, JSONCall callback) { jaroslav@1253: return new LoadWS(callback, url); jaroslav@1253: } jaroslav@1253: jaroslav@1253: @Override jaroslav@1253: public void send(LoadWS socket, JSONCall data) { jaroslav@1253: socket.send(data); jaroslav@1253: } jaroslav@1253: jaroslav@1253: @Override jaroslav@1253: public void close(LoadWS socket) { jaroslav@1253: socket.close(); jaroslav@1253: } jaroslav@1425: jaroslav@1425: // jaroslav@1425: // implementations jaroslav@1425: // jaroslav@1425: jaroslav@1425: @JavaScriptBody(args = {"object", "property"}, jaroslav@1425: body jaroslav@1425: = "if (property === null) return object;\n" jaroslav@1425: + "if (object === null) return null;\n" jaroslav@1425: + "var p = object[property]; return p ? p : null;" jaroslav@1425: ) jaroslav@1425: private static Object getProperty(Object object, String property) { jaroslav@1425: return null; jaroslav@1425: } jaroslav@1425: jaroslav@1425: public static String createJSONP(Object[] jsonResult, Runnable whenDone) { jaroslav@1425: int h = whenDone.hashCode(); jaroslav@1425: String name; jaroslav@1425: for (;;) { jaroslav@1425: name = "jsonp" + Integer.toHexString(h); jaroslav@1425: if (defineIfUnused(name, jsonResult, whenDone)) { jaroslav@1425: return name; jaroslav@1425: } jaroslav@1425: h++; jaroslav@1425: } jaroslav@1425: } jaroslav@1425: jaroslav@1425: @JavaScriptBody(args = {"name", "arr", "run"}, body jaroslav@1425: = "if (window[name]) return false;\n " jaroslav@1425: + "window[name] = function(data) {\n " jaroslav@1425: + " delete window[name];\n" jaroslav@1425: + " var el = window.document.getElementById(name);\n" jaroslav@1425: + " el.parentNode.removeChild(el);\n" jaroslav@1425: + " arr[0] = data;\n" jaroslav@1425: + " run.run__V();\n" jaroslav@1425: + "};\n" jaroslav@1425: + "return true;\n" jaroslav@1425: ) jaroslav@1425: private static boolean defineIfUnused(String name, Object[] arr, Runnable run) { jaroslav@1425: return true; jaroslav@1425: } jaroslav@1425: jaroslav@1425: @JavaScriptBody(args = {"s"}, body = "return eval('(' + s + ')');") jaroslav@1425: static Object parse(String s) { jaroslav@1425: return s; jaroslav@1425: } jaroslav@1425: jaroslav@1425: @JavaScriptBody(args = {"url", "arr", "callback", "onError", "method", "data"}, body = "" jaroslav@1425: + "var request = new XMLHttpRequest();\n" jaroslav@1425: + "if (!method) method = 'GET';\n" jaroslav@1425: + "request.open(method, url, true);\n" jaroslav@1425: + "request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n" jaroslav@1425: + "request.onreadystatechange = function() {\n" jaroslav@1425: + " if (this.readyState!==4) return;\n" jaroslav@1425: + " try {\n" jaroslav@1425: + " arr[0] = eval('(' + this.response + ')');\n" jaroslav@1425: + " } catch (error) {;\n" jaroslav@1425: + " arr[0] = this.response;\n" jaroslav@1425: + " }\n" jaroslav@1425: + " callback.run__V();\n" jaroslav@1425: + "};\n" jaroslav@1425: + "request.onerror = function (e) {\n" jaroslav@1425: + " arr[0] = e; onError.run__V();\n" jaroslav@1425: + "}\n" jaroslav@1425: + "if (data) request.send(data);" jaroslav@1425: + "else request.send();" jaroslav@1425: ) jaroslav@1425: static void loadJSON( jaroslav@1425: String url, Object[] jsonResult, Runnable whenDone, Runnable whenErr, String method, String data jaroslav@1425: ) { jaroslav@1425: } jaroslav@1425: jaroslav@1425: @JavaScriptBody(args = {"url", "jsonp"}, body jaroslav@1425: = "var scrpt = window.document.createElement('script');\n " jaroslav@1425: + "scrpt.setAttribute('src', url);\n " jaroslav@1425: + "scrpt.setAttribute('id', jsonp);\n " jaroslav@1425: + "scrpt.setAttribute('type', 'text/javascript');\n " jaroslav@1425: + "var body = document.getElementsByTagName('body')[0];\n " jaroslav@1425: + "body.appendChild(scrpt);\n" jaroslav@1425: ) jaroslav@1425: static void loadJSONP(String url, String jsonp) { jaroslav@1425: jaroslav@1425: } jaroslav@1425: jaroslav@1425: public static void extractJSON(Object jsonObject, String[] props, Object[] values) { jaroslav@1425: for (int i = 0; i < props.length; i++) { jaroslav@1425: values[i] = getProperty(jsonObject, props[i]); jaroslav@1425: } jaroslav@1425: } jaroslav@1425: jaroslav@1189: }