jaroslav@813: /** jaroslav@813: * Back 2 Browser Bytecode Translator jaroslav@813: * Copyright (C) 2012 Jaroslav Tulach jaroslav@813: * jaroslav@813: * This program is free software: you can redistribute it and/or modify jaroslav@813: * it under the terms of the GNU General Public License as published by jaroslav@813: * the Free Software Foundation, version 2 of the License. jaroslav@813: * jaroslav@813: * This program is distributed in the hope that it will be useful, jaroslav@813: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@813: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@813: * GNU General Public License for more details. jaroslav@813: * jaroslav@813: * You should have received a copy of the GNU General Public License jaroslav@813: * along with this program. Look for COPYING file in the top folder. jaroslav@813: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@813: */ jaroslav@813: package org.apidesign.bck2brwsr.htmlpage; jaroslav@813: jaroslav@992: import java.io.IOException; jaroslav@992: import java.io.InputStream; jaroslav@992: import java.io.InputStreamReader; jaroslav@992: import java.io.PushbackInputStream; jaroslav@992: import java.io.Reader; jaroslav@992: import java.net.URL; jaroslav@992: import java.util.Iterator; jaroslav@992: import java.util.concurrent.Executor; jaroslav@992: import java.util.concurrent.Executors; jaroslav@992: import java.util.logging.Level; jaroslav@992: import java.util.logging.Logger; jaroslav@992: import javafx.application.Platform; jaroslav@990: import netscape.javascript.JSObject; jaroslav@813: import org.apidesign.bck2brwsr.core.JavaScriptBody; jaroslav@992: import org.json.JSONArray; jaroslav@992: import org.json.JSONException; jaroslav@992: import org.json.JSONObject; jaroslav@992: import org.json.JSONTokener; jaroslav@813: jaroslav@813: /** jaroslav@813: * jaroslav@813: * @author Jaroslav Tulach jaroslav@813: */ jaroslav@813: public final class ConvertTypes { jaroslav@992: private static final Logger LOG = Logger.getLogger(ConvertTypes.class.getName()); jaroslav@813: ConvertTypes() { jaroslav@813: } jaroslav@813: jaroslav@813: public static String toString(Object object, String property) { jaroslav@813: Object ret = getProperty(object, property); jaroslav@813: return ret == null ? null : ret.toString(); jaroslav@813: } jaroslav@813: jaroslav@813: public static double toDouble(Object object, String property) { jaroslav@813: Object ret = getProperty(object, property); jaroslav@813: return ret instanceof Number ? ((Number)ret).doubleValue() : Double.NaN; jaroslav@813: } jaroslav@813: jaroslav@813: public static int toInt(Object object, String property) { jaroslav@813: Object ret = getProperty(object, property); jaroslav@813: return ret instanceof Number ? ((Number)ret).intValue() : Integer.MIN_VALUE; jaroslav@813: } jaroslav@906: jaroslav@906: public static T toModel(Class modelClass, Object object, String property) { jaroslav@906: Object ret = getProperty(object, property); jaroslav@990: if (ret instanceof JSObject) { jaroslav@990: Object real = ((JSObject)ret).getMember("koModel"); jaroslav@990: if (real != null) { jaroslav@990: ret = real; jaroslav@990: } jaroslav@990: } jaroslav@906: if (ret == null || modelClass.isInstance(ret)) { jaroslav@906: return modelClass.cast(ret); jaroslav@906: } jaroslav@906: throw new IllegalStateException("Value " + ret + " is not of type " + modelClass); jaroslav@906: } jaroslav@813: jaroslav@920: public static String toJSON(Object value) { jaroslav@920: if (value == null) { jaroslav@920: return "null"; jaroslav@920: } jaroslav@920: if (value instanceof String) { jaroslav@920: return '"' + jaroslav@920: ((String)value). jaroslav@920: replace("\"", "\\\""). jaroslav@920: replace("\n", "\\n"). jaroslav@920: replace("\r", "\\r"). jaroslav@920: replace("\t", "\\t") jaroslav@920: + '"'; jaroslav@920: } jaroslav@920: return value.toString(); jaroslav@920: } jaroslav@920: jaroslav@813: @JavaScriptBody(args = { "object", "property" }, jaroslav@879: body = "if (property === null) return object;\n" jaroslav@879: + "var p = object[property]; return p ? p : null;" jaroslav@813: ) jaroslav@813: private static Object getProperty(Object object, String property) { jaroslav@990: if (property == null) { jaroslav@990: return object; jaroslav@990: } else { jaroslav@990: if (object instanceof JSObject) { jaroslav@990: JSObject jo = (JSObject)object; jaroslav@990: return jo.getMember(property); jaroslav@990: } jaroslav@990: return null; jaroslav@990: } jaroslav@813: } jaroslav@954: jaroslav@954: public static String createJSONP(Object[] jsonResult, Runnable whenDone) { jaroslav@992: return "json" + Integer.toHexString(whenDone.hashCode()); jaroslav@954: } jaroslav@934: jaroslav@954: public static void loadJSON( jaroslav@954: String url, Object[] jsonResult, Runnable whenDone, String jsonp jaroslav@954: ) { jaroslav@992: REQ.execute(new LoadJSON(url, jsonResult, whenDone, jsonp)); jaroslav@992: } jaroslav@992: jaroslav@992: private static final Executor REQ = Executors.newCachedThreadPool(); jaroslav@992: private static final class LoadJSON implements Runnable { jaroslav@992: jaroslav@992: private final String url; jaroslav@992: private final Object[] jsonResult; jaroslav@992: private final Runnable whenDone; jaroslav@992: private final String jsonp; jaroslav@992: jaroslav@992: LoadJSON(String url, Object[] jsonResult, Runnable whenDone, String jsonp) { jaroslav@992: this.url = url; jaroslav@992: this.jsonResult = jsonResult; jaroslav@992: this.whenDone = whenDone; jaroslav@992: this.jsonp = jsonp; jaroslav@992: } jaroslav@992: jaroslav@992: @Override jaroslav@992: public void run() { jaroslav@992: if (Platform.isFxApplicationThread()) { jaroslav@992: whenDone.run(); jaroslav@992: return; jaroslav@992: } jaroslav@992: try { jaroslav@992: URL u = new URL(url.replace(" ", "%20")); jaroslav@992: InputStream is = u.openStream(); jaroslav@992: if (jsonp != null) { jaroslav@992: PushbackInputStream pis = new PushbackInputStream(is, 1); jaroslav@992: is = pis; jaroslav@992: for (;;) { jaroslav@992: int ch = pis.read(); jaroslav@992: if (ch == -1) { jaroslav@992: break; jaroslav@992: } jaroslav@992: if (ch == '{') { jaroslav@992: pis.unread(ch); jaroslav@992: break; jaroslav@992: } jaroslav@992: } jaroslav@992: } jaroslav@992: Reader r = new InputStreamReader(is, "UTF-8"); jaroslav@992: jaroslav@992: JSONTokener tok = new JSONTokener(r); jaroslav@992: JSONObject obj = new JSONObject(tok); jaroslav@992: jsonResult[0] = convertToArray(obj); jaroslav@992: } catch (JSONException | IOException ex) { jaroslav@992: jsonResult[0] = ex; jaroslav@997: LOG.log(Level.WARNING, "Cannot connect to " + url, ex); jaroslav@992: } finally { jaroslav@992: Platform.runLater(this); jaroslav@992: } jaroslav@992: } jaroslav@992: jaroslav@992: private static Object convertToArray(Object o) throws JSONException { jaroslav@992: if (o instanceof JSONArray) { jaroslav@992: JSONArray ja = (JSONArray)o; jaroslav@992: Object[] arr = new Object[ja.length()]; jaroslav@992: for (int i = 0; i < arr.length; i++) { jaroslav@992: arr[i] = convertToArray(ja.get(i)); jaroslav@992: } jaroslav@992: return arr; jaroslav@992: } else if (o instanceof JSONObject) { jaroslav@992: JSONObject obj = (JSONObject)o; jaroslav@992: Iterator it = obj.keys(); jaroslav@992: while (it.hasNext()) { jaroslav@992: String key = (String)it.next(); jaroslav@992: obj.put(key, convertToArray(obj.get(key))); jaroslav@992: } jaroslav@992: return obj; jaroslav@992: } else { jaroslav@992: return o; jaroslav@992: } jaroslav@954: } jaroslav@954: } jaroslav@954: jaroslav@954: @JavaScriptBody(args = { "url", "jsonp" }, body = jaroslav@954: "var scrpt = window.document.createElement('script');\n " jaroslav@954: + "scrpt.setAttribute('src', url);\n " jaroslav@954: + "scrpt.setAttribute('id', jsonp);\n " jaroslav@954: + "scrpt.setAttribute('type', 'text/javascript');\n " jaroslav@954: + "var body = document.getElementsByTagName('body')[0];\n " jaroslav@954: + "body.appendChild(scrpt);\n" jaroslav@954: ) jaroslav@954: private static void loadJSONP(String url, String jsonp) { jaroslav@954: jaroslav@954: } jaroslav@954: jaroslav@934: public static void extractJSON(Object jsonObject, String[] props, Object[] values) { jaroslav@992: if (jsonObject instanceof JSONObject) { jaroslav@992: JSONObject obj = (JSONObject)jsonObject; jaroslav@992: for (int i = 0; i < props.length; i++) { jaroslav@992: try { jaroslav@992: values[i] = obj.get(props[i]); jaroslav@992: } catch (JSONException ex) { jaroslav@992: LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex); jaroslav@992: } jaroslav@992: } jaroslav@992: jaroslav@934: } jaroslav@992: jaroslav@934: } jaroslav@934: jaroslav@813: }