You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by mi...@apache.org on 2008/06/25 20:41:27 UTC
svn commit: r671630 [1/2] - in /ode/trunk:
axis2/src/main/java/org/apache/ode/axis2/httpbinding/
axis2/src/main/java/org/apache/ode/axis2/soapbinding/
axis2/src/main/java/org/apache/ode/axis2/util/
axis2/src/test/java/org/apache/ode/axis2/httpbinding/ ...
Author: midon
Date: Wed Jun 25 11:41:26 2008
New Revision: 671630
URL: http://svn.apache.org/viewvc?rev=671630&view=rev
Log:
Merge branch 'tr_rest-connector' into trunk
Conflicts:
axis2/src/test/resources/http-binding-extensions.wsdl
axis2/src/test/resources/http-binding-validator.wsdl
Added:
ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
- copied, changed from r671620, ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java
ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java
- copied, changed from r671620, ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpClientHelperTest.java
Removed:
ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpClientHelperTest.java
Modified:
ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java
ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java
ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapExternalService.java
ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapMessageConverter.java
ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/URLEncodedTransformer.java
ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/UrlReplacementTransformer.java
ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlEncodedTransformerTest.java
ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlReplacementTransformerTest.java
ode/trunk/axis2/src/test/resources/http-binding-extensions.wsdl
ode/trunk/axis2/src/test/resources/http-binding-validator.wsdl
ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/Message.java
ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/MessageImpl.java
ode/trunk/utils/src/main/java/org/apache/ode/utils/wsdl/Messages.java
ode/trunk/utils/src/main/java/org/apache/ode/utils/wsdl/WsdlUtils.java
ode/trunk/utils/src/test/java/org/apache/ode/utils/wsdl/WsdlUtilsTest.java
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java Wed Jun 25 11:41:26 2008
@@ -26,8 +26,8 @@
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
-import javax.wsdl.extensions.http.HTTPBinding;
import javax.wsdl.extensions.http.HTTPOperation;
+import javax.wsdl.extensions.mime.MIMEContent;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
@@ -76,8 +76,8 @@
BindingOutput output = bindingOperation.getBindingOutput();
- String outputContentType = WsdlUtils.getMimeContentType(output.getExtensibilityElements());
- if (!outputContentType.endsWith("text/xml")) {
+ MIMEContent outputContent = WsdlUtils.getMimeContent(output.getExtensibilityElements());
+ if (outputContent!=null && !outputContent.getType().endsWith("text/xml")) {
throw new IllegalArgumentException(httpMsgs.msgUnsupportedContentType(binding, bindingOperation));
}
@@ -87,7 +87,6 @@
}
BindingInput input = bindingOperation.getBindingInput();
- String inputContentType = WsdlUtils.getMimeContentType(input.getExtensibilityElements());
// multipartRelated not supported
if (WsdlUtils.useMimeMultipartRelated(input)) {
@@ -95,7 +94,9 @@
}
// only 2 content-types supported
- if (inputContentType != null) {
+ MIMEContent inputContent= WsdlUtils.getMimeContent(input.getExtensibilityElements());
+ if (inputContent != null) {
+ String inputContentType = inputContent.getType();
if (!inputContentType.endsWith("text/xml") && !PostMethod.FORM_URL_ENCODED_CONTENT_TYPE.equalsIgnoreCase(inputContentType)) {
throw new IllegalArgumentException(httpMsgs.msgUnsupportedContentType(binding, bindingOperation));
}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java Wed Jun 25 11:41:26 2008
@@ -25,6 +25,8 @@
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
+import org.apache.commons.httpclient.StatusLine;
+import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
@@ -36,6 +38,7 @@
import org.apache.commons.httpclient.params.HttpParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.commons.lang.StringUtils;
import org.apache.ode.axis2.Properties;
import org.apache.ode.axis2.util.URLEncodedTransformer;
import org.apache.ode.axis2.util.UrlReplacementTransformer;
@@ -45,6 +48,7 @@
import org.apache.ode.utils.wsdl.WsdlUtils;
import org.apache.ode.il.epr.MutableEndpoint;
import org.w3c.dom.Element;
+import org.w3c.dom.Document;
import javax.wsdl.Binding;
import javax.wsdl.BindingInput;
@@ -53,24 +57,19 @@
import javax.wsdl.Operation;
import javax.wsdl.Part;
import javax.wsdl.extensions.http.HTTPOperation;
+import javax.wsdl.extensions.mime.MIMEContent;
import javax.xml.namespace.QName;
import java.io.UnsupportedEncodingException;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HttpClientHelper {
- private static final String CONTENT_TYPE_TEXT_XML = "text/xml";
private static final Log log = LogFactory.getLog(HttpClientHelper.class);
- protected static final org.apache.ode.utils.wsdl.Messages msgs = Messages.getMessages(Messages.class);
- protected Binding binding;
-
- public HttpClientHelper(Binding binding) {
- this.binding = binding;
- }
-
public void configure(HostConfiguration hostConfig, HttpState state, URI targetURI, HttpParams params) throws URIException {
if (log.isDebugEnabled()) log.debug("Configuring http client...");
// proxy configuration
@@ -84,142 +83,101 @@
}
- public HttpMethod buildHttpMethod(PartnerRoleMessageExchange odeMex, HttpParams params) throws UnsupportedEncodingException {
- Operation operation = odeMex.getOperation();
- BindingOperation bindingOperation = binding.getBindingOperation(operation.getName(), operation.getInput().getName(), operation.getOutput().getName());
-
- // message to be sent
- Element message = odeMex.getRequest().getMessage();
- Message msgDef = operation.getInput().getMessage();
-
- // base url
- String url = ((MutableEndpoint) odeMex.getEndpointReference()).getUrl();
-
- // extract part values into a map and check that all parts are assigned a value
- Map<String, Element> partElements = extractPartElements(msgDef, message);
-
- // http method type
- // the operation may override the verb, this is an extension for RESTful BPEL
- String verb = WsdlUtils.resolveVerb(binding, bindingOperation);
-
- // build the http method itself
- HttpMethod method = prepareHttpMethod(bindingOperation, verb, partElements, url, params);
- return method;
- }
-
- protected Map<String, Element> extractPartElements(Message msgDef, Element message) {
- Map<String, Element> partValues = new HashMap<String, Element>();
- for (Iterator iterator = msgDef.getParts().values().iterator(); iterator.hasNext();) {
- Part part = (Part) iterator.next();
- Element partEl = DOMUtils.findChildByName(message, new QName(null, part.getName()));
- if (partEl == null)
- throw new IllegalArgumentException(msgs.msgOdeMessageMissingRequiredPart(part.getName()));
- partValues.put(part.getName(), partEl);
- }
- return partValues;
+ /**
+ * Parse and convert a HTTP status line into an aml element.
+ *
+ * @param statusLine
+ * @return
+ * @throws HttpException
+ * @see #statusLineToElement(org.w3c.dom.Document, org.apache.commons.httpclient.StatusLine)
+ */
+ public Element statusLineToElement(String statusLine) throws HttpException {
+ return statusLineToElement(new StatusLine(statusLine));
+ }
+
+ public Element statusLineToElement(StatusLine statusLine) {
+ return statusLineToElement(DOMUtils.newDocument(), statusLine);
}
/**
- * create and initialize the http method.
- * Http Headers that may been passed in the params are not set in this method.
- * Headers will be automatically set by HttpClient.
- * See usages of HostParams.DEFAULT_HEADERS
- * See org.apache.commons.httpclient.HttpMethodDirector#executeMethod(org.apache.commons.httpclient.HttpMethod)
+ * Convert a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1">HTTP status line</a> into an xml element like this:
+ * <p/>
+ * < Status-line>
+ * < HTTP-Version>HTTP/1.1< /HTTP-Version>
+ * < Status-Code>200< /Status-Code>
+ * < Reason-Phrase>Success - The action was successfully received, understood, and accepted< /Reason-Phrase>
+ * < /Status-line></br>
+ *
+ * @param statusLine - the {@link org.apache.commons.httpclient.StatusLine} instance to be converted
+ * @param doc - the document to use to create new nodes
+ * @return an Element
*/
- protected HttpMethod prepareHttpMethod(BindingOperation bindingOperation, String verb, Map<String, Element> partValues,
- final String rootUri, HttpParams params) throws UnsupportedEncodingException {
- if (log.isDebugEnabled()) log.debug("Preparing http request...");
- // convenience variables...
- BindingInput bindingInput = bindingOperation.getBindingInput();
- HTTPOperation httpOperation = (HTTPOperation) WsdlUtils.getOperationExtension(bindingOperation);
- String contentType = WsdlUtils.getMimeContentType(bindingInput.getExtensibilityElements());
- boolean useUrlEncoded = WsdlUtils.useUrlEncoded(bindingInput) || PostMethod.FORM_URL_ENCODED_CONTENT_TYPE.equalsIgnoreCase(contentType);
- boolean useUrlReplacement = WsdlUtils.useUrlReplacement(bindingInput);
-
- final UrlReplacementTransformer replacementTransformer = new UrlReplacementTransformer(partValues.keySet());
- final URLEncodedTransformer encodedTransformer = new URLEncodedTransformer();
-
- // the http method to be built and returned
- HttpMethod method = null;
- // the 4 elements the http method may be made of
- String relativeUri = httpOperation.getLocationURI();
- String queryPath = null;
- RequestEntity requestEntity = null;
- String encodedParams = null;
-
-
- if (useUrlReplacement) {
- // insert part values in the url
- relativeUri = replacementTransformer.transform(relativeUri, partValues);
- } else if (useUrlEncoded) {
- // encode part values
- encodedParams = encodedTransformer.transform(partValues);
- }
+ public Element statusLineToElement(Document doc, StatusLine statusLine) {
+ Element statusLineEl = doc.createElementNS(null, "Status-Line");
+ Element versionEl = doc.createElementNS(null, "HTTP-Version");
+ Element codeEl = doc.createElementNS(null, "Status-Code");
+ Element reasonEl = doc.createElementNS(null, "Reason-Phrase");
+
+ // wiring
+ doc.appendChild(statusLineEl);
+ statusLineEl.appendChild(versionEl);
+ statusLineEl.appendChild(codeEl);
+ statusLineEl.appendChild(reasonEl);
+
+ // values
+ versionEl.setTextContent(statusLine.getHttpVersion());
+ codeEl.setTextContent(String.valueOf(statusLine.getStatusCode()));
+ reasonEl.setTextContent(statusLine.getReasonPhrase());
- // http-client api is not really neat
- // something similar to the following would save some if/else manipulations.
- // But we have to deal with it as-is.
- //
- // method = new Method(verb);
- // method.setRequestEnity(..)
- // etc...
- if ("GET".equalsIgnoreCase(verb) || "DELETE".equalsIgnoreCase(verb)) {
- if ("GET".equalsIgnoreCase(verb)) {
- method = new GetMethod();
- } else if ("DELETE".equalsIgnoreCase(verb)) {
- method = new DeleteMethod();
- }
- if (useUrlEncoded) {
- queryPath = encodedParams;
- }
+ return statusLineEl;
+ }
- // Let http-client manage the redirection
- // see org.apache.commons.httpclient.params.HttpClientParams.MAX_REDIRECTS
- // default is 100
- method.setFollowRedirects(true);
- } else if ("POST".equalsIgnoreCase(verb) || "PUT".equalsIgnoreCase(verb)) {
-
- if ("POST".equalsIgnoreCase(verb)) {
- method = new PostMethod();
- } else if ("PUT".equalsIgnoreCase(verb)) {
- method = new PutMethod();
- }
+ /**
+ * Build a "details" element that looks like this:
+ *
+ * @param method
+ * @return
+ * @throws IOException
+ */
+ public Element prepareDetailsElement(HttpMethod method) throws IOException {
+ return prepareDetailsElement(method, true);
+ }
- // some body-building...
- if (useUrlEncoded) {
- requestEntity = new StringRequestEntity(encodedParams, PostMethod.FORM_URL_ENCODED_CONTENT_TYPE, method.getParams().getContentCharset());
- } else if (contentType.endsWith(CONTENT_TYPE_TEXT_XML)) {
- // assumption is made that there is a single part
- // validation steps in the constructor must warranty that
- Part part = (Part) bindingOperation.getOperation().getInput().getMessage().getParts().values().iterator().next();
- Element partValue = partValues.get(part.getName());
- // if the part has an element name, we must take the first element
- if (part.getElementName() != null) {
- partValue = DOMUtils.getFirstChildElement(partValue);
+ /**
+ *
+ * @param method
+ * @param bodyIsXml if true the body will be parsed as xml else the body will be inserted as string
+ * @return
+ * @throws IOException
+ */
+ public Element prepareDetailsElement(HttpMethod method, boolean bodyIsXml) throws IOException {
+ Document doc = DOMUtils.newDocument();
+ Element detailsEl = doc.createElementNS(null, "details");
+ Element statusLineEl = statusLineToElement(doc, method.getStatusLine());
+ detailsEl.appendChild(statusLineEl);
+
+ // set the body if any
+ final InputStream bodyAsStream = method.getResponseBodyAsStream();
+ if (bodyAsStream != null) {
+ Element bodyEl = doc.createElementNS(null, "responseBody");
+ detailsEl.appendChild(bodyEl);
+ // first, try to parse the body as xml
+ // if it fails, put it as string in the body element
+ boolean exceptionDuringParsing = false;
+ if (bodyIsXml) {
+ try {
+ Element parsedBodyEl = DOMUtils.parse(bodyAsStream).getDocumentElement();
+ bodyEl.appendChild(parsedBodyEl);
+ } catch (Exception e) {
+ String errmsg = "Unable to parse the response body as xml. Body will be inserted as string.";
+ if (log.isDebugEnabled()) log.debug(errmsg, e);
+ exceptionDuringParsing = true;
}
- String xmlString = DOMUtils.domToString(partValue);
- requestEntity = new ByteArrayRequestEntity(xmlString.getBytes(), contentType);
- } else {
- // should not happen because of HttpBindingValidator, but never say never
- throw new IllegalArgumentException("Unsupported content-type!");
}
-
- // cast safely, PUT and POST are subclasses of EntityEnclosingMethod
- final EntityEnclosingMethod enclosingMethod = (EntityEnclosingMethod) method;
- enclosingMethod.setRequestEntity(requestEntity);
- enclosingMethod.setContentChunked(params.getBooleanParameter(Properties.PROP_HTTP_REQUEST_CHUNK, false));
-
- } else {
- // should not happen because of HttpBindingValidator, but never say never
- throw new IllegalArgumentException("Unsupported HTTP method: " + verb);
+ if (!bodyIsXml || exceptionDuringParsing) {
+ bodyEl.setTextContent(method.getResponseBodyAsString());
+ }
}
-
- // link params together
- method.getParams().setDefaults(params);
-
- String completeUri = rootUri + (rootUri.endsWith("/") || relativeUri.startsWith("/") ? "" : "/") + relativeUri;
- method.setPath(completeUri); // assumes that the path is properly encoded (URL safe).
- method.setQueryString(queryPath);
- return method;
+ return detailsEl;
}
}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java Wed Jun 25 11:41:26 2008
@@ -29,36 +29,36 @@
import org.apache.ode.axis2.ExternalService;
import org.apache.ode.axis2.ODEService;
import org.apache.ode.axis2.Properties;
-import org.apache.ode.il.epr.EndpointFactory;
-import org.apache.ode.il.epr.WSAEndpoint;
import org.apache.ode.bpel.iapi.BpelServer;
import org.apache.ode.bpel.iapi.EndpointReference;
+import org.apache.ode.bpel.iapi.Message;
import org.apache.ode.bpel.iapi.MessageExchange;
import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
-import org.apache.ode.bpel.iapi.Scheduler;
import org.apache.ode.bpel.iapi.ProcessConf;
+import org.apache.ode.il.epr.EndpointFactory;
+import org.apache.ode.il.epr.WSAEndpoint;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.Namespaces;
import org.apache.ode.utils.wsdl.Messages;
import org.apache.ode.utils.wsdl.WsdlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import org.w3c.dom.Node;
import javax.wsdl.Binding;
+import javax.wsdl.BindingOperation;
import javax.wsdl.Definition;
+import javax.wsdl.Fault;
import javax.wsdl.Operation;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.Service;
+import javax.wsdl.extensions.mime.MIMEContent;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
-import java.util.HashMap;
import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
/**
@@ -73,27 +73,32 @@
protected BpelServer server;
protected ProcessConf pconf;
+ private String targetNamespace;
protected QName serviceName;
protected String portName;
- protected HttpClientHelper clientHelper;
+ protected HttpClientHelper helper;
+ protected HttpMethodConverter httpMethodConverter;
protected WSAEndpoint endpointReference;
+ protected Binding portBinding;
+
public HttpExternalService(ProcessConf pconf, QName serviceName, String portName, BpelServer server) {
this.portName = portName;
this.serviceName = serviceName;
this.server = server;
+ this.pconf = pconf;
- this.pconf= pconf;
- Definition definition = pconf.getDefinitionForService(serviceName);
+ Definition definition = pconf.getDefinitionForService(serviceName);
+ targetNamespace = definition.getTargetNamespace();
Service serviceDef = definition.getService(serviceName);
if (serviceDef == null)
throw new IllegalArgumentException(msgs.msgServiceDefinitionNotFound(serviceName));
Port port = serviceDef.getPort(portName);
if (port == null)
throw new IllegalArgumentException(msgs.msgPortDefinitionNotFound(serviceName, portName));
- Binding binding = port.getBinding();
- if (binding == null)
+ portBinding = port.getBinding();
+ if (portBinding == null)
throw new IllegalArgumentException(msgs.msgBindingNotFound(portName));
// validate the http binding
@@ -101,7 +106,7 @@
throw new IllegalArgumentException(msgs.msgNoHTTPBindingForPort(portName));
}
// throws an IllegalArgumentException if not valid
- new HttpBindingValidator(binding).validate();
+ new HttpBindingValidator(portBinding).validate();
// initial endpoint reference
Element eprElmt = ODEService.genEPRfromWSDL(definition, serviceName, portName);
@@ -109,7 +114,8 @@
throw new IllegalArgumentException(msgs.msgPortDefinitionNotFound(serviceName, portName));
endpointReference = EndpointFactory.convertToWSA(ODEService.createServiceRef(eprElmt));
- clientHelper = new HttpClientHelper(binding);
+ httpMethodConverter = new HttpMethodConverter(portBinding);
+ helper = new HttpClientHelper();
connections = new MultiThreadedHttpConnectionManager();
}
@@ -137,27 +143,28 @@
final HttpParams params = Properties.HttpClient.translate(properties);
// build the http method
- final HttpMethod method = clientHelper.buildHttpMethod(odeMex, params);
+ final HttpMethod method = httpMethodConverter.createHttpRequest(odeMex, params);
// create a client
HttpClient client = new HttpClient(connections);
- // don't forget to wire params so that IL properties are passed around
+ // don't forget to wire params so that EPR properties are passed around
client.getParams().setDefaults(params);
- clientHelper.configure(client.getHostConfiguration(),client.getState(), method.getURI(),params);
+ // configure the client (proxy, security, etc)
+ helper.configure(client.getHostConfiguration(), client.getState(), method.getURI(), params);
// this callable encapsulates the http method execution and the process of the response
final Callable executionCallable;
// execute it
- boolean isTwoWay = odeMex.getMessageExchangePattern() == org.apache.ode.bpel.iapi.MessageExchange.MessageExchangePattern.REQUEST_RESPONSE;
+ boolean isTwoWay = odeMex.getMessageExchangePattern() == MessageExchange.MessageExchangePattern.REQUEST_RESPONSE;
if (isTwoWay) {
// two way
- executionCallable = new HttpExternalService.TwoWayCallable(client, method, odeMex, odeMex.getOperation());
+ executionCallable = new HttpExternalService.TwoWayCallable(client, method, odeMex);
executionCallable.call();
} else {
// one way, just execute and forget
- executionCallable = new HttpExternalService.OneWayCallable(client, method, odeMex, odeMex.getOperation());
+ executionCallable = new HttpExternalService.OneWayCallable(client, method, odeMex);
executionCallable.call();
odeMex.replyOneWayOk();
}
@@ -181,13 +188,11 @@
private class OneWayCallable implements Callable<Void> {
HttpMethod method;
PartnerRoleMessageExchange odeMex;
- Operation operation;
- HttpClient client;
+ HttpClient client;
- public OneWayCallable(HttpClient client, HttpMethod method, PartnerRoleMessageExchange odeMex, Operation operation) {
+ public OneWayCallable(HttpClient client, HttpMethod method, PartnerRoleMessageExchange odeMex) {
this.method = method;
this.odeMex = odeMex;
- this.operation = operation;
this.client = client;
}
@@ -202,7 +207,7 @@
if (log.isDebugEnabled())
log.debug("Executing http request : " + method.getName() + " " + method.getURI());
final int statusCode = client.executeMethod(method);
- // invoke getResponseBody to force the loading of the body
+ // invoke getResponseBody to force the loading of the body
// Actually the processResponse may happen in a separate thread and
// as a result the connection might be closed before the body processing (see the finally clause below).
byte[] responseBody = method.getResponseBody();
@@ -229,31 +234,34 @@
try {
// log the URI since the engine may have moved on while this One Way request was executing
if (statusCode >= 400) {
- if (log.isWarnEnabled()) log.warn("OneWay http request ["+method.getURI()+"] failed with status: " + method.getStatusLine());
+ if (log.isWarnEnabled())
+ log.warn("OneWay http request [" + method.getURI() + "] failed with status: " + method.getStatusLine());
} else {
- if (log.isDebugEnabled()) log.debug("OneWay http request ["+method.getURI()+"] status: " + method.getStatusLine());
+ if (log.isDebugEnabled())
+ log.debug("OneWay http request [" + method.getURI() + "] status: " + method.getStatusLine());
}
} catch (URIException e) {
- if(log.isDebugEnabled()) log.debug(e);
+ if (log.isDebugEnabled()) log.debug(e);
}
}
}
private class TwoWayCallable extends OneWayCallable {
- public TwoWayCallable(HttpClient client, HttpMethod method, PartnerRoleMessageExchange odeMex, Operation operation) {
- super(client, method, odeMex, operation);
+
+ public TwoWayCallable(HttpClient client, HttpMethod method, PartnerRoleMessageExchange odeMex) {
+ super(client, method, odeMex);
}
public void processResponse(final int statusCode) {
try {
if (statusCode >= 200 && statusCode < 300) {
- success();
+ _2xx_success();
} else if (statusCode >= 300 && statusCode < 400) {
- redirection();
+ _3xx_redirection();
} else if (statusCode >= 400 && statusCode < 500) {
- badRequest();
+ _4xx_badRequest();
} else if (statusCode >= 500 && statusCode < 600) {
- serverError();
+ _5xx_serverError();
} else {
unmanagedStatus();
}
@@ -263,80 +271,137 @@
}
}
- private void unmanagedStatus() {
+ private void unmanagedStatus() throws IOException {
String errmsg = "Unmanaged Status Code! " + method.getStatusLine();
log.error(errmsg);
- odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method));
}
- private void serverError() {
- QName type = new QName(Namespaces.ODE_EXTENSION_NS, "HttpRemoteServerFault");
-
- Document odeMsg = DOMUtils.newDocument();
- Element odeMsgEl = odeMsg.createElementNS(null, "message");
- Element statusEl = odeMsg.createElementNS(null, "statusLine");
- statusEl.setTextContent(String.valueOf(method.getStatusLine()));
+ /**
+ * For 500s if a fault is defined in the WSDL and the response body contains the corresponding xml doc, then reply with a fault ; else reply with failure.
+ *
+ * @throws IOException
+ */
+ private void _5xx_serverError() throws IOException {
+ String errmsg = "Internal Server Error! " + method.getStatusLine();
+ log.error(errmsg);
- odeMsg.appendChild(odeMsgEl);
- odeMsgEl.appendChild(statusEl);
- org.apache.ode.bpel.iapi.Message response = odeMex.createMessage(type);
- response.setMessage(odeMsgEl);
+ Operation opDef = odeMex.getOperation();
+ BindingOperation opBinding = portBinding.getBindingOperation(opDef.getName(), opDef.getInput().getName(), opDef.getOutput().getName());
+ if (opDef.getFaults().isEmpty()) {
+ errmsg = "Operation has no fault. This 500 error will be considered as a failure.";
+ if (log.isDebugEnabled()) log.debug(errmsg);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method));
+ } else if (opBinding.getBindingFaults().isEmpty()) {
+ errmsg = "No fault binding. This 500 error will be considered as a failure.";
+ if (log.isDebugEnabled()) log.debug(errmsg);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method));
+ } else if (method.getResponseBodyAsStream() == null) {
+ errmsg = "No body in the response. This 500 error will be considered as a failure.";
+ if (log.isDebugEnabled()) log.debug(errmsg);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method));
+ } else {
+ final InputStream bodyAsStream = method.getResponseBodyAsStream();
+ try {
+ Element bodyEl = DOMUtils.parse(bodyAsStream).getDocumentElement();
+ QName bodyName = new QName(bodyEl.getNamespaceURI(), bodyEl.getNodeName());
+ Fault faultDef = WsdlUtils.inferFault(opDef, bodyName);
+
+ // is this fault bound with ODE extension?
+ if (!WsdlUtils.isOdeFault(opBinding.getBindingFault(faultDef.getName()))) {
+ errmsg = "Fault " + bodyName + " is not bound with " + new QName(Namespaces.ODE_HTTP_EXTENSION_NS, "fault") + ". This 500 error will be considered as a failure.";
+ if (log.isDebugEnabled()) log.debug(errmsg);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method));
+ } else {
+ Part partDef = (Part) faultDef.getMessage().getParts().values().iterator().next();
- log.error("Http Server Error! " + method.getStatusLine());
- odeMex.replyWithFault(type, response);
+ // build the element to be sent back
+ Document odeMsg = DOMUtils.newDocument();
+ Element odeMsgEl = odeMsg.createElementNS(null, "message");
+ Element partEl = odeMsgEl.getOwnerDocument().createElementNS(null, partDef.getName());
+ odeMsgEl.appendChild(partEl);
+ // import the response body
+ partEl.appendChild(odeMsgEl.getOwnerDocument().importNode(bodyEl, true));
+
+ QName faultType = new QName(targetNamespace, faultDef.getName());
+ Message response = odeMex.createMessage(faultType);
+ response.setMessage(odeMsgEl);
+
+ // extract and set headers
+ httpMethodConverter.extractHttpResponseHeaders(response, method, faultDef.getMessage(), opBinding.getBindingOutput());
+ // finally send the fault. We did it!
+ odeMex.replyWithFault(faultType, response);
+ }
+ } catch (Exception e) {
+ errmsg = "Unable to parse the response body as xml. This 500 error will be considered as a failure.";
+ if (log.isDebugEnabled()) log.debug(errmsg, e);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method, false));
+ }
+ }
}
- private void badRequest() {
+ private void _4xx_badRequest() throws IOException {
String errmsg = "Bad Request! " + method.getStatusLine();
log.error(errmsg);
- odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method));
}
- private void redirection() {
- String errmsg = "Redirections are not supported! " + method.getStatusLine();
+ private void _3xx_redirection() throws IOException {
+ String errmsg = "Redirections disabled! " + method.getStatusLine();
log.error(errmsg);
- odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method));
}
- private void success() {
+ private void _2xx_success() {
if (log.isDebugEnabled()) log.debug("Http Status Line=" + method.getStatusLine());
if (log.isDebugEnabled()) log.debug("Received response for MEX " + odeMex);
+
+ Operation opDef = odeMex.getOperation();
+ BindingOperation opBinding = portBinding.getBindingOperation(opDef.getName(), opDef.getInput().getName(), opDef.getOutput().getName());
+
+ // assumption is made that a response may have at most one body. HttpBindingValidator checks this.
+ MIMEContent outputContent = WsdlUtils.getMimeContent(opBinding.getBindingOutput().getExtensibilityElements());
+ boolean isBodyMandatory = outputContent != null && !outputContent.getType().endsWith("text/xml");
+
try {
final InputStream bodyAsStream = method.getResponseBodyAsStream();
- if (bodyAsStream == null) {
- String errmsg = "Request body of a Two-way message may be empty! Msg Id=" + odeMex.getMessageExchangeId();
+ if (isBodyMandatory && bodyAsStream == null) {
+ String errmsg = "Response body is mandatory but missing! Msg Id=" + odeMex.getMessageExchangeId();
log.error(errmsg);
odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
- return;
} else {
- // only text/xml is supported in the response body
- // parse the body
- Element bodyElement;
- try {
- bodyElement = DOMUtils.parse(bodyAsStream).getDocumentElement();
- } catch (Exception e) {
- String errmsg = "Unable to parse the request body : " + e.getMessage();
- log.error(errmsg, e);
- odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, null);
- return;
- }
- try {
- org.apache.ode.bpel.iapi.Message odeResponse = odeMex.createMessage(odeMex.getOperation().getOutput().getMessage().getQName());
-
- // we expect a single part per output message
- // see org.apache.ode.axis2.httpbinding.HttpBindingValidator call in constructor
- Part part = (Part) operation.getOutput().getMessage().getParts().values().iterator().next();
+ javax.wsdl.Message outputMessage = odeMex.getOperation().getOutput().getMessage();
+ Message odeResponse = odeMex.createMessage(outputMessage.getQName());
- Element partElement = processBodyElement(part, bodyElement);
- odeResponse.setPart(part.getName(), partElement);
+ // handle the body if any
+ if (bodyAsStream != null) {
+ // only text/xml is supported in the response body
+ try {
+ Element bodyElement = DOMUtils.parse(bodyAsStream).getDocumentElement();
+ // we expect a single part per output message
+ // see org.apache.ode.axis2.httpbinding.HttpBindingValidator call in constructor
+ Part part = (Part) outputMessage.getParts().values().iterator().next();
+ Element partElement = httpMethodConverter.createPartElement(part, bodyElement);
+ odeResponse.setPart(part.getName(), partElement);
+ } catch (Exception e) {
+ String errmsg = "Unable to parse the response body: " + e.getMessage();
+ log.error(errmsg, e);
+ odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, null);
+ return;
+ }
+ }
+ // handle headers
+ httpMethodConverter.extractHttpResponseHeaders(odeResponse, method, outputMessage, opBinding.getBindingOutput());
+
+ try {
if (log.isInfoEnabled())
log.info("Response:\n" + DOMUtils.domToString(odeResponse.getMessage()));
odeMex.reply(odeResponse);
} catch (Exception ex) {
String errmsg = "Unable to process response: " + ex.getMessage();
log.error(errmsg, ex);
- odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, bodyElement);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, helper.prepareDetailsElement(method));
}
}
} catch (IOException e) {
@@ -345,48 +410,6 @@
odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, null);
}
}
-
- /**
- * Create the element to be inserted into org.apache.ode.bpel.iapi.Message.
- * If the part has a non-null element name, the bodyElement is simply appended.
- * Else if the bodyElement has a text content, the value is set to the message.
- * Else append all nodes of bodyElement to the returned element. Attributes are ignored.
- * <p/>
- * The name of the returned element is the part name.
- *
- * @param part
- * @param bodyElement
- * @return the element to insert "as is" to ODE message
- */
- private Element processBodyElement(Part part, Element bodyElement) {
- Document doc = DOMUtils.newDocument();
- Element partElement = doc.createElementNS(null, part.getName());
- if (part.getElementName() != null) {
- partElement.appendChild(doc.importNode(bodyElement, true));
- } else {
- if (DOMUtils.isEmptyElement(bodyElement)) {
- // Append an empty text node.
- // Warning! setting an empty string with setTextContent has not effect. See javadoc.
- partElement.appendChild(doc.createTextNode(""));
- } else {
- String textContent = DOMUtils.getTextContent(bodyElement);
- if (textContent != null) {
- // this is a simple type
- partElement.setTextContent(textContent);
- } else {
- // this is a complex type, import every child
- // !!! Attributes are ignored
- for (int m = 0; m < bodyElement.getChildNodes().getLength(); m++) {
- Node child = bodyElement.getChildNodes().item(m);
- partElement.appendChild(doc.importNode(child, true));
- }
- }
- }
-
- }
- return partElement;
- }
}
}
-
Copied: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java (from r671620, ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java)
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java?p2=ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java&p1=ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java&r1=671620&r2=671630&rev=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpClientHelper.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java Wed Jun 25 11:41:26 2008
@@ -19,12 +19,9 @@
package org.apache.ode.axis2.httpbinding;
-import org.apache.axis2.transport.http.HttpTransportProperties;
-import org.apache.commons.httpclient.HostConfiguration;
+import org.apache.axis2.AxisFault;
import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.HttpState;
-import org.apache.commons.httpclient.URI;
-import org.apache.commons.httpclient.URIException;
+import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
@@ -36,15 +33,22 @@
import org.apache.commons.httpclient.params.HttpParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.commons.lang.StringUtils;
import org.apache.ode.axis2.Properties;
+import org.apache.ode.axis2.OdeFault;
import org.apache.ode.axis2.util.URLEncodedTransformer;
import org.apache.ode.axis2.util.UrlReplacementTransformer;
import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
import org.apache.ode.utils.DOMUtils;
+import org.apache.ode.utils.Namespaces;
import org.apache.ode.utils.wsdl.Messages;
import org.apache.ode.utils.wsdl.WsdlUtils;
import org.apache.ode.il.epr.MutableEndpoint;
+import org.apache.ode.il.OMUtils;
+import org.apache.axiom.om.OMElement;
import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
import javax.wsdl.Binding;
import javax.wsdl.BindingInput;
@@ -52,39 +56,33 @@
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Part;
+import javax.wsdl.BindingOutput;
import javax.wsdl.extensions.http.HTTPOperation;
+import javax.wsdl.extensions.mime.MIMEContent;
+import javax.wsdl.extensions.soap.SOAPHeader;
+import javax.wsdl.extensions.ExtensibilityElement;
+import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.xml.namespace.QName;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Collection;
+import java.util.List;
-public class HttpClientHelper {
+public class HttpMethodConverter {
private static final String CONTENT_TYPE_TEXT_XML = "text/xml";
private static final Log log = LogFactory.getLog(HttpClientHelper.class);
- protected static final org.apache.ode.utils.wsdl.Messages msgs = Messages.getMessages(Messages.class);
+ protected static final Messages msgs = Messages.getMessages(Messages.class);
protected Binding binding;
- public HttpClientHelper(Binding binding) {
+ public HttpMethodConverter(Binding binding) {
this.binding = binding;
}
- public void configure(HostConfiguration hostConfig, HttpState state, URI targetURI, HttpParams params) throws URIException {
- if (log.isDebugEnabled()) log.debug("Configuring http client...");
- // proxy configuration
- if (ProxyConf.isProxyEnabled(params, targetURI.getHost())) {
- if (log.isDebugEnabled()) log.debug("ProxyConf");
- ProxyConf.configure(hostConfig, state, (HttpTransportProperties.ProxyProperties) params.getParameter(Properties.PROP_HTTP_PROXY_PREFIX));
- }
-
- // security
- // ...
-
- }
-
- public HttpMethod buildHttpMethod(PartnerRoleMessageExchange odeMex, HttpParams params) throws UnsupportedEncodingException {
+ public HttpMethod createHttpRequest(PartnerRoleMessageExchange odeMex, HttpParams params) throws UnsupportedEncodingException {
Operation operation = odeMex.getOperation();
BindingOperation bindingOperation = binding.getBindingOperation(operation.getName(), operation.getInput().getName(), operation.getOutput().getName());
@@ -107,17 +105,6 @@
return method;
}
- protected Map<String, Element> extractPartElements(Message msgDef, Element message) {
- Map<String, Element> partValues = new HashMap<String, Element>();
- for (Iterator iterator = msgDef.getParts().values().iterator(); iterator.hasNext();) {
- Part part = (Part) iterator.next();
- Element partEl = DOMUtils.findChildByName(message, new QName(null, part.getName()));
- if (partEl == null)
- throw new IllegalArgumentException(msgs.msgOdeMessageMissingRequiredPart(part.getName()));
- partValues.put(part.getName(), partEl);
- }
- return partValues;
- }
/**
* create and initialize the http method.
@@ -132,28 +119,33 @@
// convenience variables...
BindingInput bindingInput = bindingOperation.getBindingInput();
HTTPOperation httpOperation = (HTTPOperation) WsdlUtils.getOperationExtension(bindingOperation);
- String contentType = WsdlUtils.getMimeContentType(bindingInput.getExtensibilityElements());
+ MIMEContent content = WsdlUtils.getMimeContent(bindingInput.getExtensibilityElements());
+ String contentType = content == null ? "" : content.getType();
boolean useUrlEncoded = WsdlUtils.useUrlEncoded(bindingInput) || PostMethod.FORM_URL_ENCODED_CONTENT_TYPE.equalsIgnoreCase(contentType);
boolean useUrlReplacement = WsdlUtils.useUrlReplacement(bindingInput);
- final UrlReplacementTransformer replacementTransformer = new UrlReplacementTransformer(partValues.keySet());
- final URLEncodedTransformer encodedTransformer = new URLEncodedTransformer();
-
// the http method to be built and returned
HttpMethod method = null;
+
// the 4 elements the http method may be made of
String relativeUri = httpOperation.getLocationURI();
String queryPath = null;
- RequestEntity requestEntity = null;
+ RequestEntity requestEntity;
String encodedParams = null;
+ // ODE supports uri template in both port and operation location.
+ // so assemble the final url *before* replacement
+ String completeUri = rootUri;
+ if (StringUtils.isNotEmpty(relativeUri)) {
+ completeUri = completeUri + (completeUri.endsWith("/") || relativeUri.startsWith("/") ? "" : "/") + relativeUri;
+ }
if (useUrlReplacement) {
// insert part values in the url
- relativeUri = replacementTransformer.transform(relativeUri, partValues);
+ completeUri = new UrlReplacementTransformer().transform(completeUri, partValues);
} else if (useUrlEncoded) {
// encode part values
- encodedParams = encodedTransformer.transform(partValues);
+ encodedParams = new URLEncodedTransformer().transform(partValues);
}
// http-client api is not really neat
@@ -189,9 +181,8 @@
if (useUrlEncoded) {
requestEntity = new StringRequestEntity(encodedParams, PostMethod.FORM_URL_ENCODED_CONTENT_TYPE, method.getParams().getContentCharset());
} else if (contentType.endsWith(CONTENT_TYPE_TEXT_XML)) {
- // assumption is made that there is a single part
- // validation steps in the constructor must warranty that
- Part part = (Part) bindingOperation.getOperation().getInput().getMessage().getParts().values().iterator().next();
+ // get the part to be put in the body
+ Part part = bindingOperation.getOperation().getInput().getMessage().getPart(content.getPart());
Element partValue = partValues.get(part.getName());
// if the part has an element name, we must take the first element
if (part.getElementName() != null) {
@@ -216,10 +207,128 @@
// link params together
method.getParams().setDefaults(params);
-
- String completeUri = rootUri + (rootUri.endsWith("/") || relativeUri.startsWith("/") ? "" : "/") + relativeUri;
method.setPath(completeUri); // assumes that the path is properly encoded (URL safe).
method.setQueryString(queryPath);
return method;
}
+
+
+ protected Map<String, Element> extractPartElements(Message msgDef, Element message) {
+ Map<String, Element> partValues = new HashMap<String, Element>();
+ for (Iterator iterator = msgDef.getParts().values().iterator(); iterator.hasNext();) {
+ Part part = (Part) iterator.next();
+ Element partEl = DOMUtils.findChildByName(message, new QName(null, part.getName()));
+ if (partEl == null)
+ throw new IllegalArgumentException(msgs.msgOdeMessageMissingRequiredPart(part.getName()));
+ partValues.put(part.getName(), partEl);
+ }
+ return partValues;
+ }
+
+ /**
+ * Create the element to be associated with this part into the {@link org.apache.ode.bpel.iapi.Message}.
+ * <br/>An element named with the part name will be returned. the content of this element depends on the part.
+ * <p/>If the part has a non-null element name, a new element will be created and named accordingly then the text value is inserted in this new element.
+ * <br/>else the given text content is simply set on the part element.
+ *
+ * @param part
+ * @param textContent
+ * @return an element named with the part name will be returned
+ */
+ public Element createPartElement(Part part, String textContent) {
+ Document doc = DOMUtils.newDocument();
+ Element partElement = doc.createElementNS(null, part.getName());
+ if (part.getElementName() != null) {
+ Element element = doc.createElementNS(part.getElementName().getNamespaceURI(), part.getElementName().getLocalPart());
+ element.setTextContent(textContent);
+ partElement.appendChild(element);
+ }else{
+ partElement.setTextContent(textContent);
+ }
+ return partElement;
+ }
+
+
+ /**
+ * Create the element to be associated with this part into the {@link org.apache.ode.bpel.iapi.Message}.
+ * <p/>If the part has a non-null element name, the bodyElement is simply appended.
+ * Else if the bodyElement has a text content, the value is set to the message.
+ * Else append all nodes of bodyElement to the returned element. Attributes are ignored.
+ * <p/>
+ * The name of the returned element is the part name.
+ *
+ * @param part
+ * @param receivedElement
+ * @return the element to insert "as is" to ODE message
+ */
+ public Element createPartElement(Part part, Element receivedElement) {
+ Document doc = DOMUtils.newDocument();
+ Element partElement = doc.createElementNS(null, part.getName());
+ if (part.getElementName() != null) {
+ partElement.appendChild(doc.importNode(receivedElement, true));
+ } else {
+ if (DOMUtils.isEmptyElement(receivedElement)) {
+ // Append an empty text node.
+ // Warning! setting an empty string with setTextContent has not effect. See javadoc.
+ partElement.appendChild(doc.createTextNode(""));
+ } else {
+ String textContent = DOMUtils.getTextContent(receivedElement);
+ if (textContent != null) {
+ // this is a simple type
+ partElement.setTextContent(textContent);
+ } else {
+ // this is a complex type, import every child
+ // !!! Attributes are ignored
+ for (int m = 0; m < receivedElement.getChildNodes().getLength(); m++) {
+ Node child = receivedElement.getChildNodes().item(m);
+ partElement.appendChild(doc.importNode(child, true));
+ }
+ }
+ }
+
+ }
+ return partElement;
+ }
+
+ /**
+ * Process the HTTP Response Headers.
+ * <p/>
+ * First go through the list of Namespaces.ODE_HTTP_EXTENSION_NS:header elements included in the output binding. For each of them, set the header value as the value of the message part.
+ * <b/>Then add all HTTP headers as header part in the message. The name of the header would be the part name.
+ * @param odeMessage
+ * @param method
+ * @param messageDef
+ * @param bindingOutput
+ */
+ public void extractHttpResponseHeaders(org.apache.ode.bpel.iapi.Message odeMessage, HttpMethod method, Message messageDef, BindingOutput bindingOutput) {
+ Collection<UnknownExtensibilityElement> headerBindings = WsdlUtils.getHttpHeaders(bindingOutput.getExtensibilityElements());
+
+ // iterate through the list of header bindings
+ // and set the message parts accordingly
+ for (Iterator<UnknownExtensibilityElement> iterator = headerBindings.iterator(); iterator.hasNext();) {
+ Element binding = iterator.next().getElement();
+ String partName = binding.getAttribute("part");
+ String headerName = binding.getAttribute("name");
+
+ Part part = messageDef.getPart(partName);
+ if (StringUtils.isNotEmpty(partName)) {
+ odeMessage.setPart(partName, createPartElement(part, method.getRequestHeader(headerName).getValue()));
+ } else {
+ if(log.isErrorEnabled()) {
+ String errMsg = "Invalid binding: missing required attribute! Part name: "+new QName(Namespaces.ODE_HTTP_EXTENSION_NS, "part");
+ log.error(errMsg);
+ throw new RuntimeException(errMsg);
+ }
+ }
+ }
+
+ // also add all HTTP headers into the messade as header parts
+ Header[] reqHeaders = method.getResponseHeaders();
+ for (int i = 0; i < reqHeaders.length; i++) {
+ Header h = reqHeaders[i];
+ odeMessage.setHeaderPart(h.getName(), h.getValue());
+ }
+ }
+
+
}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapExternalService.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapExternalService.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapExternalService.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapExternalService.java Wed Jun 25 11:41:26 2008
@@ -277,12 +277,8 @@
if (faultType != null) {
if (__log.isWarnEnabled())
__log.warn("Fault response: faultType=" + faultType + "\n" + DOMUtils.domToString(odeMsgEl));
- QName nonNullFT = new QName(Namespaces.ODE_EXTENSION_NS, "unknownFault");
- Fault f = odeMex.getOperation().getFault(faultType.getLocalPart());
- if (f != null && f.getMessage().getQName() != null) nonNullFT = f.getMessage().getQName();
- else __log.debug("Fault " + faultType + " isn't referenced in the service definition, unknown fault.");
-
- Message response = odeMex.createMessage(nonNullFT);
+
+ Message response = odeMex.createMessage(faultType);
response.setMessage(odeMsgEl);
odeMex.replyWithFault(faultType, response);
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapMessageConverter.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapMessageConverter.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapMessageConverter.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/soapbinding/SoapMessageConverter.java Wed Jun 25 11:41:26 2008
@@ -425,10 +425,7 @@
if (headerEl == null) return;
- Element msgElmt = odeMessage.getMessage();
- Element destPart = msgElmt.getOwnerDocument().createElementNS(null, p.getName());
- msgElmt.appendChild(destPart);
- destPart.appendChild(msgElmt.getOwnerDocument().importNode(OMUtils.toDOM(headerEl), true));
+ odeMessage.setHeaderPart(p.getName(), OMUtils.toDOM(headerEl));
}
private String findHeaderPartName(List<SOAPHeader> headerDefs, QName elmtName) {
@@ -518,29 +515,13 @@
return new QName(_def.getTargetNamespace(), fdef.getName());
}
- @SuppressWarnings("unchecked")
private Fault inferFault(Operation operation, SOAPFault flt) {
if (flt.getDetail() == null)
return null;
// The detail is a dummy <detail> node containing the interesting fault element
QName elName = flt.getDetail().getFirstElement().getQName();
- for (Fault f : (Collection<Fault>)operation.getFaults().values()) {
- if (f.getMessage() == null)
- continue; // should have checked in ctor
-
- Collection<Part> parts = f.getMessage().getParts().values();
- if (parts.isEmpty())
- continue; // should check this in ctor
- Part p = parts.iterator().next();
- if (p.getElementName() == null)
- continue; // should check this is ctor
-
- if (p.getElementName().equals(elName))
- return f;
- }
-
- return null;
+ return WsdlUtils.inferFault(operation, elName);
}
}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/URLEncodedTransformer.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/URLEncodedTransformer.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/URLEncodedTransformer.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/URLEncodedTransformer.java Wed Jun 25 11:41:26 2008
@@ -21,6 +21,8 @@
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.util.EncodingUtil;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.axis2.httpbinding.Messages;
import org.w3c.dom.Element;
@@ -28,28 +30,37 @@
import javax.wsdl.Part;
import java.util.Iterator;
import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
/**
* @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
*/
public class URLEncodedTransformer {
- private static final Messages msgs = Messages.getMessages(Messages.class);
+ private static final Log log = LogFactory.getLog(URLEncodedTransformer.class);
+
+ /**
+ * @param values - a map<String, Element>, the key is a part name (without curly braces), the value the replacement value for the part name. If the value is not a simple type, it will be skipped.
+ * @return the encoded params
+ */
public String transform(Map<String, Element> values) {
if (values.isEmpty()) return null;
- NameValuePair[] pairs = new NameValuePair[values.size()];
- int i = 0;
+ List<NameValuePair> l = new ArrayList<NameValuePair>(values.size());
for (Map.Entry<String, Element> e : values.entrySet()) {
+ String partName = e.getKey();
Element node = e.getValue();
String nodeContent = DOMUtils.isEmptyElement(node) ? "" : DOMUtils.getTextContent(node);
if (nodeContent == null) {
- throw new IllegalArgumentException(msgs.msgSimpleTypeExpected(e.getKey()));
+ // if it is not a simple type, skip it
+ if (log.isDebugEnabled())
+ log.debug("Part " + partName + " skipped because associated element is not of a simple type.");
+ continue;
}
- NameValuePair p = new NameValuePair(e.getKey(), nodeContent);
- pairs[i++] = p;
+ l.add(new NameValuePair(e.getKey(), nodeContent));
}
- return EncodingUtil.formUrlEncode(pairs, "UTF-8");
+ return EncodingUtil.formUrlEncode(l.toArray(new NameValuePair[0]), "UTF-8");
}
}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/UrlReplacementTransformer.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/UrlReplacementTransformer.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/UrlReplacementTransformer.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/UrlReplacementTransformer.java Wed Jun 25 11:41:26 2008
@@ -19,24 +19,20 @@
package org.apache.ode.axis2.util;
-import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.utils.DOMUtils;
-import org.apache.ode.utils.wsdl.Messages;
import org.w3c.dom.Element;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* This encoder applies urlReplacement as defined by the <a href='http://www.w3.org/TR/wsdl#_http:urlReplacement'>WSDL specification</a>.
+ * <br/>Surrounding characters for parts may be parentheses '()' or braces '{}'. Pattern with parentheses is look up first, if found then it's replaced with the part value, else the pattern with braces is look up.
* <p/><strong>Escaping Considerations</strong>
* <br/>Replacement and default values are escaped. All characters except unreserved (as defined by <a href="http://tools.ietf.org/html/rfc2396#appendix-A">rfc2396</a>) are escaped.
* <br/> unreserved = alphanum | mark
@@ -51,33 +47,18 @@
private static final Log log = LogFactory.getLog(UrlReplacementTransformer.class);
- private static final org.apache.ode.utils.wsdl.Messages msgs = Messages.getMessages(Messages.class);
private static final org.apache.ode.axis2.httpbinding.Messages httpMsgs = org.apache.ode.axis2.httpbinding.Messages.getMessages(org.apache.ode.axis2.httpbinding.Messages.class);
- protected Set<String> partNames;
-
public UrlReplacementTransformer() {
- partNames = new HashSet<String>();
- }
-
- public UrlReplacementTransformer(Set<String> partNames) {
- this.partNames = partNames;
}
/**
* @param baseUri - the base uri template containing part names enclosed within single curly braces
- * @param values - a map<String, Object>, the key is a part name (without curly braces), the value the replacement value for the part name.
+ * @param values - a map<String, Element>, the key is a part name (without curly braces), the value the replacement value for the part name. If the value is not a simple type, it will be skipped.
* @return the encoded uri
- * @throws java.lang.IllegalArgumentException
- * if a part (key) is missing in the map, if a replacement value is null in the map, if a part pattern is not found in the uri template, if a part pattern is found more than once
+ * @throws java.lang.IllegalArgumentException if a replacement value is null in the map or if a part pattern is found more than once
*/
public String transform(String baseUri, Map<String, Element> values) {
- // each part must be given a replacement value
- if (values.keySet().size() != partNames.size() || !values.keySet().containsAll(partNames)) {
- Collection<String> disjunction = CollectionUtils.disjunction(partNames, values.keySet());
- throw new IllegalArgumentException(msgs.msgMissingReplacementValuesFor(disjunction));
- }
-
// the list containing the final split result
List<String> result = new ArrayList<String>();
@@ -87,16 +68,16 @@
// replace each part exactly once
for (Map.Entry<String, Element> e : values.entrySet()) {
- String partPattern;
+ String partName = e.getKey();
String replacementValue;
{
- String partName = e.getKey();
- partPattern = "\\(" + partName + "\\)";
Element value = e.getValue();
- if (value == null) {
- throw new IllegalArgumentException(httpMsgs.msgSimpleTypeExpected(partName));
- }
replacementValue = DOMUtils.isEmptyElement(value) ? "" : DOMUtils.getTextContent(value);
+ if (replacementValue == null) {
+ // if it is not a simple type, skip it
+ if(log.isDebugEnabled()) log.debug("Part "+partName+" skipped because associated element is not of a simple type.");
+ continue;
+ }
}
try {
@@ -105,7 +86,14 @@
// this exception is never thrown by the code of httpclient
if (log.isWarnEnabled()) log.warn(urie.getMessage(), urie);
}
- replace(result, partPattern, replacementValue);
+
+ // first, search for parentheses
+ String partPattern = "\\(" + partName + "\\)";
+ if(!replace(result, partPattern, replacementValue)){
+ // if parentheses not found, try braces
+ partPattern = "\\{" + partName + "\\}";
+ replace(result, partPattern, replacementValue);
+ }
}
// join all the array elements to form the final url
@@ -114,23 +102,14 @@
return sb.toString();
}
- private void replace(List<String> result, String partPattern, String replacementValue) {
+ private boolean replace(List<String> result, String partPattern, String replacementValue) {
// !!! i=i+2 replacement values will be skipped,
// so replaced values do not trigger additional matches
for (int i = 0; i < result.size(); i = i + 2) {
String segment = result.get(i);
// use a negative limit, so empty strings are not discarded
String[] matches = segment.split(partPattern, -1);
- if (matches.length == 1) {
- if (i == result.size() - 1) {
- // last segment, no more string to test
- throw new IllegalArgumentException(httpMsgs.msgInvalidURIPattern());
- } else {
- continue;
- }
- } else if (matches.length > 2) {
- throw new IllegalArgumentException(httpMsgs.msgInvalidURIPattern());
- } else {
+ if (matches.length == 2) {
// if exactly one match...
// remove the matching segment
@@ -142,8 +121,9 @@
// pattern found and replaced, we're done for this pattern
// move on to the next part
- break;
+ return true;
}
}
+ return false;
}
}
Copied: ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java (from r671620, ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpClientHelperTest.java)
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java?p2=ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java&p1=ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpClientHelperTest.java&r1=671620&r2=671630&rev=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpClientHelperTest.java (original)
+++ ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java Wed Jun 25 11:41:26 2008
@@ -49,15 +49,15 @@
/**
* @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
*/
-public class HttpClientHelperTest extends TestCase {
+public class HttpMethodConverterTest extends TestCase {
protected Definition definition;
- protected HttpClientHelper deliciousBuilder;
+ protected HttpMethodConverter deliciousBuilder;
protected Binding deliciousBinding;
protected Port deliciousPort;
- protected HttpClientHelper dummyBuilder;
+ protected HttpMethodConverter dummyBuilder;
protected Port dummyPort;
protected Binding dummyBinding;
@@ -72,12 +72,12 @@
Service deliciousService = definition.getService(new QName("http://ode/bpel/unit-test.wsdl", "DeliciousService"));
deliciousPort = deliciousService.getPort("TagHttpPort");
deliciousBinding = deliciousPort.getBinding();
- deliciousBuilder = new HttpClientHelper(deliciousBinding);
+ deliciousBuilder = new HttpMethodConverter(deliciousBinding);
Service dummyService = definition.getService(new QName("http://ode/bpel/unit-test.wsdl", "DummyService"));
dummyPort = dummyService.getPort("DummyServiceHttpport");
dummyBinding = dummyPort.getBinding();
- dummyBuilder = new HttpClientHelper(dummyBinding);
+ dummyBuilder = new HttpMethodConverter(dummyBinding);
}
@@ -98,7 +98,7 @@
odeMex.op = deliciousBinding.getBindingOperation("getTag", null, null).getOperation();
odeMex.req = new MockMessage(msgEl);
odeMex.epr = new MockEPR(uri);
- HttpMethod httpMethod = deliciousBuilder.buildHttpMethod(odeMex, new DefaultHttpParams());
+ HttpMethod httpMethod = deliciousBuilder.createHttpRequest(odeMex, new DefaultHttpParams());
assertTrue("GET".equalsIgnoreCase(httpMethod.getName()));
@@ -119,7 +119,7 @@
odeMex.req = new MockMessage(msgEl);
odeMex.epr = new MockEPR(uri);
try {
- HttpMethod httpMethod = deliciousBuilder.buildHttpMethod(odeMex, new DefaultHttpParams());
+ HttpMethod httpMethod = deliciousBuilder.createHttpRequest(odeMex, new DefaultHttpParams());
fail("IllegalArgumentException expected because message element is empty.");
} catch (IllegalArgumentException e) {
// expected behavior
@@ -145,7 +145,7 @@
odeMex.op = dummyBinding.getBindingOperation("hello", null, null).getOperation();
odeMex.req = new MockMessage(msgEl);
odeMex.epr = new MockEPR(uri);
- HttpMethod httpMethod = dummyBuilder.buildHttpMethod(odeMex, new DefaultHttpParams());
+ HttpMethod httpMethod = dummyBuilder.createHttpRequest(odeMex, new DefaultHttpParams());
assertTrue("POST".equalsIgnoreCase(httpMethod.getName()));
assertEquals("Generated URI does not match", expectedUri, httpMethod.getURI().toString());
@@ -224,6 +224,10 @@
}
+ public void setHeaderPart(String name, String content) {
+
+ }
+
public void setMessage(Element msg) {
}
Modified: ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlEncodedTransformerTest.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlEncodedTransformerTest.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlEncodedTransformerTest.java (original)
+++ ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlEncodedTransformerTest.java Wed Jun 25 11:41:26 2008
@@ -31,10 +31,10 @@
* @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
*/
public class UrlEncodedTransformerTest extends TestCase {
- protected URLEncodedTransformer transformer= new URLEncodedTransformer();
+ protected URLEncodedTransformer transformer = new URLEncodedTransformer();
- public void testSimple(){
+ public void testSimple() {
Document doc = DOMUtils.newDocument();
Map<String, Element> m = new HashMap<String, Element>();
Element element = doc.createElement("part1");
@@ -52,7 +52,7 @@
assertTrue(res.contains("part1=42+3.14159"));
assertTrue(res.contains("part2=hello+word+%40%23%24%25+%26*"));
assertTrue(res.contains("emptyPart="));
- assertTrue(res.split("&").length==m.size());
+ assertTrue(res.split("&").length == m.size());
}
@@ -63,12 +63,6 @@
Map<String, Element> m = new HashMap<String, Element>();
m.put("part1", element);
- try {
- transformer.transform(m);
- fail("IllegalArgumentException expected because a complex type is passed.");
- } catch (IllegalArgumentException e) {
- // expected behavior
- }
-
+ assertEquals("Result should empty because the only part is associated to a complex type", "", transformer.transform(m));
}
}
Modified: ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlReplacementTransformerTest.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlReplacementTransformerTest.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlReplacementTransformerTest.java (original)
+++ ode/trunk/axis2/src/test/java/org/apache/ode/axis2/util/UrlReplacementTransformerTest.java Wed Jun 25 11:41:26 2008
@@ -33,22 +33,48 @@
*/
public class UrlReplacementTransformerTest extends TestCase {
- //<http:operation location="o1/A(part1)B(part2)/(part3)"/>
- private String baseUrl = "o1/A(part1)B(part2)/(part3)";
- public void testRegularCases() {
+ public void testWithParentheses() {
String[][] a = new String[][]{
- new String[]{"with alphabetical chars", baseUrl, "o1/AtutuBtiti/toto", "part1", "tutu", "part2", "titi", "part3", "toto"}
+ new String[]{"with alphabetical chars", "o1/A(part1)B(part2)/(part3)", "o1/AtutuBtiti/toto", "part1", "tutu", "part2", "titi", "part3", "toto"}
, new String[]{"parts are ends", "(part1)B(part2)/(part3)", "3B14/159", "part1", "3", "part2", "14", "part3", "159"}
, new String[]{"a single part", "(part1)", "314159", "part1", "314159"}
, new String[]{"parts surrounded with ()", "o1/A((part1))B((part2))/((part3))", "o1/A(3)B(14)/(159)", "part1", "3", "part2", "14", "part3", "159"}
- , new String[]{"with numeric chars", baseUrl, "o1/A3B14/159%20and%20an%20epsilon", "part1", "3", "part2", "14", "part3", "159 and an epsilon"}
- , new String[]{"with empty values", baseUrl, "o1/AB/", "part1", "", "part2", "", "part3", ""}
- , new String[]{"with special chars", baseUrl, "o1/AWhatB%2410%2C000/~!%40%23%24%25%5E%26*()_%2B%3D-%60%5B%5D%7B%7D%7C%5C.", "part1", "What", "part2", "$10,000", "part3", "~!@#$%^&*()_+=-`[]{}|\\."}
- , new String[]{"with values containing key names", baseUrl, "o1/Avalue_of_part1_is_(part2)_and_should_not_be_replacedBsame_for_part2(part3)/foo", "part1", "value_of_part1_is_(part2)_and_should_not_be_replaced", "part2", "same_for_part2(part3)", "part3", "foo"}
+ , new String[]{"with numeric chars", "o1/A(part1)B(part2)/(part3)", "o1/A3B14/159%20and%20an%20epsilon", "part1", "3", "part2", "14", "part3", "159 and an epsilon"}
+ , new String[]{"with empty values", "o1/A(part1)B(part2)/(part3)", "o1/AB/", "part1", "", "part2", "", "part3", ""}
+ , new String[]{"with special chars", "o1/A(part1)B(part2)/(part3)", "o1/AWhatB%2410%2C000/~!%40%23%24%25%5E%26*()_%2B%3D-%60%5B%5D%7B%7D%7C%5C.", "part1", "What", "part2", "$10,000", "part3", "~!@#$%^&*()_+=-`[]{}|\\."}
+ , new String[]{"with values containing key names", "o1/A(part1)B(part2)/(part3)", "o1/Avalue_of_part1_is_(part2)_and_should_not_be_replacedBsame_for_part2(part3)/foo", "part1", "value_of_part1_is_(part2)_and_should_not_be_replaced", "part2", "same_for_part2(part3)", "part3", "foo"}
};
Document doc = DOMUtils.newDocument();
+ UrlReplacementTransformer encoder = new UrlReplacementTransformer();
+ for (String[] data : a) {
+ // convert into map
+ Map<String, Element> parts = new HashMap<String, Element>();
+ for (int k = 3; k < data.length; k = k + 2) {
+ Element element = doc.createElement(data[k]);
+ element.setTextContent(data[k + 1]);
+ parts.put(data[k], element);
+ }
+ assertEquals(data[0], data[2], encoder.transform(data[1], parts));
+ }
+ }
+
+
+ public void testWithBraces() {
+ String[][] a = new String[][]{
+ new String[]{"with alphabetical chars", "o1/A{part1}B{part2}/{part3}", "o1/AtutuBtiti/toto", "part1", "tutu", "part2", "titi", "part3", "toto"}
+ , new String[]{"parts are ends", "{part1}B{part2}/{part3}", "3B14/159", "part1", "3", "part2", "14", "part3", "159"}
+ , new String[]{"a single part", "{part1}", "314159", "part1", "314159"}
+ , new String[]{"parts surrounded with {}", "o1/A{{part1}}B{{part2}}/{{part3}}", "o1/A{3}B{14}/{159}", "part1", "3", "part2", "14", "part3", "159"}
+ , new String[]{"with numeric chars", "o1/A{part1}B{part2}/{part3}", "o1/A3B14/159%20and%20an%20epsilon", "part1", "3", "part2", "14", "part3", "159 and an epsilon"}
+ , new String[]{"with empty values", "o1/A{part1}B{part2}/{part3}", "o1/AB/", "part1", "", "part2", "", "part3", ""}
+ , new String[]{"with special chars", "o1/A{part1}B{part2}/{part3}", "o1/AWhatB%2410%2C000/~!%40%23%24%25%5E%26*()_%2B%3D-%60%5B%5D%7B%7D%7C%5C.", "part1", "What", "part2", "$10,000", "part3", "~!@#$%^&*()_+=-`[]{}|\\."}
+ , new String[]{"with values containing key names", "o1/A{part1}B{part2}/{part3}", "o1/Avalue_of_part1_is_%7Bpart2%7D_and_should_not_be_replacedBsame_for_part2%7Bpart3%7D/foo", "part1", "value_of_part1_is_{part2}_and_should_not_be_replaced", "part2", "same_for_part2{part3}", "part3", "foo"}
+ };
+
+ Document doc = DOMUtils.newDocument();
+ UrlReplacementTransformer encoder = new UrlReplacementTransformer();
for (String[] data : a) {
// convert into map
Map<String, Element> parts = new HashMap<String, Element>();
@@ -57,24 +83,35 @@
element.setTextContent(data[k + 1]);
parts.put(data[k], element);
}
- UrlReplacementTransformer encoder = new UrlReplacementTransformer(parts.keySet());
assertEquals(data[0], data[2], encoder.transform(data[1], parts));
}
}
- public void testMissingPartPatterns() {
- try {
- Map<String, Element> map = new HashMap<String, Element>();
- map.put("part1", null);
- UrlReplacementTransformer encoder = new UrlReplacementTransformer(map.keySet());
- encoder.transform("", map);
- fail("Exception expected! Missing Part Patterns in URI");
- } catch (IllegalArgumentException e) {
- // expected behavior
+ public void testWithMixnMatch() {
+ String[][] a = new String[][]{
+ new String[]{"with alphabetical chars", "o1/A(part1)B{part2}/{part3}", "o1/AtutuBtiti/toto", "part1", "tutu", "part2", "titi", "part3", "toto"}
+ , new String[]{"parts are ends", "{part1}B{part2}/(part3)", "3B14/159", "part1", "3", "part2", "14", "part3", "159"}
+ , new String[]{"a single part", "{part1}", "314159", "part1", "314159"}
+ , new String[]{"with empty values", "o1/A{part1}B(part2)/{part3}", "o1/AB/", "part1", "", "part2", "", "part3", ""}
+ };
+
+ Document doc = DOMUtils.newDocument();
+ UrlReplacementTransformer encoder = new UrlReplacementTransformer();
+ for (String[] data : a) {
+ // convert into map
+ Map<String, Element> parts = new HashMap<String, Element>();
+ for (int k = 3; k < data.length; k = k + 2) {
+ Element element = doc.createElement(data[k]);
+ element.setTextContent(data[k + 1]);
+ parts.put(data[k], element);
+ }
+ assertEquals(data[0], data[2], encoder.transform(data[1], parts));
}
+
}
+
public void testComplexType() {
Document doc = DOMUtils.newDocument();
Element element = doc.createElement("part1");
@@ -82,13 +119,9 @@
Map<String, Element> m = new HashMap<String, Element>();
m.put("part1", element);
- UrlReplacementTransformer encoder = new UrlReplacementTransformer(m.keySet());
- try {
- encoder.transform("(part1)", m);
- fail("IllegalArgumentException expected because a complex type is passed.");
- } catch (IllegalArgumentException e) {
- // expected behavior
- }
+ UrlReplacementTransformer encoder = new UrlReplacementTransformer();
+ assertEquals("Result should be equal to template because the only part is associated to a complex type", "(part1)", encoder.transform("(part1)", m));
+
}
}
Modified: ode/trunk/axis2/src/test/resources/http-binding-extensions.wsdl
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/test/resources/http-binding-extensions.wsdl?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/test/resources/http-binding-extensions.wsdl (original)
+++ ode/trunk/axis2/src/test/resources/http-binding-extensions.wsdl Wed Jun 25 11:41:26 2008
@@ -120,10 +120,14 @@
<wsdl:input>
<http:urlReplacement/>
<mime:content type="text/xml" part="article"/>
- <!-- fault binding -->
- <odex:fault name="UpdateFailed"/>
</wsdl:input>
<wsdl:output/>
+ <!-- fault binding -->
+ <wsdl:fault name="UpdateFailed">
+ <!-- name attribute is optional -->
+ <!--<odex:fault name="UpdateFailed"/>-->
+ <odex:fault/>
+ </wsdl:fault>
</wsdl:operation>
<wsdl:operation name="doPOST">
<http:operation location=""/>
Modified: ode/trunk/axis2/src/test/resources/http-binding-validator.wsdl
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/test/resources/http-binding-validator.wsdl?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/axis2/src/test/resources/http-binding-validator.wsdl (original)
+++ ode/trunk/axis2/src/test/resources/http-binding-validator.wsdl Wed Jun 25 11:41:26 2008
@@ -382,7 +382,8 @@
</wsdl:binding>
<wsdl:binding name="DummyServiceHttpBinding_get+urlReplacement+missing_part" type="ns1:DummyServicePortType">
<wsdl:documentation>
- shouldPass # WSLD spec requires that all message parts must be in the url pattern when urlReplacement is used. However ODE relaxes this.
+ shouldPass # WSLD spec requires that all message parts must be in the url pattern when urlReplacement is used.
+ However ODE relaxes this.
</wsdl:documentation>
<http:binding verb="GET"/>
<wsdl:operation name="hello">
@@ -410,6 +411,21 @@
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
+ <wsdl:binding name="DummyServiceHttpBinding_get+urlReplacement+empty_pattern" type="ns1:DummyServicePortType">
+ <wsdl:documentation>
+ shouldPass # Operation-location may be empty. REST connector will not fill it for instance.
+ </wsdl:documentation>
+ <http:binding verb="GET"/>
+ <wsdl:operation name="hello">
+ <http:operation location=""/>
+ <wsdl:input>
+ <http:urlReplacement/>
+ </wsdl:input>
+ <wsdl:output>
+ <mime:content type="text/xml" part="hello"/>
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
<!-- ###################################### -->
<!-- Verb at the operation level -->
Modified: ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/Message.java
URL: http://svn.apache.org/viewvc/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/Message.java?rev=671630&r1=671629&r2=671630&view=diff
==============================================================================
--- ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/Message.java (original)
+++ ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/Message.java Wed Jun 25 11:41:26 2008
@@ -69,6 +69,13 @@
void setHeaderPart(String name, Element content);
/**
+ * Set a header part value
+ * @param name header part name
+ * @param content header part text content
+ */
+ void setHeaderPart(String name, String content);
+
+ /**
* Gets all header parts in the message.
* @return
*/