summaryrefslogtreecommitdiffstats
path: root/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider')
-rw-r--r--sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java45
-rw-r--r--sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java70
-rw-r--r--sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java70
-rw-r--r--sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java189
-rw-r--r--sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java318
-rw-r--r--sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JavaToSmd.java56
-rw-r--r--sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/ScaDomainScriptServlet.java114
7 files changed, 862 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java
new file mode 100644
index 0000000000..a9fff462fa
--- /dev/null
+++ b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java
@@ -0,0 +1,45 @@
+/*
+ * 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.jsonrpc.provider;
+
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+
+/**
+ * Invoker for the JSONRPC Binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCBindingInvoker implements Invoker {
+ Operation operation;
+ String uri;
+
+ public JSONRPCBindingInvoker(Operation operation, String uri) {
+ this.operation = operation;
+ this.uri = uri;
+ }
+
+ public Message invoke(Message msg) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java
new file mode 100644
index 0000000000..245eade7ad
--- /dev/null
+++ b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java
@@ -0,0 +1,70 @@
+/*
+ * 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.jsonrpc.provider;
+
+import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.host.http.ServletHost;
+import org.apache.tuscany.sca.host.http.ServletHostExtensionPoint;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.provider.BindingProviderFactory;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * JSON-RPC Provider Factory
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCBindingProviderFactory implements BindingProviderFactory<JSONRPCBinding> {
+
+ private MessageFactory messageFactory;
+ private ServletHost servletHost;
+
+ public JSONRPCBindingProviderFactory(ExtensionPointRegistry extensionPoints) {
+ ServletHostExtensionPoint servletHosts = extensionPoints.getExtensionPoint(ServletHostExtensionPoint.class);
+ this.servletHost = servletHosts.getServletHosts().get(0);
+
+ ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class);
+ messageFactory = modelFactories.getFactory(MessageFactory.class);
+ }
+
+ public ReferenceBindingProvider createReferenceBindingProvider(RuntimeComponent component,
+ RuntimeComponentReference reference,
+ JSONRPCBinding binding) {
+
+ return new JSONRPCReferenceBindingProvider(component, reference, binding);
+ }
+
+ public ServiceBindingProvider createServiceBindingProvider(RuntimeComponent component,
+ RuntimeComponentService service,
+ JSONRPCBinding binding) {
+ return new JSONRPCServiceBindingProvider(component, service, binding, messageFactory, servletHost);
+ }
+
+ public Class<JSONRPCBinding> getModelType() {
+ return JSONRPCBinding.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java
new file mode 100644
index 0000000000..e2528f59e5
--- /dev/null
+++ b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java
@@ -0,0 +1,70 @@
+/*
+ * 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.jsonrpc.provider;
+
+import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+
+/**
+ * Implementation of the JSONRPC Binding Provider for References
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCReferenceBindingProvider implements ReferenceBindingProvider {
+
+ private RuntimeComponentReference reference;
+ private JSONRPCBinding binding;
+
+ public JSONRPCReferenceBindingProvider(RuntimeComponent component,
+ RuntimeComponentReference reference,
+ JSONRPCBinding binding) {
+ this.reference = reference;
+ this.binding = binding;
+
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ return reference.getInterfaceContract();
+ }
+
+ public Invoker createInvoker(Operation operation) {
+ return new JSONRPCBindingInvoker(operation, binding.getURI());
+ }
+
+ public void start() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stop() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return false;
+ }
+
+}
diff --git a/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java
new file mode 100644
index 0000000000..909bd7bc19
--- /dev/null
+++ b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java
@@ -0,0 +1,189 @@
+/*
+ * 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.jsonrpc.provider;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding;
+import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding;
+import org.apache.tuscany.sca.databinding.json.JSONDataBinding;
+import org.apache.tuscany.sca.host.http.ServletHost;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * Implementation of the JSONRPC Binding Provider for Services
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCServiceBindingProvider implements ServiceBindingProvider {
+
+ // Path to the scaDomain.js script
+ // Note: this is the same as the Ajax binding to keep the client code
+ // the same for clients using either the ajax or jsonrpc binding
+ private static final String SCA_DOMAIN_SCRIPT = "/SCADomain/scaDomain.js";
+
+ private MessageFactory messageFactory;
+
+ private RuntimeComponent component;
+ private RuntimeComponentService service;
+ private InterfaceContract serviceContract;
+ private JSONRPCBinding binding;
+ private ServletHost servletHost;
+ private List<String> servletMappings = new ArrayList<String>();
+ private String domainScriptMapping;
+
+ public JSONRPCServiceBindingProvider(RuntimeComponent component,
+ RuntimeComponentService service,
+ JSONRPCBinding binding,
+ MessageFactory messageFactory,
+ ServletHost servletHost) {
+ this.component = component;
+ this.service = service;
+ this.binding = binding;
+ this.messageFactory = messageFactory;
+ this.servletHost = servletHost;
+
+ //clone the service contract to avoid databinding issues
+ try {
+ this.serviceContract = (InterfaceContract)service.getInterfaceContract().clone();
+ } catch(CloneNotSupportedException e) {
+ this.serviceContract = service.getInterfaceContract();
+ }
+
+ setDataBinding(serviceContract.getInterface());
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ return service.getInterfaceContract();
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return false;
+ }
+
+ public void start() {
+ // Set default databinding to json
+ serviceContract.getInterface().resetDataBinding(JSONDataBinding.NAME);
+
+ // Determine the service business interface
+ Class<?> serviceInterface = getTargetJavaClass(serviceContract.getInterface());
+
+ // Create a Java proxy to the target service
+ Object proxy = component.getComponentContext().createSelfReference(serviceInterface, service).getService();
+
+ // Create and register a Servlet for this service
+ JSONRPCServiceServlet serviceServlet =
+ new JSONRPCServiceServlet(messageFactory, binding, service, serviceContract, serviceInterface, proxy);
+ String mapping = binding.getURI();
+ if (!mapping.endsWith("/")) {
+ mapping += "/";
+ }
+ if (!mapping.endsWith("*")) {
+ mapping += "*";
+ }
+
+ servletHost.addServletMapping(mapping, serviceServlet);
+ servletMappings.add(mapping);
+ servletHost.addServletMapping(binding.getURI(), serviceServlet);
+ servletMappings.add(binding.getURI());
+
+ // Register service to scaDomain.js
+ int port;
+ URI uri = URI.create(servletHost.getURLMapping(binding.getURI()).toString());
+ port = uri.getPort();
+ if (port == -1) {
+ port = servletHost.getDefaultPort();
+ }
+
+ // get the ScaDomainScriptServlet, if it doesn't yet exist create one
+ // this uses removeServletMapping / addServletMapping as there is no getServletMapping facility
+ domainScriptMapping = URI.create("http://localhost:" + port + SCA_DOMAIN_SCRIPT).toString();
+ ScaDomainScriptServlet scaDomainServlet =
+ (ScaDomainScriptServlet)servletHost.getServletMapping(domainScriptMapping);
+ if (scaDomainServlet == null) {
+ scaDomainServlet = new ScaDomainScriptServlet();
+ servletHost.addServletMapping(domainScriptMapping, scaDomainServlet);
+ }
+
+ // Add this service to the SCA Domain Script Servlet
+ scaDomainServlet.addService(binding.getName());
+ }
+
+ public void stop() {
+
+ // Remove the Servlet mappings we've added
+ for (String mapping: servletMappings) {
+ servletHost.removeServletMapping(mapping);
+ }
+
+ // Unregister the service from the SCA Domain Script Servlet
+ ScaDomainScriptServlet scaDomainServlet = (ScaDomainScriptServlet) servletHost.getServletMapping(domainScriptMapping);
+ if (scaDomainServlet != null) {
+ scaDomainServlet.removeService(binding.getName());
+
+ // Remove the Servlet if there's no more registered services
+ if (scaDomainServlet.getServiceNames().isEmpty()) {
+ servletHost.removeServletMapping(domainScriptMapping);
+ }
+ }
+
+ }
+
+ private Class<?> getTargetJavaClass(Interface targetInterface) {
+ // TODO: right now assume that the target is always a Java
+ // Implementation. Need to figure out how to generate Java
+ // Interface in cases where the target is not a Java Implementation
+ return ((JavaInterface)targetInterface).getJavaClass();
+ }
+
+ private void setDataBinding(Interface interfaze) {
+ List<Operation> operations = interfaze.getOperations();
+ for (Operation operation : operations) {
+ operation.setDataBinding(JSONDataBinding.NAME);
+ DataType<List<DataType>> inputType = operation.getInputType();
+ if (inputType != null) {
+ List<DataType> logical = inputType.getLogical();
+ for (DataType inArg : logical) {
+ if (!SimpleJavaDataBinding.NAME.equals(inArg.getDataBinding())) {
+ inArg.setDataBinding(JSONDataBinding.NAME);
+ }
+ }
+ }
+ DataType outputType = operation.getOutputType();
+ if (outputType != null) {
+ if (!SimpleJavaDataBinding.NAME.equals(outputType.getDataBinding())) {
+ outputType.setDataBinding(JSONDataBinding.NAME);
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java
new file mode 100644
index 0000000000..4f6f5c6077
--- /dev/null
+++ b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java
@@ -0,0 +1,318 @@
+/*
+ * 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.jsonrpc.provider;
+
+import java.io.BufferedReader;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.osoa.sca.ServiceRuntimeException;
+
+import com.metaparadigm.jsonrpc.JSONRPCBridge;
+import com.metaparadigm.jsonrpc.JSONRPCResult;
+import com.metaparadigm.jsonrpc.JSONRPCServlet;
+
+/**
+ * Servlet that handles JSON-RPC requests invoking SCA services.
+ *
+ * There is an instance of this Servlet for each <binding.jsonrpc>
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCServiceServlet extends JSONRPCServlet {
+ private static final long serialVersionUID = 1L;
+
+ transient MessageFactory messageFactory;
+
+ transient Binding binding;
+ transient String serviceName;
+ transient Object serviceInstance;
+ transient RuntimeComponentService componentService;
+ transient InterfaceContract serviceContract;
+ transient Class<?> serviceInterface;
+
+ public JSONRPCServiceServlet(MessageFactory messageFactory,
+ Binding binding,
+ RuntimeComponentService componentService,
+ InterfaceContract serviceContract,
+ Class<?> serviceInterface,
+ Object serviceInstance) {
+ this.messageFactory = messageFactory;
+ this.binding = binding;
+ this.serviceName = binding.getName();
+ this.componentService = componentService;
+ this.serviceContract = serviceContract;
+ this.serviceInterface = serviceInterface;
+ this.serviceInstance = serviceInstance;
+ }
+
+ /**
+ * Override to do nothing as the JSONRPCServlet is setup by the
+ * service method in this class.
+ */
+ @Override
+ public void init(ServletConfig config) {
+ }
+
+ @Override
+ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ if ("smd".equals(request.getQueryString())) {
+ handleSMDRequest(request, response);
+ } else {
+ try {
+ handleServiceRequest(request, response);
+
+ } catch(RuntimeException re) {
+ if(re.getCause() instanceof javax.security.auth.login.LoginException) {
+ if (re.getCause() instanceof javax.security.auth.login.FailedLoginException) {
+ response.setHeader("WWW-Authenticate", "BASIC realm=\"" + "ldap-realm" + "\"");
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }else {
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ }
+ }
+ } finally {
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ session.removeAttribute("JSONRPCBridge");
+ }
+ }
+ }
+ }
+
+ private void handleServiceRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ // Encode using UTF-8, although We are actually ASCII clean as
+ // all unicode data is JSON escaped using backslash u. This is
+ // less data efficient for foreign character sets but it is
+ // needed to support naughty browsers such as Konqueror and Safari
+ // which do not honour the charset set in the response
+ response.setContentType("text/plain;charset=utf-8");
+ OutputStream out = response.getOutputStream();
+
+ // Decode using the charset in the request if it exists otherwise
+ // use UTF-8 as this is what all browser implementations use.
+ // The JSON-RPC-Java JavaScript client is ASCII clean so it
+ // although here we can correctly handle data from other clients
+ // that do not escape non ASCII data
+ String charset = request.getCharacterEncoding();
+ if (charset == null) {
+ charset = "UTF-8";
+ }
+ BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), charset));
+
+ // Read the request
+ CharArrayWriter data = new CharArrayWriter();
+ char[] buf = new char[4096];
+ int ret;
+ while ((ret = in.read(buf, 0, 4096)) != -1) {
+ data.write(buf, 0, ret);
+ }
+
+ JSONObject jsonReq = null;
+ String method = null;
+ try {
+ jsonReq = new JSONObject(data.toString());
+ method = jsonReq.getString("method");
+ } catch (Exception e) {
+ //FIXME Exceptions are not handled correctly here
+ // They should be reported to the client JavaScript as proper
+ // JavaScript exceptions.
+ throw new RuntimeException("Unable to parse request", e);
+ }
+
+
+ // check if it's a system request
+ // or a method invocation
+ byte[] bout;
+ if (method.startsWith("system.")) {
+ bout = handleJSONRPCSystemInvocation(request, response, data.toString());
+ } else {
+ bout = handleJSONRPCMethodInvocation(request, response, jsonReq);
+ }
+
+ // Send response to client
+ out.write(bout);
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * handles requests for the SMD descriptor for a service
+ */
+ protected void handleSMDRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, UnsupportedEncodingException {
+ String serviceUrl = request.getRequestURL().toString();
+ String smd = JavaToSmd.interfaceToSmd(serviceInterface, serviceUrl);
+
+ response.setContentType("text/plain;charset=utf-8");
+ OutputStream out = response.getOutputStream();
+ byte[] bout = smd.getBytes("UTF-8");
+ out.write(bout);
+ out.flush();
+ out.close();
+ }
+
+ protected byte[] handleJSONRPCSystemInvocation(HttpServletRequest request, HttpServletResponse response, String requestData) throws IOException,
+ UnsupportedEncodingException {
+ /*
+ * Create a new bridge for every request to avoid all the problems with
+ * JSON-RPC-Java storing the bridge in the session
+ */
+ HttpSession session = request.getSession();
+
+ JSONRPCBridge jsonrpcBridge = new JSONRPCBridge();
+ jsonrpcBridge.registerObject("Service", serviceInstance, serviceInterface);
+ session.setAttribute("JSONRPCBridge", jsonrpcBridge);
+
+ org.json.JSONObject jsonReq = null;
+ com.metaparadigm.jsonrpc.JSONRPCResult jsonResp = null;
+ try {
+ jsonReq = new org.json.JSONObject(requestData);
+ } catch (java.text.ParseException e) {
+ throw new RuntimeException("Unable to parse request", e);
+ }
+
+ String method = jsonReq.getString("method");
+ if ((method != null) && (method.indexOf('.') < 0)) {
+ jsonReq.putOpt("method", "Service" + "." + method);
+ }
+
+ // invoke the request
+ jsonResp = jsonrpcBridge.call(new Object[] {request}, jsonReq);
+
+ return jsonResp.toString().getBytes("UTF-8");
+ }
+
+ protected byte[] handleJSONRPCMethodInvocation(HttpServletRequest request, HttpServletResponse response, JSONObject jsonReq) throws IOException,
+ UnsupportedEncodingException {
+
+ String method = null;
+ Object[] args = null;
+ Object id = null;
+ try {
+ // Extract the method
+ method = jsonReq.getString("method");
+ if ((method != null) && (method.indexOf('.') < 0)) {
+ jsonReq.putOpt("method", "Service" + "." + method);
+ }
+
+ // Extract the arguments
+ JSONArray array = jsonReq.getJSONArray("params");
+ args = new Object[array.length()];
+ for (int i = 0; i < args.length; i++) {
+ args[i] = array.get(i);
+ }
+ id = jsonReq.get("id");
+
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to find json method name", e);
+ }
+
+ // invoke the request
+ RuntimeWire wire = componentService.getRuntimeWire(binding, serviceContract);
+ Operation jsonOperation = findOperation(method);
+ Object result = null;
+
+
+ // Invoke the get operation on the service implementation
+ Message requestMessage = messageFactory.createMessage();
+ requestMessage.setOperation(jsonOperation);
+
+ requestMessage.getHeaders().add(request);
+
+ requestMessage.setBody(args);
+
+ //result = wire.invoke(jsonOperation, args);
+ Message responseMessage = null;
+ try {
+ responseMessage = wire.getInvocationChain(jsonOperation).getHeadInvoker().invoke(requestMessage);
+ } catch (RuntimeException re) {
+ if (re.getCause() instanceof javax.security.auth.login.LoginException) {
+ throw re;
+ } else {
+ //some other exception
+ JSONRPCResult errorResult = new JSONRPCResult(JSONRPCResult.CODE_REMOTE_EXCEPTION, id, re);
+ return errorResult.toString().getBytes("UTF-8");
+ }
+ }
+
+ if (!responseMessage.isFault()) {
+ //successful execution of the invocation
+ try {
+ result = responseMessage.getBody();
+ JSONObject jsonResponse = new JSONObject();
+ jsonResponse.put("result", result);
+ jsonResponse.putOpt("id", id);
+ //get response to send to client
+ return jsonResponse.toString().getBytes("UTF-8");
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("Unable to create JSON response", e);
+ }
+ } else {
+ //exception thrown while executing the invocation
+ Throwable exception = (Throwable)responseMessage.getBody();
+ JSONRPCResult errorResult = new JSONRPCResult(JSONRPCResult.CODE_REMOTE_EXCEPTION, id, exception );
+ return errorResult.toString().getBytes("UTF-8");
+ }
+
+ }
+
+ /**
+ * Find the operation from the component service contract
+ * @param componentService
+ * @param method
+ * @return
+ */
+ private Operation findOperation(String method) {
+ if (method.contains(".")) {
+ method = method.substring(method.lastIndexOf(".") + 1);
+ }
+
+ List<Operation> operations = serviceContract.getInterface().getOperations();
+ //componentService.getBindingProvider(binding).getBindingInterfaceContract().getInterface().getOperations();
+
+
+ Operation result = null;
+ for (Operation o : operations) {
+ if (o.getName().equalsIgnoreCase(method)) {
+ result = o;
+ break;
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JavaToSmd.java b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JavaToSmd.java
new file mode 100644
index 0000000000..64339fda7b
--- /dev/null
+++ b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JavaToSmd.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.jsonrpc.provider;
+
+import java.lang.reflect.Method;
+
+/**
+ * Utility class to create a Simple Method Description (SMD) descriptor
+ * from a Java class. See http://dojo.jot.com/SMD.
+ *
+ * TODO: Change to work from the Tuscany Interface instead of a Java class
+ *
+ * @version $Rev$ $Date$
+ */
+class JavaToSmd {
+
+ static String interfaceToSmd(Class<?> klazz, String serviceUrl) {
+ String name = klazz.getSimpleName();
+ Method[] methods = klazz.getMethods();
+
+ StringBuffer smdSb = new StringBuffer();
+ smdSb.append("{\"SMDVersion\":\".1\",\"objectName\":\"" + name + "\",\"serviceType\":\"JSON-RPC\",\"serviceURL\":\""+ serviceUrl + "\",\"methods\":[");
+ for (int i = 0; i < methods.length; i++) {
+ if (i != 0) smdSb.append(",");
+ Class<?>[] params = methods[i].getParameterTypes();
+ smdSb.append("{\"name\":\""+methods[i].getName() + "\",\"parameters\":[");
+ for (int j = 0; j < params.length; j++) {
+ if (j != 0) smdSb.append(",");
+ // right now Dojo doesn't look at the type value, so we'll default it to STRING
+ // also, since we can't introspect the method parameter names we'll just create an incrementing parameter name
+ smdSb.append("{\"name\":\"param" + j + "\",\"type\":\"STRING\"}");
+ }
+ smdSb.append("]}");
+ }
+ smdSb.append("]}");
+
+ return smdSb.toString();
+ }
+
+}
diff --git a/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/ScaDomainScriptServlet.java b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/ScaDomainScriptServlet.java
new file mode 100644
index 0000000000..999588abf1
--- /dev/null
+++ b/sca-java-1.x/tags/1.6-TUSCANY-3909/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/ScaDomainScriptServlet.java
@@ -0,0 +1,114 @@
+/*
+ * 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.jsonrpc.provider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Servlet to handle requests for the scaDomain.js script.
+ *
+ * This script wrappers the JSON-RPC-Java jsonrpc.js script
+ * adding in at the bottom the JavaScript to create and initialize
+ * the variables representing the SCA services.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScaDomainScriptServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ protected transient List<String> serviceNames;
+
+ public ScaDomainScriptServlet() {
+ serviceNames = new ArrayList<String>();
+ }
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+
+ ServletOutputStream os = response.getOutputStream();
+
+ os.println();
+ os.println("/* Apache Tuscany scaDomain.js Header */");
+ os.println();
+
+ writeJSONRPCJavaScript(os);
+ writeScaDomainCode(os, request.getServletPath());
+ }
+
+ /**
+ * Creates a JavaScript variable within the scaDomain script for each SCA service and
+ * initializes its value with the JSON-RPC client to invoke the serverside service.
+ */
+ protected void writeScaDomainCode(ServletOutputStream out, String path) throws IOException {
+ out.println();
+ out.println("/* Apache Tuscany scaDomain.js Footer */");
+ out.println();
+ out.println("function scaDomain() {}");
+
+ // remove the leading slash '/' character
+ path = path.substring(1);
+
+ for (String serviceName : serviceNames) {
+ out.println();
+
+ // A slight hack to make the service function available with a variable named 'serviceName'
+ // to do that the JSONRpcClient is added to the scaDomain and then the service function is got from that
+ out.println("scaDomain." + serviceName + " = " + "new JSONRpcClient(\"" + serviceName + "\");");
+ out.println(serviceName + " = scaDomain." + serviceName + ".Service;");
+ }
+
+ out.println();
+ out.println("/** End of Apache Tuscany scaDomain.js */");
+ out.println();
+ }
+
+ /**
+ * Reads the jsonrpc.js script from the classpath and adds its contents to the output stream.
+ */
+ protected void writeJSONRPCJavaScript(ServletOutputStream os) throws IOException {
+ URL url = getClass().getResource("jsonrpc.js");
+ InputStream is = url.openStream();
+ int i;
+ while ((i = is.read()) != -1) {
+ os.write(i);
+ }
+ }
+
+ public void addService(String serviceName) {
+ serviceNames.add(serviceName);
+ }
+
+ public void removeService(String serviceName) {
+ serviceNames.remove(serviceName);
+ }
+
+ public List<String> getServiceNames() {
+ return serviceNames;
+ }
+
+}