diff options
Diffstat (limited to 'sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org')
15 files changed, 491 insertions, 356 deletions
diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/WebsocketBinding.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/WebsocketBinding.java index 8988b376de..a78a6b11c2 100644 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/WebsocketBinding.java +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/WebsocketBinding.java @@ -28,6 +28,7 @@ import org.apache.tuscany.sca.provider.BaseBindingImpl; public class WebsocketBinding extends BaseBindingImpl {
public static final QName TYPE = new QName(SCA11_TUSCANY_NS, "binding.websocket");
+ private String port;
public WebsocketBinding() {
}
@@ -37,4 +38,12 @@ public class WebsocketBinding extends BaseBindingImpl { return TYPE;
}
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
}
diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JSONUtil.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JSONUtil.java index 492dfae3dd..3fdb1ee1c1 100644 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JSONUtil.java +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JSONUtil.java @@ -33,6 +33,18 @@ public class JSONUtil { private static Gson gson = new Gson(); + public static String encodeMessage(WebSocketBindingMessage request) { + return gson.toJson(request); + } + + public static WebSocketBindingMessage decodeMessage(String jsonRequest) { + return gson.fromJson(jsonRequest, WebSocketBindingMessage.class); + } + + public static String encodePayload(Object payload) { + return gson.toJson(payload); + } + /** * Convert request parameters from JSON to operation parameter types. * @@ -42,7 +54,7 @@ public class JSONUtil { * the operation to invoke * @return an array of objects */ - public static Object[] decodeJsonParamsForOperation(String jsonData, Operation operation) { + public static Object[] decodePayloadForOperation(String jsonData, Operation operation) { Object[] args = new Object[operation.getInputType().getLogical().size()]; final String[] json = parseArray(jsonData); int index = 0; @@ -100,49 +112,4 @@ public class JSONUtil { private JSONUtil() { } - /** - * Converts a Java object to JSON format. - * - * @param response - * the response to convert - * @return the object in JSON format - */ - public static String encodeResponse(Object response) { - return gson.toJson(response); - } - - /** - * Convert request parameters as JSON array. - * - * @param params - * request parameters - * @return request parameters as JSON array - */ - public static String encodeRequestParams(Object[] params) { - StringBuilder builder = new StringBuilder(); - for (int index = 0; index < params.length; index++) { - Object param = params[index]; - builder.append(index == 0 ? "[" : ","); - builder.append(gson.toJson(param)); - } - builder.append("]"); - return builder.toString(); - } - - public static String encodeRequest(WebSocketBindingRequest request) { - return gson.toJson(request); - } - - public static WebSocketBindingRequest decodeRequest(String jsonRequest) { - return gson.fromJson(jsonRequest, WebSocketBindingRequest.class); - } - - public static WebSocketBindingResponse decodeResponse(String operationResponse) { - return gson.fromJson(operationResponse, WebSocketBindingResponse.class); - } - - public static Object decodeResponsePayload(String payload, Class<?> returnType) { - return gson.fromJson(payload, returnType); - } - } diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JavascriptGenerator.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JavascriptGenerator.java new file mode 100644 index 0000000000..04faf0113d --- /dev/null +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JavascriptGenerator.java @@ -0,0 +1,99 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.binding.websocket.runtime;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.interfacedef.Operation;
+
+public class JavascriptGenerator {
+
+ private final static String CONTEXT = "this.WebsocketComponentContext";
+ private static final String LF = "\n";
+ private static StringBuilder builder = new StringBuilder();
+
+ public static void generateServiceProxy(String component, String service, List<Operation> operations, int port) {
+ if (builder.length() == 0) {
+ builder.append(CONTEXT).append("={};").append(LF);
+ }
+ builder.append("if(!" + CONTEXT + "." + component + ")" + CONTEXT + "." + component + "={};").append(LF);
+ builder.append(CONTEXT + "." + component + "." + service + "={};").append(LF);
+ for (Operation operation : operations) {
+ builder.append(
+ CONTEXT + "." + component + "." + service + "." + operation.getName() + "="
+ + generateFunctionHeader(operation)).append(LF);
+ builder.append(generateFunctionContent(port, component, service, operation)).append(LF);
+ builder.append("};").append(LF);
+ }
+ }
+
+ private static String generateFunctionHeader(Operation operation) {
+ String header = "function(";
+ for (int i = 0; i < operation.getInputType().getLogical().size(); i++) {
+ if (i > 0)
+ header += ",";
+ header += "p" + i;
+ }
+ header += ") {";
+ return header;
+ }
+
+ private static String generateFunctionContent(int port, String component, String service, Operation operation) {
+ String content = "sendMessage(" + port + ",'" + component + "." + service + "." + operation.getName() + "',[";
+ for (int i = 0; i < operation.getInputType().getLogical().size(); i++) {
+ if (i > 0)
+ content += ",";
+ content += "p" + i;
+ }
+ content += "]);";
+ return content;
+ }
+
+ public static String getServiceProxies() {
+ return builder.toString();
+ }
+
+ public static void clear() {
+ builder.setLength(0);
+ }
+
+ private JavascriptGenerator() {
+ }
+
+}
diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JavascriptResourceServlet.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JavascriptResourceServlet.java new file mode 100644 index 0000000000..def2783a81 --- /dev/null +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/JavascriptResourceServlet.java @@ -0,0 +1,109 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.binding.websocket.runtime;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class JavascriptResourceServlet extends HttpServlet {
+
+ private static final String JSON_PLUGIN_PATH = "js/jquery.json-2.2.min.js";
+ private static final String WEBSOCKET_TOOLKIT_PATH = "js/TuscanyWebsocketToolkit.js";
+
+ private String jsonPlugin;
+ private String websocketToolkit;
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
+ try {
+ resp.setContentType("text/javascript");
+ OutputStream os = resp.getOutputStream();
+ os.write(getJsonPlugin().getBytes());
+ os.write("var Tuscany = new function() {\n".getBytes());
+ os.write(getWebsocketToolkit().getBytes());
+ os.write(JavascriptGenerator.getServiceProxies().getBytes());
+ os.write("}\n".getBytes());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String getJsonPlugin() {
+ if (jsonPlugin == null) {
+ jsonPlugin = getResource(JSON_PLUGIN_PATH);
+ }
+ return jsonPlugin;
+ }
+
+ private String getWebsocketToolkit() {
+ if (websocketToolkit == null) {
+ websocketToolkit = getResource(WEBSOCKET_TOOLKIT_PATH);
+ }
+ return websocketToolkit;
+ }
+
+ private String getResource(String path) {
+ InputStream is = getClass().getClassLoader().getResourceAsStream(path);
+ BufferedReader r = new BufferedReader(new InputStreamReader(is));
+ StringBuilder builder = new StringBuilder();
+ try {
+ String line = null;
+ while ((line = r.readLine()) != null) {
+ builder.append(line + "\n");
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ r.close();
+ } catch (IOException ignored) {
+ }
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/TuscanyWebSocket.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/TuscanyWebSocket.java new file mode 100644 index 0000000000..c267d9e6a4 --- /dev/null +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/TuscanyWebSocket.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.binding.websocket.runtime; + +import java.io.IOException; + +import org.eclipse.jetty.websocket.WebSocket; + +public class TuscanyWebSocket implements WebSocket, WebSocket.OnTextMessage { + + private Connection connection; + private WebSocketBindingDispatcher dispatcher; + + public TuscanyWebSocket(WebSocketBindingDispatcher dispatcher) { + this.dispatcher = dispatcher; + } + + @Override + public void onOpen(Connection connection) { + this.connection = connection; + } + + @Override + public void onMessage(String jsonRequest) { + WebSocketBindingMessage request = JSONUtil.decodeMessage(jsonRequest); + WebsocketServiceInvoker invoker = dispatcher.dispatch(request.getOperation()); + if (invoker == null) { + throw new RuntimeException("No operation found for " + request.getOperation()); + } else { + WebSocketBindingMessage response = invoker.invokeSync(request); + String jsonResponse = JSONUtil.encodeMessage(response); + try { + connection.sendMessage(jsonResponse); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + @Override + public void onClose(int closeCode, String message) { + } + +} diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketBindingRequest.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketBindingDispatcher.java index 19b875805a..4e0dbaffd5 100644 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketBindingRequest.java +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketBindingDispatcher.java @@ -18,40 +18,22 @@ */ package org.apache.tuscany.sca.binding.websocket.runtime; -public class WebSocketBindingRequest { +import java.util.HashMap; +import java.util.Map; - private String requestId; - private String uri; - private String payload; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; - public WebSocketBindingRequest(String requestId, String uri, String payload) { - this.requestId = requestId; - this.uri = uri; - this.payload = payload; - } +public class WebSocketBindingDispatcher { - public String getRequestId() { - return requestId; - } + private Map<String, WebsocketServiceInvoker> invokers = new HashMap<String, WebsocketServiceInvoker>(); - public void setRequestId(String requestId) { - this.requestId = requestId; + public void addOperation(String uri, RuntimeEndpoint endpoint, Operation operation) { + System.out.println("Adding " + uri); + invokers.put(uri, new WebsocketServiceInvoker(operation, endpoint)); } - public String getUri() { - return uri; + public WebsocketServiceInvoker dispatch(String uri) { + return invokers.get(uri); } - - public void setUri(String uri) { - this.uri = uri; - } - - public String getPayload() { - return payload; - } - - public void setPayload(String payload) { - this.payload = payload; - } - -} +}
\ No newline at end of file diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketBindingResponse.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketBindingMessage.java index 51664879a3..1ff8c4c10e 100644 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketBindingResponse.java +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketBindingMessage.java @@ -18,22 +18,22 @@ */ package org.apache.tuscany.sca.binding.websocket.runtime; -public class WebSocketBindingResponse { +public class WebSocketBindingMessage { - private String uri; + private String operation; private String payload; - public WebSocketBindingResponse(String uri, String payload) { - this.uri = uri; + public WebSocketBindingMessage(String operation, String payload) { + this.operation = operation; this.payload = payload; } - public String getUri() { - return uri; + public String getOperation() { + return operation; } - public void setUri(String uri) { - this.uri = uri; + public void setOperation(String operation) { + this.operation = operation; } public String getPayload() { diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketOperationDispatcher.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketOperationDispatcher.java deleted file mode 100644 index c33b3ca12a..0000000000 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketOperationDispatcher.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tuscany.sca.binding.websocket.runtime; - -import java.io.IOException; -import java.nio.channels.SocketChannel; -import java.util.HashMap; -import java.util.Map; - -import org.apache.tuscany.sca.interfacedef.Operation; -import org.apache.tuscany.sca.runtime.RuntimeEndpoint; -import org.apache.websocket.ServerWebSocket; -import org.apache.websocket.WebSocket; -import org.apache.websocket.WebSocketApplication; -import org.apache.websocket.WebSocketException; - -public class WebSocketOperationDispatcher implements WebSocketApplication<SocketChannel> { - - private ServerWebSocket server; - private Map<String, RuntimeEndpoint> endpoints = new HashMap<String, RuntimeEndpoint>(); - private Map<String, Operation> operations = new HashMap<String, Operation>(); - - public WebSocketOperationDispatcher(ServerWebSocket server) { - this.server = server; - } - - public void addOperation(String uri, RuntimeEndpoint endpoint, Operation operation) { - endpoints.put(uri, endpoint); - operations.put(uri, operation); - } - - public Operation getOperation(String uri) { - return operations.get(uri); - } - - public RuntimeEndpoint getEndpoint(String uri) { - return endpoints.get(uri); - } - - @Override - public void onConnection(WebSocket<SocketChannel> socket) { - // release server thread - new Thread(new WebSocketRequestHandler(socket, this)).start(); - } - - @Override - public void onHandshakeError(IOException e) { - throw new RuntimeException(e); - } - - @Override - public String acceptProtocol(String protocol) { - // don't accept any subprotocols - return null; - } - - @Override - public boolean acceptOrigin(String origin) { - // accept all clients - return true; - } - - @Override - public Map<String, String> acceptExtensions(Map<String, String> headers) throws WebSocketException { - // don't accept any extensions - return null; - } - - public void shutdown() { - try { - server.close(); - endpoints.clear(); - operations.clear(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - -}
\ No newline at end of file diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketRequestHandler.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketRequestHandler.java deleted file mode 100644 index 59d8af3133..0000000000 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketRequestHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tuscany.sca.binding.websocket.runtime; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.nio.channels.SocketChannel; - -import org.apache.tuscany.sca.interfacedef.Operation; -import org.apache.tuscany.sca.runtime.RuntimeEndpoint; -import org.apache.websocket.WebSocket; - -public class WebSocketRequestHandler implements Runnable { - - private WebSocket<SocketChannel> websocket; - private WebSocketOperationDispatcher dispatcher; - - public WebSocketRequestHandler(WebSocket<SocketChannel> socket, WebSocketOperationDispatcher dispatcher) { - this.websocket = socket; - this.dispatcher = dispatcher; - } - - @Override - public void run() { - while (true) { - try { - // TODO use Java NIO selectors on websockets - String request = websocket.receiveText(); - String response = handleRequest(request); - websocket.sendText(response); - } catch (IOException e) { - if (!websocket.isOpen()) { - System.out.println("Client disconnected. Stopping WebSocketRequestHandler."); - break; - } else { - throw new RuntimeException(e); - } - } - } - } - - // TODO handle request asynchronously in a background thread - private String handleRequest(String jsonRequest) { - WebSocketBindingRequest request = JSONUtil.decodeRequest(jsonRequest); - RuntimeEndpoint wire = dispatcher.getEndpoint(request.getUri()); - Operation operation = dispatcher.getOperation(request.getUri()); - System.out.println("handleRequest - " + request.getUri() + " - " + wire + " - " + operation); - String jsonParams = request.getPayload(); - Object[] args = JSONUtil.decodeJsonParamsForOperation(jsonParams, operation); - try { - Object operationResponse = wire.invoke(operation, args); - String payload = JSONUtil.encodeResponse(operationResponse); - WebSocketBindingResponse response = new WebSocketBindingResponse(request.getRequestId(), payload); - return JSONUtil.encodeResponse(response); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketServer.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketServer.java new file mode 100644 index 0000000000..e470ddfde0 --- /dev/null +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebSocketServer.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.binding.websocket.runtime; + +import java.net.URISyntaxException; + +import javax.servlet.http.HttpServletRequest; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.eclipse.jetty.websocket.WebSocket; +import org.eclipse.jetty.websocket.WebSocketHandler; + +public class WebSocketServer extends Server { + + private WebSocketBindingDispatcher dispatcher; + + public WebSocketServer(int port) throws URISyntaxException { + SelectChannelConnector connector = new SelectChannelConnector(); + connector.setPort(port); + addConnector(connector); + + setHandler(new WebSocketHandler() { + + @Override + public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { + System.out.println("Connection established"); + return new TuscanyWebSocket(dispatcher); + } + }); + + dispatcher = new WebSocketBindingDispatcher(); + } + + public WebSocketBindingDispatcher getDispatcher() { + return dispatcher; + } + +} diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketBindingProviderFactory.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketBindingProviderFactory.java index d7f8ef98a5..1f750234ae 100644 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketBindingProviderFactory.java +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketBindingProviderFactory.java @@ -21,6 +21,8 @@ package org.apache.tuscany.sca.binding.websocket.runtime; import org.apache.tuscany.sca.binding.websocket.WebsocketBinding;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.host.http.ServletHost;
+import org.apache.tuscany.sca.host.http.ServletHostHelper;
import org.apache.tuscany.sca.provider.BindingProviderFactory;
import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
import org.apache.tuscany.sca.provider.ServiceBindingProvider;
@@ -29,7 +31,10 @@ import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; public class WebsocketBindingProviderFactory implements BindingProviderFactory<WebsocketBinding> {
+ private ServletHost servletHost;
+
public WebsocketBindingProviderFactory(ExtensionPointRegistry extensionPoints) {
+ this.servletHost = ServletHostHelper.getServletHost(extensionPoints);
}
public Class<WebsocketBinding> getModelType() {
@@ -41,7 +46,7 @@ public class WebsocketBindingProviderFactory implements BindingProviderFactory<W }
public ServiceBindingProvider createServiceBindingProvider(RuntimeEndpoint endpoint) {
- return new WebsocketServiceBindingProvider(endpoint);
+ return new WebsocketServiceBindingProvider(endpoint, servletHost);
}
}
diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketReferenceBindingProvider.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketReferenceBindingProvider.java index d2e95f9623..4057e46956 100644 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketReferenceBindingProvider.java +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketReferenceBindingProvider.java @@ -41,7 +41,6 @@ public class WebsocketReferenceBindingProvider implements ReferenceBindingProvid }
public void stop() {
- WebsocketReferenceInvoker.shutdown();
}
public InterfaceContract getBindingInterfaceContract() {
diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketReferenceInvoker.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketReferenceInvoker.java index 84025491fe..65c9139a28 100644 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketReferenceInvoker.java +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketReferenceInvoker.java @@ -19,26 +19,13 @@ package org.apache.tuscany.sca.binding.websocket.runtime;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.channels.SocketChannel;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.Message;
-import org.apache.websocket.WebSocket;
-import org.apache.websocket.WebSocketConnector;
public class WebsocketReferenceInvoker implements Invoker {
- // TODO add timeout mechanism for persistent connections
- private static ConcurrentMap<String, WebSocket<SocketChannel>> persistentWebsockets = new ConcurrentHashMap<String, WebSocket<SocketChannel>>();
-
protected Operation operation;
protected EndpointReference endpoint;
@@ -48,58 +35,7 @@ public class WebsocketReferenceInvoker implements Invoker { }
public Message invoke(Message msg) {
- try {
- WebSocket<SocketChannel> websocket = initWebsocketConnection(endpoint.getBinding().getURI());
- return doInvoke(msg, websocket);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private WebSocket<SocketChannel> initWebsocketConnection(String uri) throws IOException, URISyntaxException {
- WebSocket<SocketChannel> websocket = null;
- synchronized (persistentWebsockets) {
- websocket = persistentWebsockets.get(uri);
- if (websocket == null) {
- WebSocketConnector connector = new WebSocketConnector();
- websocket = connector.connect(new URI(uri), null, "apache-tuscany", null);
- persistentWebsockets.put(uri, websocket);
- }
- }
- return websocket;
- }
-
- public Message doInvoke(Message msg, WebSocket<SocketChannel> websocket) throws IOException {
- String componentName = endpoint.getTargetEndpoint().getComponent().getName();
- String serviceName = endpoint.getTargetEndpoint().getService().getName();
- String operationName = operation.getName();
- String uri = componentName + "/" + serviceName + "/" + operationName;
- String payload = JSONUtil.encodeRequestParams((Object[]) msg.getBody());
- WebSocketBindingRequest request = new WebSocketBindingRequest(UUID.randomUUID().toString(), uri, payload);
-
- String operationResponse = invokeViaWebsocket(websocket, JSONUtil.encodeRequest(request));
-
- WebSocketBindingResponse response = JSONUtil.decodeResponse(operationResponse);
- Class<?> returnType = operation.getOutputType().getLogical().get(0).getPhysical();
- Object invocationResponse = JSONUtil.decodeResponsePayload(response.getPayload(), returnType);
- msg.setBody(invocationResponse);
- return msg;
- }
-
- private String invokeViaWebsocket(WebSocket<SocketChannel> websocket, String request) throws IOException {
- websocket.sendText(request);
- return websocket.receiveText();
- }
-
- public static void shutdown() {
- for (WebSocket<SocketChannel> websocket : persistentWebsockets.values()) {
- try {
- websocket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- persistentWebsockets.clear();
+ throw new RuntimeException("Not implemented yet");
}
}
diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketServiceBindingProvider.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketServiceBindingProvider.java index fe5efcffef..7f89a523c3 100644 --- a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketServiceBindingProvider.java +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketServiceBindingProvider.java @@ -19,65 +19,75 @@ package org.apache.tuscany.sca.binding.websocket.runtime;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
+import org.apache.tuscany.sca.binding.websocket.WebsocketBinding;
+import org.apache.tuscany.sca.host.http.ServletHost;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.provider.ServiceBindingProvider;
import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
-import org.apache.websocket.ServerWebSocket;
public class WebsocketServiceBindingProvider implements ServiceBindingProvider {
- private static Map<String, WebSocketOperationDispatcher> dispatchers = new HashMap<String, WebSocketOperationDispatcher>();
-
+ private static final String JAVASCRIPT_RESOURCE_PATH = "/org.apache.tuscany.sca.WebsocketComponentContext.js";
+ private static Map<Integer, WebSocketServer> servers = new HashMap<Integer, WebSocketServer>();
private RuntimeEndpoint endpoint;
+ private ServletHost servletHost;
- public WebsocketServiceBindingProvider(RuntimeEndpoint endpoint) {
+ public WebsocketServiceBindingProvider(RuntimeEndpoint endpoint, ServletHost servletHost) {
this.endpoint = endpoint;
+ this.servletHost = servletHost;
}
public void start() {
- String uri = endpoint.getBinding().getURI();
- WebSocketOperationDispatcher dispatcher = initDispatcherForURI(uri);
- String component = endpoint.getComponent().getName();
- String service = endpoint.getService().getName();
- for (Operation op : getBindingInterfaceContract().getInterface().getOperations()) {
- String operation = op.getName();
- dispatcher.addOperation(component + "/" + service + "/" + operation, endpoint, op);
+ WebsocketBinding binding = (WebsocketBinding) endpoint.getBinding();
+ int port = Integer.parseInt(binding.getPort());
+ try {
+ WebSocketServer server = initServerForURI(port);
+ String component = endpoint.getComponent().getName();
+ String service = endpoint.getService().getName();
+ for (Operation op : getBindingInterfaceContract().getInterface().getOperations()) {
+ String operation = op.getName();
+ server.getDispatcher().addOperation(component + "." + service + "." + operation, endpoint, op);
+ }
+ JavascriptGenerator.generateServiceProxy(component, service, getBindingInterfaceContract().getInterface()
+ .getOperations(), port);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
}
+ initJavascriptResource();
+ }
+ private WebSocketServer initServerForURI(int port) throws Exception {
+ WebSocketServer server = servers.get(port);
+ if (server == null) {
+ server = new WebSocketServer(port);
+ server.start();
+ servers.put(port, server);
+ }
+ return server;
}
- private WebSocketOperationDispatcher initDispatcherForURI(String uri) {
- WebSocketOperationDispatcher dispatcher = dispatchers.get(uri);
- if (dispatcher == null) {
- try {
- ServerWebSocket server = new ServerWebSocket(new URI(uri));
- System.out.println("Starting websocket server " + server + " at " + uri + "...");
- dispatcher = new WebSocketOperationDispatcher(server);
- System.out.println("Created new dispatcher for " + uri + " " + dispatcher);
- dispatchers.put(uri, dispatcher);
- server.register("/", dispatcher);
- new Thread(server).start();
- } catch (IOException e) {
- throw new RuntimeException(e);
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- }
+ private void initJavascriptResource() {
+ if (servletHost.getServletMapping(JAVASCRIPT_RESOURCE_PATH) == null) {
+ System.out.println("Adding javascript servlet");
+ servletHost.addServletMapping(JAVASCRIPT_RESOURCE_PATH, new JavascriptResourceServlet());
}
- return dispatcher;
}
public void stop() {
- for (WebSocketOperationDispatcher dispatcher : dispatchers.values()) {
- dispatcher.shutdown();
+ for (WebSocketServer server : servers.values()) {
+ try {
+ server.stop();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
- dispatchers.clear();
+ servers.clear();
+ servletHost.removeServletMapping(JAVASCRIPT_RESOURCE_PATH);
+ JavascriptGenerator.clear();
}
public InterfaceContract getBindingInterfaceContract() {
diff --git a/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketServiceInvoker.java b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketServiceInvoker.java new file mode 100644 index 0000000000..7615be916c --- /dev/null +++ b/sca-java-2.x/contrib/modules/binding-websocket/src/main/java/org/apache/tuscany/sca/binding/websocket/runtime/WebsocketServiceInvoker.java @@ -0,0 +1,73 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.binding.websocket.runtime;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+
+public class WebsocketServiceInvoker {
+
+ protected Operation operation;
+ protected RuntimeEndpoint endpoint;
+
+ public WebsocketServiceInvoker(Operation operation, RuntimeEndpoint endpoint) {
+ this.operation = operation;
+ this.endpoint = endpoint;
+ }
+
+ public WebSocketBindingMessage invokeSync(WebSocketBindingMessage request) {
+ String jsonParams = request.getPayload();
+ Object[] args = JSONUtil.decodePayloadForOperation(jsonParams, operation);
+ try {
+ Object operationResponse = endpoint.invoke(operation, args);
+ String payload = JSONUtil.encodePayload(operationResponse);
+ WebSocketBindingMessage response = new WebSocketBindingMessage(request.getOperation(), payload);
+ return response;
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void invokeAsync(WebSocketBindingMessage request, TuscanyWebSocket channel) {
+ // TODO add multiple response support
+ }
+
+}
|