summaryrefslogtreecommitdiffstats
path: root/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca
diff options
context:
space:
mode:
Diffstat (limited to 'tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca')
-rw-r--r--tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java147
-rw-r--r--tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java65
-rw-r--r--tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCClientInvoker.java74
-rw-r--r--tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCDatabindingHelper.java61
-rw-r--r--tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java107
-rw-r--r--tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java124
-rw-r--r--tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java314
-rw-r--r--tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JavaToSmd.java56
8 files changed, 948 insertions, 0 deletions
diff --git a/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java
new file mode 100644
index 0000000000..f3abf82520
--- /dev/null
+++ b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java
@@ -0,0 +1,147 @@
+/*
+ * 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.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.util.EntityUtils;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.DataExchangeSemantics;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+/**
+ * Invoker for the JSONRPC Binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCBindingInvoker implements Invoker, DataExchangeSemantics {
+ private EndpointReference endpointReference;
+ private Operation operation;
+ private String uri;
+
+ private HttpClient httpClient;
+
+ public JSONRPCBindingInvoker(EndpointReference endpointReference, Operation operation, HttpClient httpClient) {
+ this.endpointReference = endpointReference;
+ this.operation = operation;
+ this.uri = ((JSONRPCBinding) endpointReference.getBinding()).getURI();
+
+ this.httpClient = httpClient;
+ }
+
+ public Message invoke(Message msg) {
+ HttpPost post = null;
+ HttpResponse response = null;
+ try {
+
+ JSONObject jsonRequest = null;;
+ String requestId = "1";
+ Object[] args = null;
+ try {
+ // Extract the method
+ jsonRequest = new JSONObject();
+ jsonRequest.putOpt("method", "Service" + "." + msg.getOperation().getName());
+
+ // Extract the arguments
+ args = msg.getBody();
+ JSONArray array = new JSONArray();
+ for (int i = 0; i < args.length; i++) {
+ array.put(args[i]);
+ }
+ jsonRequest.putOpt("params", array);
+ jsonRequest.put("id", requestId);
+
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to parse JSON parameter", e);
+ }
+
+ post = new HttpPost(uri);
+ String req = jsonRequest.toString();
+ StringEntity entity = new StringEntity(req, "application/json; charset\"UTF-8\"");
+ post.setEntity(entity);
+
+ response = httpClient.execute(post);
+
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+ //success
+ JSONObject jsonResponse = null;
+ try {
+
+ jsonResponse = new JSONObject(EntityUtils.toString(response.getEntity()));
+
+ //check requestId
+ if (! jsonResponse.getString("id").equalsIgnoreCase(requestId)) {
+ throw new RuntimeException("Invalid response id:" + requestId );
+ }
+
+ msg.setBody(jsonResponse.get("result"));
+ } 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 response", e);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ msg.setFaultBody(e);
+ }
+
+ return msg;
+ }
+
+ private static JSONObject getJSONRequest(Message msg) {
+
+ JSONObject jsonRequest = null;;
+ Object[] args = null;
+ Object id = null;
+ try {
+ // Extract the method
+ jsonRequest = new JSONObject();
+ jsonRequest.putOpt("method", "Service" + "." + msg.getOperation().getName());
+
+ // Extract the arguments
+ args = msg.getBody();
+ JSONArray array = new JSONArray();
+ for (int i = 0; i < args.length; i++) {
+ array.put(args[i]);
+ }
+ jsonRequest.putOpt("params", array);
+ id = jsonRequest.put("id", "1");
+
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to parse JSON parameter", e);
+ }
+
+ return jsonRequest;
+ }
+
+ public boolean allowsPassByReference() {
+ return true;
+ }
+}
diff --git a/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java
new file mode 100644
index 0000000000..4059d5a1f0
--- /dev/null
+++ b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java
@@ -0,0 +1,65 @@
+/*
+ * 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.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+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;
+
+/**
+ * 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);
+
+ FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ messageFactory = modelFactories.getFactory(MessageFactory.class);
+ }
+
+ public ReferenceBindingProvider createReferenceBindingProvider(EndpointReference endpointReference) {
+
+ return new JSONRPCReferenceBindingProvider(endpointReference);
+ }
+
+ public ServiceBindingProvider createServiceBindingProvider(Endpoint endpoint) {
+ return new JSONRPCServiceBindingProvider(endpoint, messageFactory, servletHost);
+ }
+
+ public Class<JSONRPCBinding> getModelType() {
+ return JSONRPCBinding.class;
+ }
+
+}
diff --git a/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCClientInvoker.java b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCClientInvoker.java
new file mode 100644
index 0000000000..d25861b610
--- /dev/null
+++ b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCClientInvoker.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+import org.apache.http.client.HttpClient;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
+import org.apache.tuscany.sca.invocation.DataExchangeSemantics;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.jabsorb.client.Client;
+import org.jabsorb.client.Session;
+import org.jabsorb.client.TransportRegistry;
+
+/**
+ * Invoker for the JSONRPC Binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCClientInvoker implements Invoker, DataExchangeSemantics {
+ private EndpointReference endpointReference;
+ private Operation operation;
+ private Method method;
+ private String uri;
+
+ public JSONRPCClientInvoker(EndpointReference endpointReference, Operation operation, HttpClient httpClient) {
+ this.endpointReference = endpointReference;
+ this.operation = operation;
+ this.method = ((JavaOperation)operation).getJavaMethod();
+ this.uri = ((JSONRPCBinding)endpointReference.getBinding()).getURI();
+ }
+
+ public Message invoke(Message msg) {
+ Session session = TransportRegistry.i().createSession(uri);
+ Client client = new Client(session);
+ Object proxy = client.openProxy("", method.getDeclaringClass());
+
+ try {
+ Object result = client.invoke(proxy, method, (Object[])msg.getBody());
+ msg.setBody(result);
+ } catch (Exception e) {
+ msg.setFaultBody(e);
+ } finally {
+ client.closeProxy(proxy);
+ session.close();
+ }
+ return msg;
+ }
+
+ public boolean allowsPassByReference() {
+ return true;
+ }
+}
diff --git a/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCDatabindingHelper.java b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCDatabindingHelper.java
new file mode 100644
index 0000000000..3cdcb32830
--- /dev/null
+++ b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCDatabindingHelper.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.jsonrpc.provider;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding;
+import org.apache.tuscany.sca.databinding.json.JSONDataBinding;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.Operation;
+
+/**
+ * JSONRPC Binding helper class to handle setting the proper
+ * data binding in the interface contract for JSONRPC
+ * services and references
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCDatabindingHelper {
+
+ @SuppressWarnings("unchecked")
+ static 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/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java
new file mode 100644
index 0000000000..e5d24f1e1c
--- /dev/null
+++ b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java
@@ -0,0 +1,107 @@
+/*
+ * 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.http.HttpHost;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.protocol.HTTP;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+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.RuntimeComponentReference;
+
+/**
+ * Implementation of the JSONRPC Binding Provider for References
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSONRPCReferenceBindingProvider implements ReferenceBindingProvider {
+
+ private EndpointReference endpointReference;
+ private RuntimeComponentReference reference;
+ private InterfaceContract referenceContract;
+
+ private HttpClient httpClient;
+
+ public JSONRPCReferenceBindingProvider(EndpointReference endpointReference) {
+
+ this.endpointReference = endpointReference;
+ this.reference = (RuntimeComponentReference) endpointReference.getReference();
+
+ //clone the service contract to avoid databinding issues
+ /*
+ try {
+ this.referenceContract = (InterfaceContract)reference.getInterfaceContract().clone();
+ } catch(CloneNotSupportedException e) {
+ this.referenceContract = reference.getInterfaceContract();
+ }
+
+ JSONRPCDatabindingHelper.setDataBinding(referenceContract.getInterface());
+ */
+
+ // Create an HTTP client
+ HttpParams defaultParameters = new BasicHttpParams();
+ //defaultParameters.setIntParameter(HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 10);
+ HttpProtocolParams.setContentCharset(defaultParameters, HTTP.UTF_8);
+ HttpConnectionParams.setConnectionTimeout(defaultParameters, 60000);
+ HttpConnectionParams.setSoTimeout(defaultParameters, 60000);
+
+ SchemeRegistry supportedSchemes = new SchemeRegistry();
+ supportedSchemes.register(new Scheme(HttpHost.DEFAULT_SCHEME_NAME, PlainSocketFactory.getSocketFactory(), 80));
+
+ ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(defaultParameters, supportedSchemes);
+
+ httpClient = new DefaultHttpClient(connectionManager, defaultParameters);
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ //return referenceContract;
+ return reference.getInterfaceContract();
+ }
+
+ public Invoker createInvoker(Operation operation) {
+ return new JSONRPCClientInvoker(endpointReference, operation, httpClient);
+ }
+
+ public void start() {
+ // TODO Provide support for JSONRPC References
+ }
+
+ public void stop() {
+ // TODO Provide support for JSONRPC References
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return false;
+ }
+
+}
diff --git a/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java
new file mode 100644
index 0000000000..dca4965378
--- /dev/null
+++ b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java
@@ -0,0 +1,124 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding;
+import org.apache.tuscany.sca.databinding.json.JSONDataBinding;
+import org.apache.tuscany.sca.host.http.ServletHost;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+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 {
+ private MessageFactory messageFactory;
+
+ private Endpoint endpoint;
+ private RuntimeComponent component;
+ private RuntimeComponentService service;
+ private InterfaceContract serviceContract;
+ private JSONRPCBinding binding;
+ private ServletHost servletHost;
+ private List<String> servletMappings = new ArrayList<String>();
+
+ public JSONRPCServiceBindingProvider(Endpoint endpoint,
+ MessageFactory messageFactory,
+ ServletHost servletHost) {
+ this.endpoint = endpoint;
+ this.component = (RuntimeComponent)endpoint.getComponent();
+ this.service = (RuntimeComponentService)endpoint.getService();
+ this.binding = (JSONRPCBinding) endpoint.getBinding();
+ 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();
+ }
+
+ JSONRPCDatabindingHelper.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());
+ }
+
+ public void stop() {
+
+ // Remove the Servlet mappings we've added
+ for (String mapping: servletMappings) {
+ servletHost.removeServletMapping(mapping);
+ }
+
+ }
+
+ 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();
+ }
+}
diff --git a/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java
new file mode 100644
index 0000000000..71d335acc8
--- /dev/null
+++ b/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java
@@ -0,0 +1,314 @@
+/*
+ * 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.jabsorb.JSONRPCBridge;
+import org.jabsorb.JSONRPCResult;
+import org.jabsorb.JSONRPCServlet;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * 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) {
+ response.setHeader("WWW-Authenticate", "BASIC realm=\"" + "ldap-realm" + "\"");
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ } 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;
+ try {
+ if (method.startsWith("system.")) {
+ bout = handleJSONRPCSystemInvocation(request, response, data.toString());
+ } else {
+ bout = handleJSONRPCMethodInvocation(request, response, jsonReq);
+ }
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+
+ // 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, JSONException {
+ /*
+ * 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;
+ JSONRPCResult jsonResp = null;
+ jsonReq = new org.json.JSONObject(requestData);
+
+ 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/tags/java/sca/2.0-M4-RC3/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JavaToSmd.java b/tags/java/sca/2.0-M4-RC3/modules/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/tags/java/sca/2.0-M4-RC3/modules/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();
+ }
+
+}