ko4j registers implementation of Transfer and WSTransfer based on XHR and WebSocket from a browser. The Java implementations of these interfaces has been moved to ko-ws-tyrus module. JavaScript arrays passed as parameters to Java callback methods need to be wrapped.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2013-2013 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-2013 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;
48 import java.net.URISyntaxException;
49 import java.util.Iterator;
50 import javax.websocket.ClientEndpoint;
51 import javax.websocket.ContainerProvider;
52 import javax.websocket.DeploymentException;
53 import javax.websocket.OnClose;
54 import javax.websocket.OnError;
55 import javax.websocket.OnMessage;
56 import javax.websocket.OnOpen;
57 import javax.websocket.Session;
58 import javax.websocket.WebSocketContainer;
59 import net.java.html.json.OnReceive;
60 import org.apidesign.html.context.spi.Contexts;
61 import org.apidesign.html.json.spi.JSONCall;
62 import org.apidesign.html.json.spi.Technology;
63 import org.apidesign.html.json.spi.Transfer;
64 import org.apidesign.html.json.spi.WSTransfer;
65 import org.netbeans.html.wstyrus.TyrusContext.Comm;
66 import org.json.JSONArray;
67 import org.json.JSONException;
68 import org.json.JSONObject;
69 import org.json.JSONTokener;
70 import org.openide.util.lookup.ServiceProvider;
72 /** This is an implementation module that provides support for
73 * WebSocket protocol for {@link OnReceive} communication end point for
76 * Don't deal with this module directly, rather use the
77 * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
78 * WebSocket connection.
80 * There is no need to include this module in your application if you are
81 * running on JDK8. JDK8 WebView provides its own implementation of the
82 * WebSocket API based on WebSocket object inside a browser. This is included
83 * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
85 * @author Jaroslav Tulach <jtulach@netbeans.org>
87 @ServiceProvider(service = Contexts.Provider.class)
88 public final class TyrusContext
89 implements Contexts.Provider, WSTransfer<Comm>, Transfer {
91 public void fillContext(Contexts.Builder context, Class<?> requestor) {
92 // default WebSocket transfer implementation is registered
93 // in ko-fx module with 100, provide this one as a fallback only
94 context.register(WSTransfer.class, this, 1000);
95 context.register(Transfer.class, this, 1000);
99 public Comm open(String url, JSONCall callback) {
101 return new Comm(new URI(url), callback);
102 } catch (URISyntaxException ex) {
103 throw new IllegalStateException(ex);
108 public void send(Comm socket, JSONCall data) {
109 socket.session.getAsyncRemote().sendText(data.getMessage());
113 public void close(Comm socket) {
115 final Session s = socket.session;
119 } catch (IOException ex) {
120 socket.callback.notifyError(ex);
125 public void extract(Object obj, String[] props, Object[] values) {
126 LoadJSON.extractJSON(obj, props, values);
130 public Object toJSON(InputStream is) throws IOException {
131 return LoadJSON.parse(is);
135 public void loadJSON(JSONCall call) {
136 LoadJSON.loadJSON(call);
139 /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
140 * WebSocket channel. You are unlikely to get on hold of it.
143 public static final class Comm {
144 private final JSONCall callback;
145 private Session session;
147 Comm(final URI url, JSONCall callback) {
148 this.callback = callback;
150 final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
151 c.connectToServer(Comm.this, url);
152 } catch (DeploymentException | IOException ex) {
158 public synchronized void open(Session s) {
160 callback.notifySuccess(null);
164 public void close() {
166 callback.notifyError(null);
170 public void message(final String orig, Session s) {
172 String data = orig.trim();
174 JSONTokener tok = new JSONTokener(data);
175 Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
176 json = convertToArray(obj);
177 } catch (JSONException ex) {
180 callback.notifySuccess(json);
184 public void wasAnError(Throwable t) {
185 callback.notifyError(t);
188 static Object convertToArray(Object o) throws JSONException {
189 if (o instanceof JSONArray) {
190 JSONArray ja = (JSONArray) o;
191 Object[] arr = new Object[ja.length()];
192 for (int i = 0; i < arr.length; i++) {
193 arr[i] = convertToArray(ja.get(i));
196 } else if (o instanceof JSONObject) {
197 JSONObject obj = (JSONObject) o;
198 Iterator it = obj.keys();
199 while (it.hasNext()) {
200 String key = (String) it.next();
201 obj.put(key, convertToArray(obj.get(key)));