jaroslav@37: /** jaroslav@358: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. jaroslav@37: * jaroslav@358: * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. jaroslav@37: * jaroslav@358: * Oracle and Java are registered trademarks of Oracle and/or its affiliates. jaroslav@358: * Other names may be trademarks of their respective owners. jaroslav@37: * jaroslav@358: * The contents of this file are subject to the terms of either the GNU jaroslav@358: * General Public License Version 2 only ("GPL") or the Common jaroslav@358: * Development and Distribution License("CDDL") (collectively, the jaroslav@358: * "License"). You may not use this file except in compliance with the jaroslav@358: * License. You can obtain a copy of the License at jaroslav@358: * http://www.netbeans.org/cddl-gplv2.html jaroslav@358: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the jaroslav@358: * specific language governing permissions and limitations under the jaroslav@358: * License. When distributing the software, include this License Header jaroslav@358: * Notice in each file and include the License file at jaroslav@358: * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this jaroslav@358: * particular file as subject to the "Classpath" exception as provided jaroslav@358: * by Oracle in the GPL Version 2 section of the License file that jaroslav@358: * accompanied this code. If applicable, add the following below the jaroslav@358: * License Header, with the fields enclosed by brackets [] replaced by jaroslav@358: * your own identifying information: jaroslav@358: * "Portions Copyrighted [year] [name of copyright owner]" jaroslav@358: * jaroslav@358: * Contributor(s): jaroslav@358: * jaroslav@358: * The Original Software is NetBeans. The Initial Developer of the Original jaroslav@358: * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved. jaroslav@358: * jaroslav@358: * If you wish your version of this file to be governed by only the CDDL jaroslav@358: * or only the GPL Version 2, indicate your decision by adding jaroslav@358: * "[Contributor] elects to include this software in this distribution jaroslav@358: * under the [CDDL or GPL Version 2] license." If you do not indicate a jaroslav@358: * single choice of license, a recipient has the option to distribute jaroslav@358: * your version of this file under either the CDDL, the GPL Version 2 or jaroslav@358: * to extend the choice of license to its licensees as provided above. jaroslav@358: * However, if you add GPL Version 2 code and therefore, elected the GPL jaroslav@358: * Version 2 license, then the option applies only if the new code is jaroslav@358: * made subject to such option by the copyright holder. jaroslav@37: */ jaroslav@37: package org.apidesign.html.kofx; jaroslav@37: jaroslav@37: import java.io.IOException; jaroslav@60: import java.io.InputStream; jaroslav@37: import java.io.InputStreamReader; jaroslav@75: import java.io.OutputStream; jaroslav@37: import java.io.PushbackInputStream; jaroslav@37: import java.io.Reader; jaroslav@74: import java.net.HttpURLConnection; jaroslav@37: import java.net.MalformedURLException; jaroslav@37: import java.net.URL; jaroslav@74: import java.net.URLConnection; jaroslav@37: import java.util.Iterator; jaroslav@37: import java.util.concurrent.Executor; jaroslav@37: import java.util.concurrent.Executors; jaroslav@158: import java.util.concurrent.ThreadFactory; jaroslav@37: import java.util.logging.Level; jaroslav@37: import java.util.logging.Logger; jaroslav@37: import javafx.application.Platform; jaroslav@131: import net.java.html.js.JavaScriptBody; jaroslav@37: import netscape.javascript.JSObject; jaroslav@37: import org.apidesign.html.json.spi.JSONCall; jaroslav@37: import org.json.JSONArray; jaroslav@37: import org.json.JSONException; jaroslav@37: import org.json.JSONObject; jaroslav@37: import org.json.JSONTokener; jaroslav@37: jaroslav@54: /** This is an implementation package - just jaroslav@54: * include its JAR on classpath and use official {@link Context} API jaroslav@54: * to access the functionality. jaroslav@37: * jaroslav@37: * @author Jaroslav Tulach jaroslav@37: */ jaroslav@37: final class LoadJSON implements Runnable { jaroslav@37: private static final Logger LOG = FXContext.LOG; jaroslav@158: private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() { jaroslav@158: @Override jaroslav@158: public Thread newThread(Runnable runnable) { jaroslav@158: Thread thread = Executors.defaultThreadFactory().newThread(runnable); jaroslav@158: thread.setDaemon(true); jaroslav@158: return thread; jaroslav@158: } jaroslav@158: }); jaroslav@37: jaroslav@37: private final JSONCall call; jaroslav@37: private final URL base; jaroslav@37: private Throwable error; jaroslav@37: private Object json; jaroslav@37: jaroslav@37: jaroslav@37: private LoadJSON(JSONCall call) { jaroslav@37: this.call = call; jaroslav@37: URL b; jaroslav@37: try { jaroslav@37: b = new URL(findBaseURL()); jaroslav@37: } catch (MalformedURLException ex) { jaroslav@37: LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex); jaroslav@37: b = null; jaroslav@37: } jaroslav@37: this.base = b; jaroslav@37: } jaroslav@37: jaroslav@37: public static void loadJSON(JSONCall call) { jaroslav@258: assert !"WebSocket".equals(call.getMethod()); jaroslav@258: REQ.execute(new LoadJSON((call))); jaroslav@37: } jaroslav@37: jaroslav@37: @Override jaroslav@37: public void run() { jaroslav@37: if (Platform.isFxApplicationThread()) { jaroslav@37: if (error != null) { jaroslav@37: call.notifyError(error); jaroslav@37: } else { jaroslav@37: call.notifySuccess(json); jaroslav@37: } jaroslav@37: return; jaroslav@37: } jaroslav@37: final String url; jaroslav@37: if (call.isJSONP()) { jaroslav@37: url = call.composeURL("dummy"); jaroslav@37: } else { jaroslav@37: url = call.composeURL(null); jaroslav@37: } jaroslav@37: try { jaroslav@37: final URL u = new URL(base, url.replace(" ", "%20")); jaroslav@74: URLConnection conn = u.openConnection(); jaroslav@74: if (conn instanceof HttpURLConnection) { jaroslav@74: HttpURLConnection huc = (HttpURLConnection) conn; jaroslav@74: if (call.getMethod() != null) { jaroslav@74: huc.setRequestMethod(call.getMethod()); jaroslav@74: } jaroslav@75: if (call.isDoOutput()) { jaroslav@75: huc.setDoOutput(true); jaroslav@75: final OutputStream os = huc.getOutputStream(); jaroslav@75: call.writeData(os); jaroslav@75: os.flush(); jaroslav@75: } jaroslav@74: } jaroslav@74: final PushbackInputStream is = new PushbackInputStream( jaroslav@74: conn.getInputStream(), 1 jaroslav@74: ); jaroslav@37: boolean array = false; jaroslav@73: boolean string = false; jaroslav@37: if (call.isJSONP()) { jaroslav@37: for (;;) { jaroslav@37: int ch = is.read(); jaroslav@37: if (ch == -1) { jaroslav@37: break; jaroslav@37: } jaroslav@37: if (ch == '[') { jaroslav@37: is.unread(ch); jaroslav@37: array = true; jaroslav@37: break; jaroslav@37: } jaroslav@37: if (ch == '{') { jaroslav@37: is.unread(ch); jaroslav@37: break; jaroslav@37: } jaroslav@37: } jaroslav@37: } else { jaroslav@37: int ch = is.read(); jaroslav@138: if (ch == -1) { jaroslav@73: string = true; jaroslav@138: } else { jaroslav@138: array = ch == '['; jaroslav@138: is.unread(ch); jaroslav@138: if (!array && ch != '{') { jaroslav@138: string = true; jaroslav@138: } jaroslav@73: } jaroslav@37: } jaroslav@73: try { jaroslav@73: if (string) { jaroslav@73: throw new JSONException(""); jaroslav@73: } jaroslav@73: Reader r = new InputStreamReader(is, "UTF-8"); jaroslav@37: jaroslav@73: JSONTokener tok = new JSONTokener(r); jaroslav@73: Object obj; jaroslav@73: obj = array ? new JSONArray(tok) : new JSONObject(tok); jaroslav@73: json = convertToArray(obj); jaroslav@73: } catch (JSONException ex) { jaroslav@73: Reader r = new InputStreamReader(is, "UTF-8"); jaroslav@73: StringBuilder sb = new StringBuilder(); jaroslav@73: for (;;) { jaroslav@73: int ch = r.read(); jaroslav@73: if (ch == -1) { jaroslav@73: break; jaroslav@73: } jaroslav@73: sb.append((char)ch); jaroslav@73: } jaroslav@73: json = sb.toString(); jaroslav@73: } jaroslav@73: } catch (IOException ex) { jaroslav@37: error = ex; jaroslav@37: } finally { jaroslav@37: Platform.runLater(this); jaroslav@37: } jaroslav@37: } jaroslav@37: jaroslav@247: static Object convertToArray(Object o) throws JSONException { jaroslav@37: if (o instanceof JSONArray) { jaroslav@37: JSONArray ja = (JSONArray)o; jaroslav@37: Object[] arr = new Object[ja.length()]; jaroslav@37: for (int i = 0; i < arr.length; i++) { jaroslav@37: arr[i] = convertToArray(ja.get(i)); jaroslav@37: } jaroslav@37: return arr; jaroslav@37: } else if (o instanceof JSONObject) { jaroslav@37: JSONObject obj = (JSONObject)o; jaroslav@37: Iterator it = obj.keys(); jaroslav@37: while (it.hasNext()) { jaroslav@37: String key = (String)it.next(); jaroslav@37: obj.put(key, convertToArray(obj.get(key))); jaroslav@37: } jaroslav@37: return obj; jaroslav@37: } else { jaroslav@37: return o; jaroslav@37: } jaroslav@37: } jaroslav@37: jaroslav@37: public static void extractJSON(Object jsonObject, String[] props, Object[] values) { jaroslav@37: if (jsonObject instanceof JSONObject) { jaroslav@37: JSONObject obj = (JSONObject)jsonObject; jaroslav@37: for (int i = 0; i < props.length; i++) { jaroslav@37: try { jaroslav@37: values[i] = obj.has(props[i]) ? obj.get(props[i]) : null; jaroslav@37: } catch (JSONException ex) { jaroslav@37: LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex); jaroslav@37: } jaroslav@37: } jaroslav@37: } jaroslav@37: if (jsonObject instanceof JSObject) { jaroslav@37: JSObject obj = (JSObject)jsonObject; jaroslav@37: for (int i = 0; i < props.length; i++) { jaroslav@37: Object val = obj.getMember(props[i]); jaroslav@37: values[i] = isDefined(val) ? val : null; jaroslav@37: } jaroslav@37: } jaroslav@37: } jaroslav@37: jaroslav@60: public static Object parse(InputStream is) throws IOException { jaroslav@60: try { jaroslav@60: InputStreamReader r = new InputStreamReader(is, "UTF-8"); jaroslav@60: JSONTokener t = new JSONTokener(r); jaroslav@60: return new JSONObject(t); jaroslav@60: } catch (JSONException ex) { jaroslav@60: throw new IOException(ex); jaroslav@60: } jaroslav@60: } jaroslav@118: jaroslav@118: @JavaScriptBody(args = { }, body = jaroslav@118: "var h;" jaroslav@118: + "if (!!window && !!window.location && !!window.location.href)\n" jaroslav@118: + " h = window.location.href;\n" jaroslav@118: + "else " jaroslav@118: + " h = null;" jaroslav@118: + "return h;\n" jaroslav@118: ) jaroslav@118: private static native String findBaseURL(); jaroslav@60: jaroslav@37: private static boolean isDefined(Object val) { jaroslav@37: return !"undefined".equals(val); jaroslav@37: } jaroslav@37: }