During the API review process (bug 246133) the reviewers decided that in order to include html4j to NetBeans Platform, we need to stop using org.apidesign namespace and switch to NetBeans one. Repackaging all SPI packages into org.netbeans.html.smthng.spi.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
6 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7 * Other names may be trademarks of their respective owners.
9 * The contents of this file are subject to the terms of either the GNU
10 * General Public License Version 2 only ("GPL") or the Common
11 * Development and Distribution License("CDDL") (collectively, the
12 * "License"). You may not use this file except in compliance with the
13 * License. You can obtain a copy of the License at
14 * http://www.netbeans.org/cddl-gplv2.html
15 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16 * specific language governing permissions and limitations under the
17 * License. When distributing the software, include this License Header
18 * Notice in each file and include the License file at
19 * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
20 * particular file as subject to the "Classpath" exception as provided
21 * by Oracle in the GPL Version 2 section of the License file that
22 * accompanied this code. If applicable, add the following below the
23 * License Header, with the fields enclosed by brackets [] replaced by
24 * your own identifying information:
25 * "Portions Copyrighted [year] [name of copyright owner]"
29 * The Original Software is NetBeans. The Initial Developer of the Original
30 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
32 * If you wish your version of this file to be governed by only the CDDL
33 * or only the GPL Version 2, indicate your decision by adding
34 * "[Contributor] elects to include this software in this distribution
35 * under the [CDDL or GPL Version 2] license." If you do not indicate a
36 * single choice of license, a recipient has the option to distribute
37 * your version of this file under either the CDDL, the GPL Version 2 or
38 * to extend the choice of license to its licensees as provided above.
39 * However, if you add GPL Version 2 code and therefore, elected the GPL
40 * Version 2 license, then the option applies only if the new code is
41 * made subject to such option by the copyright holder.
43 package org.netbeans.html.wstyrus;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.io.InputStreamReader;
48 import java.io.OutputStream;
49 import java.io.PushbackInputStream;
50 import java.io.Reader;
51 import java.net.HttpURLConnection;
53 import java.net.URLConnection;
54 import java.util.ArrayList;
55 import java.util.Iterator;
56 import java.util.List;
57 import java.util.concurrent.Executor;
58 import java.util.concurrent.Executors;
59 import java.util.concurrent.ThreadFactory;
60 import java.util.logging.Logger;
61 import net.java.html.js.JavaScriptBody;
62 import org.netbeans.html.json.spi.JSONCall;
63 import org.json.JSONArray;
64 import org.json.JSONException;
65 import org.json.JSONObject;
66 import org.json.JSONTokener;
68 /** This is an implementation package - just
69 * include its JAR on classpath and use official {@link Context} API
70 * to access the functionality.
72 * @author Jaroslav Tulach
74 final class LoadJSON implements Runnable {
75 private static final Logger LOG = Logger.getLogger(LoadJSON.class.getName());
76 private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
78 public Thread newThread(Runnable runnable) {
79 Thread thread = Executors.defaultThreadFactory().newThread(runnable);
80 thread.setDaemon(true);
85 private final JSONCall call;
86 private final URL base;
89 private LoadJSON(JSONCall call) {
94 public static void loadJSON(JSONCall call) {
95 assert !"WebSocket".equals(call.getMethod());
96 REQ.execute(new LoadJSON((call)));
102 Throwable error = null;
105 if (call.isJSONP()) {
106 url = call.composeURL("dummy");
108 url = call.composeURL(null);
111 final URL u = new URL(base, url.replace(" ", "%20"));
112 URLConnection conn = u.openConnection();
113 if (call.isDoOutput()) {
114 conn.setDoOutput(true);
116 if (call.getMethod() != null && conn instanceof HttpURLConnection) {
117 ((HttpURLConnection) conn).setRequestMethod(call.getMethod());
119 if (call.isDoOutput()) {
120 final OutputStream os = conn.getOutputStream();
124 final PushbackInputStream is = new PushbackInputStream(
125 conn.getInputStream(), 1
127 boolean[] arrayOrString = { false, false };
128 detectJSONType(call.isJSONP(), is, arrayOrString);
130 if (arrayOrString[1]) {
131 throw new JSONException("");
133 JSONTokener tok = createTokener(is);
135 obj = arrayOrString[0] ? new JSONArray(tok) : new JSONObject(tok);
136 json = convertToArray(obj);
137 } catch (JSONException ex) {
138 Reader r = new InputStreamReader(is, "UTF-8");
139 StringBuilder sb = new StringBuilder();
147 json = sb.toString();
149 } catch (IOException ex) {
153 call.notifyError(error);
155 call.notifySuccess(json);
160 private static void detectJSONType(boolean skipAnything, final PushbackInputStream is, boolean[] arrayOrString) throws IOException {
164 arrayOrString[1] = true;
167 if (Character.isWhitespace(ch)) {
173 arrayOrString[0] = true;
182 arrayOrString[1] = true;
188 private static JSONTokener createTokener(InputStream is) throws IOException {
189 Reader r = new InputStreamReader(is, "UTF-8");
191 return new JSONTokener(r);
192 } catch (LinkageError ex) {
193 // phones may carry outdated version of JSONTokener
194 StringBuilder sb = new StringBuilder();
202 return new JSONTokener(sb.toString());
206 static Object convertToArray(Object o) throws JSONException {
207 if (o instanceof JSONArray) {
208 JSONArray ja = (JSONArray)o;
209 Object[] arr = new Object[ja.length()];
210 for (int i = 0; i < arr.length; i++) {
211 arr[i] = convertToArray(ja.get(i));
214 } else if (o instanceof JSONObject) {
215 JSONObject obj = (JSONObject)o;
216 Iterator it = obj.keys();
217 List<Object> collect = new ArrayList<Object>();
218 while (it.hasNext()) {
219 String key = (String)it.next();
220 final Object val = obj.get(key);
221 final Object newVal = convertToArray(val);
227 int size = collect.size();
228 for (int i = 0; i < size; i += 2) {
229 obj.put((String) collect.get(i), collect.get(i + 1));
232 } else if (o == JSONObject.NULL) {
239 public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
240 if (jsonObject instanceof JSONObject) {
241 JSONObject obj = (JSONObject)jsonObject;
242 for (int i = 0; i < props.length; i++) {
243 Object val = obj.opt(props[i]);
244 if (val == JSONObject.NULL) {
251 for (int i = 0; i < props.length; i++) {
252 values[i] = getProperty(jsonObject, props[i]);
256 @JavaScriptBody(args = {"object", "property"},
258 = "if (property === null) return object;\n"
259 + "if (object === null) return null;\n"
260 + "var p = object[property]; return p ? p : null;"
262 private static Object getProperty(Object object, String property) {
266 public static Object parse(InputStream is) throws IOException {
268 PushbackInputStream push = new PushbackInputStream(is, 1);
269 boolean[] arrayOrString = { false, false };
270 detectJSONType(false, push, arrayOrString);
271 JSONTokener t = createTokener(push);
272 Object obj = arrayOrString[0] ? new JSONArray(t) : new JSONObject(t);
273 return convertToArray(obj);
274 } catch (JSONException ex) {
275 throw new IOException(ex);