summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2010-08-30 08:08:38 +0000
committerantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2010-08-30 08:08:38 +0000
commite8fbcbd2e96c5fe66ee9a47b53c6884cccb8dc6c (patch)
tree13f5f751f1aa4b725aa4468b9cbd93bacc7fe86c
parent8c2d8a9be1b4c591691edafcd966edf566831c30 (diff)
Start of the runtime code to support wireFormat.httpXml, still needs code to turn query parameters into xml
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@990723 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPXMLWireFormatProviderFactory.java70
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPXMLWireFormatServiceInterceptor.java225
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.WireFormatProviderFactory1
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/test/java/org/apache/tuscany/sca/binding/http/HelloworldTestCase.java8
-rw-r--r--sca-java-2.x/trunk/modules/binding-http-runtime/src/test/resources/helloworld.composite9
5 files changed, 313 insertions, 0 deletions
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPXMLWireFormatProviderFactory.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPXMLWireFormatProviderFactory.java
new file mode 100644
index 0000000000..cb60101bb7
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPXMLWireFormatProviderFactory.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.http.format;
+
+import org.apache.tuscany.sca.binding.http.HTTPXMLWireFormat;
+import org.apache.tuscany.sca.common.xml.dom.DOMHelper;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.databinding.xml.DOMDataBinding;
+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 HTTPXMLWireFormatProviderFactory implements WireFormatProviderFactory<HTTPXMLWireFormat> {
+
+ private DOMHelper domHelper;
+
+ public HTTPXMLWireFormatProviderFactory(ExtensionPointRegistry extensionPoints) {
+ this.domHelper = DOMHelper.getInstance(extensionPoints);
+ }
+
+ @Override
+ public Class<HTTPXMLWireFormat> 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) {
+ interfaceContract.getInterface().resetDataBinding(DOMDataBinding.NAME);
+ return interfaceContract;
+ }
+ @Override
+ public Interceptor createInterceptor() {
+ return new HTTPXMLWireFormatServiceInterceptor(endpoint, domHelper);
+ }
+ @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/HTTPXMLWireFormatServiceInterceptor.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPXMLWireFormatServiceInterceptor.java
new file mode 100644
index 0000000000..48768096c5
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/format/HTTPXMLWireFormatServiceInterceptor.java
@@ -0,0 +1,225 @@
+/*
+ * 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.common.xml.dom.DOMHelper;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.util.FaultException;
+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;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Handles the xml 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 HTTPXMLWireFormatServiceInterceptor implements Interceptor {
+
+ private Invoker next;
+ private String jsonpCallbackName = "callback";
+ private DOMHelper domHelper;
+
+ public HTTPXMLWireFormatServiceInterceptor(RuntimeEndpoint endpoint, DOMHelper domHelper) {
+ this.domHelper = domHelper;
+ }
+
+ @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();
+
+ Object o = msg.getBody();
+ if (msg.isFault()) {
+ String xml = domHelper.saveAsString((Node)((FaultException)o).getFaultInfo());
+ servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, xml);
+ } else {
+ String xml = "";
+ if (o instanceof Element) {
+ xml = domHelper.saveAsString((Node)o);
+ } else if ((o instanceof Object[]) && ((Object[])o)[0] instanceof Node) {
+ xml = domHelper.saveAsString((Node)((Object[])o)[0]);
+ } else if (o != null) {
+ throw new IllegalStateException("expecting Node payload: " + o);
+ }
+ servletResponse.getOutputStream().println(xml);
+ }
+
+ return msg;
+ }
+
+ /**
+ * Turn the query request into XML.
+ *
+ * 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();
+ return new Object[operation.getInputType().getLogical().size()];
+ }
+
+ /**
+ * 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;
+ }
+
+ 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/resources/META-INF/services/org.apache.tuscany.sca.provider.WireFormatProviderFactory b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.WireFormatProviderFactory
index f500a62c91..88cd59bb13 100644
--- a/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.WireFormatProviderFactory
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.WireFormatProviderFactory
@@ -16,3 +16,4 @@
# under the License.
org.apache.tuscany.sca.binding.http.format.HTTPDefaultWireFormatProviderFactory;model=org.apache.tuscany.sca.binding.http.HTTPDefaultWireFormat
+org.apache.tuscany.sca.binding.http.format.HTTPXMLWireFormatProviderFactory;model=org.apache.tuscany.sca.binding.http.HTTPXMLWireFormat
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/test/java/org/apache/tuscany/sca/binding/http/HelloworldTestCase.java b/sca-java-2.x/trunk/modules/binding-http-runtime/src/test/java/org/apache/tuscany/sca/binding/http/HelloworldTestCase.java
index cc3974cab6..c7f2403af6 100644
--- a/sca-java-2.x/trunk/modules/binding-http-runtime/src/test/java/org/apache/tuscany/sca/binding/http/HelloworldTestCase.java
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/test/java/org/apache/tuscany/sca/binding/http/HelloworldTestCase.java
@@ -65,6 +65,14 @@ public class HelloworldTestCase {
InputStream is = url.openStream();
Assert.assertEquals("\"Hello Petra\"", read(is));
}
+
+ @Test
+ public void testXml() throws Exception {
+ URL url = new URL("http://localhost:8080/HelloworldXmlComponent/Helloworld/sayHello?arg0=Petra");
+ InputStream is = url.openStream();
+ Assert.assertTrue(read(is).endsWith(">Hello null</return>"));
+ }
+
private static String read(InputStream is) throws IOException {
BufferedReader reader = null;
try {
diff --git a/sca-java-2.x/trunk/modules/binding-http-runtime/src/test/resources/helloworld.composite b/sca-java-2.x/trunk/modules/binding-http-runtime/src/test/resources/helloworld.composite
index 2430eba1ed..7497cfcbac 100644
--- a/sca-java-2.x/trunk/modules/binding-http-runtime/src/test/resources/helloworld.composite
+++ b/sca-java-2.x/trunk/modules/binding-http-runtime/src/test/resources/helloworld.composite
@@ -29,4 +29,13 @@
</service>
</component>
+ <component name="HelloworldXmlComponent">
+ <implementation.java class="org.apache.tuscany.sca.binding.http.HelloworldImpl"/>
+ <service name="Helloworld">
+ <tuscany:binding.http>
+ <tuscany:wireFormat.httpXml />
+ </tuscany:binding.http>
+ </service>
+ </component>
+
</composite>