summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding
diff options
context:
space:
mode:
authorantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2010-08-30 07:34:19 +0000
committerantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2010-08-30 07:34:19 +0000
commit4451293fe6378fda3b0953c7c2a8a7b0f049a368 (patch)
treedff16c03af7bf7263d81c7a9aaf1e4f4cc284708 /sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding
parentd33c0c2b7141ed9dbf02e01ff094e6b0342275da (diff)
Update the http binding to use default wireFormat and operationSelector that work as being discussed on the ML to expose arbitrary sca services as http endpoints. See http://apache.markmail.org/message/ix3vvyomronellmi
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@990712 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding')
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultOperationSelectorProviderFactory.java60
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultServiceOperationSelectorInterceptor.java85
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultWireFormatProviderFactory.java68
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultWireFormatServiceInterceptor.java229
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingServiceServlet.java53
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPContext.java46
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPGetListenerServlet.java94
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java74
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceListenerServlet.java85
9 files changed, 587 insertions, 207 deletions
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultOperationSelectorProviderFactory.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultOperationSelectorProviderFactory.java
new file mode 100644
index 0000000000..bf6ad75cd3
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultOperationSelectorProviderFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.http.format;
+
+import org.apache.tuscany.sca.binding.http.HTTPDefaultOperationSelector;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.Phase;
+import org.apache.tuscany.sca.provider.OperationSelectorProvider;
+import org.apache.tuscany.sca.provider.OperationSelectorProviderFactory;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+
+public class HTTPDefaultOperationSelectorProviderFactory implements OperationSelectorProviderFactory<HTTPDefaultOperationSelector>{
+
+ public HTTPDefaultOperationSelectorProviderFactory(ExtensionPointRegistry extensionPoints) {
+ }
+
+ @Override
+ public Class<HTTPDefaultOperationSelector> getModelType() {
+ return null;
+ }
+
+ @Override
+ public OperationSelectorProvider createReferenceOperationSelectorProvider(RuntimeEndpointReference endpointReference) {
+ return null;
+ }
+
+ @Override
+ public OperationSelectorProvider createServiceOperationSelectorProvider(final RuntimeEndpoint endpoint) {
+ return new OperationSelectorProvider(){
+ @Override
+ public Interceptor createInterceptor() {
+ return new HTTPDefaultServiceOperationSelectorInterceptor(endpoint);
+ }
+
+ @Override
+ public String getPhase() {
+ return Phase.SERVICE_BINDING_OPERATION_SELECTOR;
+ }};
+ }
+
+}
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultServiceOperationSelectorInterceptor.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultServiceOperationSelectorInterceptor.java
new file mode 100644
index 0000000000..dc4f37dbad
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultServiceOperationSelectorInterceptor.java
@@ -0,0 +1,85 @@
+/*
+ * 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.http.format;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tuscany.sca.binding.http.provider.HTTPContext;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Sets the operation based on the request path.
+ *
+ * From a url: http://localhost:8080/HelloworldComponent/Helloworld/sayHello?name=Petra
+ * where the component is HelloworldComponent and the service is Helloworld
+ * the path will be "/sayHello" so the operation is "sayHello".
+ *
+ * TODO: we could also do something similar to how the JMS binding supports
+ * a single "onMessage" method to get all requests, so perhaps this could
+ * also support impls with method: service(HttpServletRequest, HttpServletResponse)
+ */
+public class HTTPDefaultServiceOperationSelectorInterceptor implements Interceptor {
+
+ private Invoker next;
+ private List<Operation> operations;
+
+ public HTTPDefaultServiceOperationSelectorInterceptor(RuntimeEndpoint endpoint) {
+ Interface serviceInterface = endpoint.getService().getInterfaceContract().getInterface();
+ this.operations = serviceInterface.getOperations();
+ }
+
+ @Override
+ public Message invoke(Message msg) {
+ HTTPContext context = msg.getBindingContext();
+ HttpServletRequest request = context.getRequest();
+ String path = request.getPathInfo();
+ if (path.startsWith("/")) {
+ path = path.substring(1);
+ }
+
+ for (Operation op : operations) {
+ if (op.getName().equals(path)) {
+ msg.setOperation(op);
+ return next.invoke(msg);
+ }
+ }
+
+ throw new ServiceRuntimeException("No matching operation: " + path);
+ }
+
+ @Override
+ public void setNext(Invoker next) {
+ this.next = next;
+ }
+
+ @Override
+ public Invoker getNext() {
+ return next;
+ }
+
+}
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultWireFormatProviderFactory.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultWireFormatProviderFactory.java
new file mode 100644
index 0000000000..45e74d8ec8
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultWireFormatProviderFactory.java
@@ -0,0 +1,68 @@
+/*
+ * 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.http.format;
+
+import org.apache.tuscany.sca.binding.http.HTTPDefaultWireFormat;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.Phase;
+import org.apache.tuscany.sca.provider.WireFormatProvider;
+import org.apache.tuscany.sca.provider.WireFormatProviderFactory;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+
+public class HTTPDefaultWireFormatProviderFactory implements WireFormatProviderFactory<HTTPDefaultWireFormat> {
+
+ public HTTPDefaultWireFormatProviderFactory(ExtensionPointRegistry extensionPoints) {
+ }
+
+ @Override
+ public Class<HTTPDefaultWireFormat> getModelType() {
+ return null;
+ }
+
+ @Override
+ public WireFormatProvider createReferenceWireFormatProvider(RuntimeEndpointReference endpointReference) {
+ return null;
+ }
+
+ @Override
+ public WireFormatProvider createServiceWireFormatProvider(final RuntimeEndpoint endpoint) {
+ return new WireFormatProvider() {
+ @Override
+ public InterfaceContract configureWireFormatInterfaceContract(InterfaceContract interfaceContract) {
+ // TODO: Ideally this wants to set the databinding on a per request basis from the
+ // http content type and accept headers and so support things like json or xml etc,
+ // for now to get started just use json
+ interfaceContract.getInterface().resetDataBinding("JSON");
+ return interfaceContract;
+ }
+ @Override
+ public Interceptor createInterceptor() {
+ return new HTTPDefaultWireFormatServiceInterceptor(endpoint);
+ }
+ @Override
+ public String getPhase() {
+ return Phase.SERVICE_BINDING_WIREFORMAT;
+ }};
+ }
+
+}
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultWireFormatServiceInterceptor.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultWireFormatServiceInterceptor.java
new file mode 100644
index 0000000000..9a0c73e9b0
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPDefaultWireFormatServiceInterceptor.java
@@ -0,0 +1,229 @@
+/*
+ * 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.http.format;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tuscany.sca.binding.http.provider.HTTPContext;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Handles the default wire format for the http binding
+ *
+ * 1- determine the request and response format (xml, json, etc) from the
+ * binding config or content type header and accept headers
+ * - TODO: need a way to configure the databinding framework based on that format
+ * 2- get the request contents from the HttpServletRequest
+ * - for a post its just the request body
+ * - for a get need to convert the query string into a body based on the format (xml, json, etc)
+ * 3- send the request on down the wire
+ * 4- set the response contents in the HttpServletResponse
+ * (the databinding should already have put it in the correct format)
+ *
+ */
+public class HTTPDefaultWireFormatServiceInterceptor implements Interceptor {
+
+ private Invoker next;
+ private String jsonpCallbackName = "callback";
+
+ public HTTPDefaultWireFormatServiceInterceptor(RuntimeEndpoint endpoint) {
+ }
+
+ @Override
+ public void setNext(Invoker next) {
+ this.next = next;
+ }
+
+ @Override
+ public Invoker getNext() {
+ return next;
+ }
+
+ @Override
+ public Message invoke(Message msg) {
+ try {
+ return invokeResponse(getNext().invoke(invokeRequest(msg)));
+ } catch (IOException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ private Message invokeRequest(Message msg) throws IOException {
+ HTTPContext context = msg.getBindingContext();
+ HttpServletRequest servletRequest = context.getRequest();
+ if ("GET".equals(servletRequest.getMethod())) {
+ msg.setBody(getRequestFromQueryString(msg.getOperation(), servletRequest));
+ } else {
+ msg.setBody(read(servletRequest));
+ }
+ return msg;
+ }
+
+ private Message invokeResponse(Message msg) throws IOException {
+ HTTPContext context = msg.getBindingContext();
+ HttpServletRequest servletRequest = context.getRequest();
+ HttpServletResponse servletResponse = context.getResponse();
+
+ if (msg.isFault()) {
+ servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, String.valueOf(msg.getBody()));
+ } else {
+ String response = getResponseAsString(servletRequest, servletResponse, msg.getBody());
+ servletResponse.getOutputStream().println(response);
+ }
+
+ return msg;
+ }
+
+ /**
+ * Turn the request into a string array of JSON structures. The data binding
+ * layer will then convert each of the individual parameters into the appropriate
+ * types for the implementation interface
+ *
+ * From ML thread: http://apache.markmail.org/message/ix3vvyomronellmi
+ * 1- if the binding configuration contains a mapping from query parameter name to operation parameter then use that.
+ * 2- if the service interface or impl uses jaxrs annotations to name the parameters then use that mapping
+ * 3- if the query parameters are name arg0, arg1 etc than use those names for the mapping,
+ * 4- otherwise use the order in the query string.
+ */
+ protected Object[] getRequestFromQueryString(Operation operation, ServletRequest servletRequest) {
+
+ List<DataType> types = operation.getInputType().getLogical();
+ int typesIndex = 0;
+
+ List<String> jsonRequestArray = new ArrayList<String>();
+
+ for (String name : getOrderedParameterNames(servletRequest)) {
+ String jsonRequest = "";
+ // quote string parameters so clients work in the usual javascript way
+ if (typesIndex < types.size() && String.class.equals(types.get(typesIndex).getGenericType())) {
+ String x = servletRequest.getParameter(name);
+ if (x.startsWith("\"") || x.startsWith("'")) {
+ jsonRequest += x;
+ } else {
+ if (x.contains("\"")) {
+ jsonRequest += "'" + x + "'";
+ } else {
+ jsonRequest += "\"" + x + "\"";
+ }
+ }
+ } else {
+ jsonRequest += servletRequest.getParameter(name);
+ }
+ jsonRequestArray.add(jsonRequest);
+ }
+
+ return jsonRequestArray.toArray();
+ }
+
+ /**
+ * Get the request parameter names in the correct order.
+ * Either the query parameters are named arg0, arg1, arg2 etc or else use the order
+ * from the order in the query string. Eg, the url:
+ * http://localhost:8085/HelloWorldService/sayHello2?first=petra&last=arnold&callback=foo"
+ * should invoke:
+ * sayHello2("petra", "arnold")
+ * so the parameter names should be ordered: "first", "last"
+ */
+ protected List<String> getOrderedParameterNames(ServletRequest servletRequest) {
+ List<String> orderedNames = new ArrayList<String>();
+ Set<String> parameterNames = servletRequest.getParameterMap().keySet();
+ if (parameterNames.contains("arg0")) {
+ for (int i=0; i<parameterNames.size(); i++) {
+ String name = "arg" + i;
+ if (parameterNames.contains(name)) {
+ orderedNames.add(name);
+ } else {
+ break;
+ }
+ }
+ } else {
+ final String queryString = ((HttpServletRequest)servletRequest).getQueryString();
+ SortedSet<String> sortedNames = new TreeSet<String>(new Comparator<String>(){
+ public int compare(String o1, String o2) {
+ int i = queryString.indexOf(o1);
+ int j = queryString.indexOf(o2);
+ return i - j;
+ }});
+ for (String name : parameterNames) {
+ // ignore system and jsonpCallbackName parameters
+ if (!name.startsWith("_") && !name.equals(jsonpCallbackName)) {
+ sortedNames.add(name);
+ }
+ }
+ orderedNames.addAll(sortedNames);
+ }
+ return orderedNames;
+ }
+
+ /**
+ * The databinding layer will have converted the return type into a JSON string so simply
+ * add wrap it for return.
+ */
+ protected String getResponseAsString(HttpServletRequest servletRequest, HttpServletResponse servletResponse, Object response) {
+ String jsonResponse = response.toString();
+
+ if ("GET".equals(servletRequest.getMethod())) {
+ // handle JSONP callback name padding
+ String callback = servletRequest.getParameter(jsonpCallbackName);
+ if (callback != null && callback.length() > 1) {
+ jsonResponse = callback + "(" + jsonResponse + ");";
+ }
+ }
+
+ return jsonResponse;
+ }
+
+ protected static String read(HttpServletRequest servletRequest) throws IOException {
+ InputStream is = servletRequest.getInputStream();
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(is));
+ StringBuffer sb = new StringBuffer();
+ String str;
+ while ((str = reader.readLine()) != null) {
+ sb.append(str);
+ }
+ return sb.toString();
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+}
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingServiceServlet.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingServiceServlet.java
new file mode 100644
index 0000000000..686032571e
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingServiceServlet.java
@@ -0,0 +1,53 @@
+/*
+ * 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.http.provider;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+
+public class HTTPBindingServiceServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ protected transient MessageFactory messageFactory;
+ protected transient RuntimeEndpoint wire;
+
+ public HTTPBindingServiceServlet(RuntimeEndpoint wire, MessageFactory messageFactory) {
+ this.wire = wire;
+ this.messageFactory = messageFactory;
+ }
+
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ HTTPContext bindingContext = new HTTPContext();
+ bindingContext.setRequest(request);
+ bindingContext.setResponse(response);
+ Message msg = messageFactory.createMessage();
+ msg.setBindingContext(bindingContext);
+ wire.invoke(msg);
+ }
+}
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPContext.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPContext.java
new file mode 100644
index 0000000000..0a49823f06
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPContext.java
@@ -0,0 +1,46 @@
+/*
+ * 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.http.provider;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Holder to pass servlet request and response between the Inteceptors
+ */
+public class HTTPContext {
+
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+
+ public HttpServletRequest getRequest() {
+ return request;
+ }
+ public void setRequest(HttpServletRequest request) {
+ this.request = request;
+ }
+ public HttpServletResponse getResponse() {
+ return response;
+ }
+ public void setResponse(HttpServletResponse response) {
+ this.response = response;
+ }
+
+}
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPGetListenerServlet.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPGetListenerServlet.java
deleted file mode 100644
index e20d420d49..0000000000
--- a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPGetListenerServlet.java
+++ /dev/null
@@ -1,94 +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.http.provider;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URLDecoder;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.tuscany.sca.invocation.Invoker;
-import org.apache.tuscany.sca.invocation.Message;
-import org.apache.tuscany.sca.invocation.MessageFactory;
-
-/**
- * Servlet responsible for dispatching HTTP GET requests to the
- * target component implementation.
- *
- * @version $Rev$ $Date$
- */
-public class HTTPGetListenerServlet extends HttpServlet {
- private static final long serialVersionUID = 2865466417329430610L;
-
- private MessageFactory messageFactory;
- private Invoker getInvoker;
-
- /**
- * Constructs a new HTTPServiceListenerServlet.
- */
- public HTTPGetListenerServlet(Invoker getInvoker, MessageFactory messageFactory) {
- this.getInvoker = getInvoker;
- this.messageFactory = messageFactory;
- }
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-
- // Get the request path
- String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8");
- if (path.length() ==0) {
-
- // Redirect to a URL ending with / to make relative hrefs work
- // relative to the served resource.
- response.sendRedirect(request.getRequestURL().append('/').toString());
- return;
- }
-
- // Invoke the get operation on the service implementation
- Message requestMessage = messageFactory.createMessage();
- String id = path.substring(1);
- requestMessage.setBody(new Object[] {id});
- Message responseMessage = getInvoker.invoke(requestMessage);
- if (responseMessage.isFault()) {
- throw new ServletException((Throwable)responseMessage.getBody());
- }
-
- // Write the response from the service implementation to the response
- // output stream
- InputStream is = (InputStream)responseMessage.getBody();
- OutputStream os = response.getOutputStream();
- byte[] buffer = new byte[2048];
- for (;;) {
- int n = is.read(buffer);
- if (n <= 0)
- break;
- os.write(buffer, 0, n);
- }
- os.flush();
- os.close();
-
- }
-
-}
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java
index 41981d2db5..e123c28e02 100644
--- a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java
@@ -22,6 +22,8 @@ package org.apache.tuscany.sca.binding.http.provider;
import javax.servlet.Servlet;
import org.apache.tuscany.sca.binding.http.HTTPBinding;
+import org.apache.tuscany.sca.binding.http.HTTPDefaultOperationSelector;
+import org.apache.tuscany.sca.binding.http.HTTPDefaultWireFormat;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.host.http.ServletHost;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
@@ -36,8 +38,6 @@ import org.apache.tuscany.sca.provider.OperationSelectorProviderFactory;
import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint;
import org.apache.tuscany.sca.provider.WireFormatProvider;
import org.apache.tuscany.sca.provider.WireFormatProviderFactory;
-import org.apache.tuscany.sca.runtime.RuntimeComponent;
-import org.apache.tuscany.sca.runtime.RuntimeComponentService;
import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
/**
@@ -49,17 +49,15 @@ public class HTTPServiceBindingProvider implements EndpointProvider {
private ExtensionPointRegistry extensionPoints;
private RuntimeEndpoint endpoint;
- private RuntimeComponent component;
- private RuntimeComponentService service;
- private InterfaceContract serviceContract;
private HTTPBinding binding;
private MessageFactory messageFactory;
-
private OperationSelectorProvider osProvider;
private WireFormatProvider wfProvider;
-
private ServletHost servletHost;
private String servletMapping;
+ private InterfaceContract interfaceContract;
+ private boolean widget;
+
private HTTPBindingListenerServlet bindingListenerServlet;
public HTTPServiceBindingProvider(RuntimeEndpoint endpoint,
@@ -68,18 +66,24 @@ public class HTTPServiceBindingProvider implements EndpointProvider {
ServletHost servletHost) {
this.endpoint = endpoint;
- this.component = (RuntimeComponent)endpoint.getComponent();
- this.service = (RuntimeComponentService)endpoint.getService();
this.binding = (HTTPBinding)endpoint.getBinding();
+ this.widget = "Widget".equals(binding.getName());
this.extensionPoints = extensionPoints;
this.messageFactory = messageFactory;
this.servletHost = servletHost;
- // retrieve operation selector and wire format service providers
+ if (binding.getOperationSelector() == null && !widget) {
+ binding.setOperationSelector(new HTTPDefaultOperationSelector());
+ }
+ if (binding.getRequestWireFormat() == null && !widget) {
+ binding.setRequestWireFormat(new HTTPDefaultWireFormat());
+ }
+ if (binding.getResponseWireFormat() == null && !widget) {
+ binding.setResponseWireFormat(new HTTPDefaultWireFormat());
+ }
ProviderFactoryExtensionPoint providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class);
-
if (binding.getOperationSelector() != null) {
// Configure the interceptors for operation selection
@@ -97,23 +101,36 @@ public class HTTPServiceBindingProvider implements EndpointProvider {
}
}
-
-
//clone the service contract to avoid databinding issues
try {
- this.serviceContract = (InterfaceContract) service.getInterfaceContract().clone();
+ interfaceContract = (InterfaceContract)endpoint.getComponentServiceInterfaceContract().clone();
// configure data binding
if (this.wfProvider != null) {
- wfProvider.configureWireFormatInterfaceContract(service.getInterfaceContract());
+ wfProvider.configureWireFormatInterfaceContract(interfaceContract);
}
} catch(CloneNotSupportedException e) {
- this.serviceContract = service.getInterfaceContract();
+ // shouldn't happen
}
+ servletMapping = binding.getURI();
+ if (!servletMapping.endsWith("/")) {
+ servletMapping += "/";
+ }
+ if (!servletMapping.endsWith("*")) {
+ servletMapping += "*";
+ }
}
public void start() {
+ if (widget) {
+ start1x();
+ } else {
+ servletHost.addServletMapping(servletMapping, new HTTPBindingServiceServlet(endpoint, messageFactory));
+ }
+ }
+
+ public void start1x() {
// Get the invokers for the supported operations
Servlet servlet = null;
bindingListenerServlet = new HTTPBindingListenerServlet(binding, messageFactory );
@@ -122,39 +139,39 @@ public class HTTPServiceBindingProvider implements EndpointProvider {
String operationName = operation.getName();
if (operationName.equals("get")) {
Invoker getInvoker = invocationChain.getHeadInvoker();
- bindingListenerServlet.setGetInvoker(getInvoker);
+ bindingListenerServlet.setGetInvoker(getInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("conditionalGet")) {
Invoker conditionalGetInvoker = invocationChain.getHeadInvoker();
- bindingListenerServlet.setConditionalGetInvoker(conditionalGetInvoker);
+ bindingListenerServlet.setConditionalGetInvoker(conditionalGetInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("delete")) {
Invoker deleteInvoker = invocationChain.getHeadInvoker();
- bindingListenerServlet.setDeleteInvoker(deleteInvoker);
+ bindingListenerServlet.setDeleteInvoker(deleteInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("conditionalDelete")) {
Invoker conditionalDeleteInvoker = invocationChain.getHeadInvoker();
- bindingListenerServlet.setConditionalDeleteInvoker(conditionalDeleteInvoker);
+ bindingListenerServlet.setConditionalDeleteInvoker(conditionalDeleteInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("put")) {
Invoker putInvoker = invocationChain.getHeadInvoker();
- bindingListenerServlet.setPutInvoker(putInvoker);
+ bindingListenerServlet.setPutInvoker(putInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("conditionalPut")) {
Invoker conditionalPutInvoker = invocationChain.getHeadInvoker();
- bindingListenerServlet.setConditionalPutInvoker(conditionalPutInvoker);
+ bindingListenerServlet.setConditionalPutInvoker(conditionalPutInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("post")) {
Invoker postInvoker = invocationChain.getHeadInvoker();
- bindingListenerServlet.setPostInvoker(postInvoker);
+ bindingListenerServlet.setPostInvoker(postInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("conditionalPost")) {
Invoker conditionalPostInvoker = invocationChain.getHeadInvoker();
- bindingListenerServlet.setConditionalPostInvoker(conditionalPostInvoker);
+ bindingListenerServlet.setConditionalPostInvoker(conditionalPostInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("service")) {
Invoker serviceInvoker = invocationChain.getHeadInvoker();
- servlet = new HTTPServiceListenerServlet(binding, serviceInvoker, messageFactory);
+// servlet = new HTTPServiceListenerServlet(binding, serviceInvoker, messageFactory);
break;
}
}
@@ -174,14 +191,13 @@ public class HTTPServiceBindingProvider implements EndpointProvider {
servletHost.addServletMapping(servletMapping, servlet);
}
-
+
public void stop() {
- // Unregister the Servlet from the Servlet host
servletHost.removeServletMapping(servletMapping);
}
public InterfaceContract getBindingInterfaceContract() {
- return service.getInterfaceContract();
+ return interfaceContract;
}
public boolean supportsOneWayInvocation() {
@@ -192,6 +208,8 @@ public class HTTPServiceBindingProvider implements EndpointProvider {
* Add specific http interceptor to invocation chain
*/
public void configure() {
+
+ if (widget) return;
InvocationChain bindingChain = endpoint.getBindingInvocationChain();
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceListenerServlet.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceListenerServlet.java
deleted file mode 100644
index f752dce3e1..0000000000
--- a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceListenerServlet.java
+++ /dev/null
@@ -1,85 +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.http.provider;
-
-import java.io.IOException;
-
-import javax.servlet.Servlet;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.tuscany.sca.assembly.Binding;
-import org.apache.tuscany.sca.invocation.Invoker;
-import org.apache.tuscany.sca.invocation.Message;
-import org.apache.tuscany.sca.invocation.MessageFactory;
-
-/**
- * Servlet responsible for dispatching HTTP service requests to the
- * target component implementation.
- *
- * @version $Rev$ $Date$
- */
-public class HTTPServiceListenerServlet implements Servlet {
- transient private Binding binding;
- transient private ServletConfig config;
- transient private MessageFactory messageFactory;
- transient private Invoker serviceInvoker;
-
- /**
- * Constructs a new HTTPServiceListenerServlet.
- */
- public HTTPServiceListenerServlet(Binding binding, Invoker serviceInvoker, MessageFactory messageFactory) {
- this.binding = binding;
- this.serviceInvoker = serviceInvoker;
- this.messageFactory = messageFactory;
- }
-
- public ServletConfig getServletConfig() {
- return config;
- }
-
- public String getServletInfo() {
- return "";
- }
-
- public void init(ServletConfig config) throws ServletException {
- this.config = config;
- }
-
- public void destroy() {
-
- }
-
- public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
- // Dispatch the service interaction to the service invoker
- Message requestMessage = messageFactory.createMessage();
- requestMessage.setBody(new Object[]{request, response});
- Message responseMessage = serviceInvoker.invoke(requestMessage);
- if (responseMessage.isFault()) {
- // Turn a fault into an exception
- //throw new ServletException((Throwable)responseMessage.getBody());
- Throwable e = (Throwable)responseMessage.getBody();
- ((HttpServletResponse)response).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
- }
- }
-}