You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by mr...@apache.org on 2008/05/20 00:57:26 UTC
svn commit: r658024 [2/4] - in /ode/trunk: ./
axis2-war/src/test/java/org/apache/ode/axis2/
axis2-war/src/test/java/org/apache/ode/axis2/httpbinding/
axis2-war/src/test/java/org/apache/ode/axis2/management/
axis2-war/src/test/resources/TestHttpBinding/...
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ExternalService.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ExternalService.java?rev=658024&r1=658023&r2=658024&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ExternalService.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ExternalService.java Mon May 19 15:57:24 2008
@@ -1,306 +1,16 @@
-/*
- * 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.ode.axis2;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-
-import javax.wsdl.Definition;
-import javax.wsdl.Fault;
-import javax.wsdl.Operation;
-import javax.xml.namespace.QName;
-
-import org.apache.axiom.soap.SOAPEnvelope;
-import org.apache.axis2.AxisFault;
-import org.apache.axis2.addressing.EndpointReference;
-import org.apache.axis2.client.OperationClient;
-import org.apache.axis2.client.Options;
-import org.apache.axis2.client.ServiceClient;
-import org.apache.axis2.context.ConfigurationContext;
-import org.apache.axis2.context.MessageContext;
-import org.apache.axis2.engine.AxisConfiguration;
-import org.apache.axis2.wsdl.WSDLConstants;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ode.axis2.util.SoapMessageConverter;
-import org.apache.ode.bpel.iapi.BpelServer;
-import org.apache.ode.bpel.iapi.Message;
-import org.apache.ode.bpel.iapi.MessageExchange;
import org.apache.ode.bpel.iapi.PartnerRoleChannel;
import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
-import org.apache.ode.bpel.iapi.Scheduler;
-import org.apache.ode.bpel.iapi.MessageExchange.FailureType;
-import org.apache.ode.il.OMUtils;
-import org.apache.ode.il.epr.EndpointFactory;
-import org.apache.ode.il.epr.MutableEndpoint;
-import org.apache.ode.il.epr.WSAEndpoint;
-import org.apache.ode.utils.DOMUtils;
-import org.apache.ode.utils.Namespaces;
-import org.apache.ode.utils.uuid.UUID;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
+import javax.xml.namespace.QName;
/**
- * Acts as a service not provided by ODE. Used mainly for invocation as a way to maintain the WSDL decription of used services.
- *
- * @author Matthieu Riou <mriou at apache dot org>
+ + * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
*/
-public class ExternalService implements PartnerRoleChannel {
-
- private static final Log __log = LogFactory.getLog(ExternalService.class);
-
- private static final int EXPIRE_SERVICE_CLIENT = 30000;
-
- private static ThreadLocal<CachedServiceClient> _cachedClients = new ThreadLocal<CachedServiceClient>();
-
- private Definition _definition;
-
- private QName _serviceName;
-
- private String _portName;
-
- private AxisConfiguration _axisConfig;
-
- private SoapMessageConverter _converter;
-
- private Scheduler _sched;
-
- private BpelServer _server;
-
- public ExternalService(Definition definition, QName serviceName, String portName, AxisConfiguration axisConfig,
- Scheduler sched, BpelServer server) throws AxisFault {
- _definition = definition;
- _serviceName = serviceName;
- _portName = portName;
- _axisConfig = axisConfig;
- _sched = sched;
- _converter = new SoapMessageConverter(definition, serviceName, portName);
- _server = server;
- }
-
- public void invoke(final PartnerRoleMessageExchange odeMex) {
- boolean isTwoWay = odeMex.getMessageExchangePattern() == org.apache.ode.bpel.iapi.MessageExchange.MessageExchangePattern.REQUEST_RESPONSE;
- try {
- // Override options are passed to the axis MessageContext so we can
- // retrieve them in our session out handler.
- MessageContext mctx = new MessageContext();
- writeHeader(mctx, odeMex);
-
- _converter.createSoapRequest(mctx, odeMex.getRequest(), odeMex.getOperation());
-
- SOAPEnvelope soapEnv = mctx.getEnvelope();
- EndpointReference axisEPR = new EndpointReference(((MutableEndpoint) odeMex.getEndpointReference()).getUrl());
- if (__log.isDebugEnabled()) {
- __log.debug("Axis2 sending message to " + axisEPR.getAddress() + " using MEX " + odeMex);
- __log.debug("Message: " + soapEnv);
- }
-
- Options options = new Options();
- options.setAction(mctx.getSoapAction());
- options.setTo(axisEPR);
- options.setTimeOutInMilliSeconds(60000);
- options.setExceptionToBeThrownOnSOAPFault(false);
-
- CachedServiceClient cached = _cachedClients.get();
- long now = System.currentTimeMillis();
- if (cached == null || cached._expire < now) {
- cached = new CachedServiceClient();
- ConfigurationContext ctx = new ConfigurationContext(_axisConfig);
- cached._client = new ServiceClient(ctx, null);
- cached._expire = now + EXPIRE_SERVICE_CLIENT;
- _cachedClients.set(cached);
- }
- final OperationClient operationClient = cached._client.createClient(isTwoWay ? ServiceClient.ANON_OUT_IN_OP
- : ServiceClient.ANON_OUT_ONLY_OP);
- operationClient.setOptions(options);
- operationClient.addMessageContext(mctx);
-
- if (isTwoWay) {
- final Operation operation = odeMex.getOperation();
-
- try {
- operationClient.execute(true);
- MessageContext response = operationClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
- MessageContext flt = operationClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_FAULT_VALUE);
- if (response != null && __log.isDebugEnabled())
- __log.debug("Service response:\n" + response.getEnvelope().toString());
-
- if (flt != null) {
- reply(odeMex, operation, flt, true);
- } else {
- reply(odeMex, operation, response, response.isFault());
- }
- } catch (Throwable t) {
- String errmsg = "Error sending message to Axis2 for ODE mex " + odeMex;
- __log.error(errmsg, t);
- replyWithFailure(odeMex, MessageExchange.FailureType.COMMUNICATION_ERROR, errmsg, null);
- }
- } else /* one-way case */{
- operationClient.execute(false);
- odeMex.replyOneWayOk();
- }
- } catch (AxisFault axisFault) {
- String errmsg = "Error sending message to Axis2 for ODE mex " + odeMex;
- __log.error(errmsg, axisFault);
- odeMex.replyWithFailure(MessageExchange.FailureType.COMMUNICATION_ERROR, errmsg, null);
- }
- }
-
- /**
- * Extracts the action to be used for the given operation. It first checks to see
- * if a value is specified using WS-Addressing in the portType, it then falls back onto
- * getting it from the SOAP Binding.
- * @param operation the name of the operation to get the Action for
- * @return The action value for the specified operation
- */
- private String getAction(String operation)
- {
- String action = _converter.getWSAInputAction(operation);
- if (action == null || "".equals(action))
- {
- action = _converter.getSoapAction(operation);
- }
- return action;
- }
-
- /**
- * Extracts endpoint information from ODE message exchange to stuff them into Axis MessageContext.
- */
- private void writeHeader(MessageContext ctxt, PartnerRoleMessageExchange odeMex) {
- Options options = ctxt.getOptions();
- WSAEndpoint targetEPR = EndpointFactory.convertToWSA((MutableEndpoint) odeMex.getEndpointReference());
- WSAEndpoint myRoleEPR = EndpointFactory.convertToWSA((MutableEndpoint) odeMex.getMyRoleEndpointReference());
-
- String partnerSessionId = odeMex.getProperty(MessageExchange.PROPERTY_SEP_PARTNERROLE_SESSIONID);
- String myRoleSessionId = odeMex.getProperty(MessageExchange.PROPERTY_SEP_MYROLE_SESSIONID);
-
- if (partnerSessionId != null) {
- if (__log.isDebugEnabled()) {
- __log.debug("Partner session identifier found for WSA endpoint: " + partnerSessionId);
- }
- targetEPR.setSessionId(partnerSessionId);
- }
- options.setProperty("targetSessionEndpoint", targetEPR);
-
- if (myRoleEPR != null) {
- if (myRoleSessionId != null) {
- if (__log.isDebugEnabled()) {
- __log.debug("MyRole session identifier found for myrole (callback) WSA endpoint: " + myRoleSessionId);
- }
- myRoleEPR.setSessionId(myRoleSessionId);
- }
- options.setProperty("callbackSessionEndpoint", odeMex.getMyRoleEndpointReference());
- } else {
- __log.debug("My-Role EPR not specified, SEP will not be used.");
- }
-
- String action = getAction(odeMex.getOperationName());
- ctxt.setSoapAction(action);
-
- if (MessageExchange.MessageExchangePattern.REQUEST_RESPONSE == odeMex.getMessageExchangePattern()) {
- EndpointReference annonEpr =
- new EndpointReference(Namespaces.WS_ADDRESSING_ANON_URI);
- ctxt.setReplyTo(annonEpr);
- ctxt.setMessageID("uuid:" + new UUID().toString());
- }
- }
-
- public org.apache.ode.bpel.iapi.EndpointReference getInitialEndpointReference() {
- Element eprElmt = ODEService.genEPRfromWSDL(_definition, _serviceName, _portName);
- if (eprElmt == null)
- throw new IllegalArgumentException("Service " + _serviceName + " and port " + _portName
- + "couldn't be found in provided WSDL document!");
- return EndpointFactory.convertToWSA(ODEService.createServiceRef(eprElmt));
- }
-
- public void close() {
- // nothing
- }
-
- public String getPortName() {
- return _portName;
- }
-
- public QName getServiceName() {
- return _serviceName;
- }
-
- private void replyWithFailure(final PartnerRoleMessageExchange odeMex, final FailureType error, final String errmsg, final Element details) {
- try {
- odeMex.replyWithFailure(error, errmsg, details);
- } catch (Exception e) {
- String emsg = "Error executing replyWithFailure; reply will be lost.";
- __log.error(emsg, e);
-
- }
-
- }
-
- private void reply(final PartnerRoleMessageExchange odeMex, final Operation operation, final MessageContext reply, final boolean fault) {
- try {
- if (__log.isDebugEnabled()) __log.debug("Received response for MEX " + odeMex);
- if (fault) {
- Document odeMsg = DOMUtils.newDocument();
- Element odeMsgEl = odeMsg.createElementNS(null, "message");
- odeMsg.appendChild(odeMsgEl);
- QName faultType = _converter.parseSoapFault(odeMsgEl, reply.getEnvelope(), operation);
- if (__log.isDebugEnabled()) __log.debug("Reply is a fault, found type: " + faultType);
-
- 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);
- response.setMessage(odeMsgEl);
-
- odeMex.replyWithFault(faultType, response);
- } else {
- if (__log.isWarnEnabled())
- __log.warn("Fault response: faultType=(unkown)\n" + reply.getEnvelope().toString());
- odeMex.replyWithFailure(FailureType.OTHER, reply.getEnvelope().getBody().getFault().getText(),
- OMUtils.toDOM(reply.getEnvelope().getBody()));
- }
- } else {
- Message response = odeMex.createMessage(odeMex.getOperation().getOutput().getMessage().getQName());
- _converter.parseSoapResponse(response, reply.getEnvelope(), operation);
- if (__log.isInfoEnabled()) __log.info("Response:\n" + (response.getMessage() != null ?
- DOMUtils.domToString(response.getMessage()) : "empty"));
- odeMex.reply(response);
- }
- } catch (Exception ex) {
- String errmsg = "Unable to process response: " + ex.getMessage();
- __log.error(errmsg, ex);
- odeMex.replyWithFailure(FailureType.OTHER, errmsg, null);
- }
-
- }
-
- // INNER CLASS
- static class CachedServiceClient {
- ServiceClient _client;
+public interface ExternalService extends PartnerRoleChannel {
+ void invoke(PartnerRoleMessageExchange odeMex);
- long _expire;
- }
+ String getPortName();
+ QName getServiceName();
}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/MessageExchangeContextImpl.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/MessageExchangeContextImpl.java?rev=658024&r1=658023&r2=658024&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/MessageExchangeContextImpl.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/MessageExchangeContextImpl.java Mon May 19 15:57:24 2008
@@ -63,7 +63,7 @@
ExternalService service = (ExternalService)partnerRoleMessageExchange.getPartnerRoleChannel();
if (__log.isDebugEnabled())
- __log.debug("The service to invoke is the external service " + service);
+ __log.debug("The service to invoke is the external service " + service.getServiceName()+":"+service.getPortName());
service.invoke(partnerRoleMessageExchange);
}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/Messages.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/Messages.java?rev=658024&r1=658023&r2=658024&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/Messages.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/Messages.java Mon May 19 15:57:24 2008
@@ -107,30 +107,6 @@
return format("Error shutting down service unit \"{0}\".", serviceUnitID);
}
- /** Port {0} is missing <wsdl:binding> or <soapbind:binding> */
- public String msgNoBindingForPort(QName sericeName) {
- return format("Couldn't find any port in service {0} having <wsdl:binding> and <soapbind:binding>", sericeName);
- }
-
- /** Port {0} has multiple <soapbind:binding> elements */
- public String msgMultipleSoapBindingsForPort(String portName) {
- return format("Port {0} has multiple <soapbind:binding> elements", portName);
- }
-
- /**
- * Attempted to import WSDL for namespace {0} from multiple locations:
- * definitions from {1} will be ignored
- */
- public String msgDuplicateWSDLImport(String tns, String location) {
- return format("Attempted to import WSDL for namespace {0} from"
- + " multiple locations: definitions from {1} will be ignored", tns, location);
- }
-
- /** The WSDL for namespace "{0}" could not be found in "{1}". */
- public String msgWsdlImportNotFound(String wsdlUri, String location) {
- return format("The WSDL for namespace \"{0}\" could not be found in \"{1}\".", wsdlUri, location);
- }
-
public String msgBpelEventListenerRegistered(String listenerCN) {
return format("Registered custom BPEL event listener: {0}", listenerCN);
}
@@ -152,93 +128,6 @@
}
- public Throwable msgOdeMessageMissingRequiredPart(String partName) {
- String s = format("Message is missing required part: {0}", partName);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgServiceDefinitionNotFound(QName serviceName) {
- String s = format("Servicd definition not found: {0}.", serviceName);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgPortDefinitionNotFound(QName serviceName, String portName) {
- String s = format("Port definition not found: service {0} port {1}.", serviceName, portName);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgBindingOperationNotFound(QName serviceName, String portName, String name) {
- String s = format("Binding operation not found: service {0} port {1} name {2}.", serviceName, portName, name);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgBindingInputNotFound(QName serviceName, String portName, String name) {
- String s = format("Binding input not found: service {0} port {1} name {2}.", serviceName, portName, name);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgBindingNotFound(QName serviceName, String portName) {
- String s = format("Binding not found: service {0} port {1}.", serviceName, portName);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgNoSOAPBindingForPort(String name) {
- String s = format("No SOAP binding for port: {0}.", name);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgSoapHeaderReferencesUnkownPart(String part) {
- String s = format("SOAP header references unknown part: {0}.", part);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgBindingDefinesNonElementDocListParts() {
- String s = format("Binding defines non-element document literal part(s)");
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgUnexpectedElementInSOAPBody(QName name, QName elementName) {
- String s = format("Unexpected element in SOAP body: message {0} element {1}.", name, elementName);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgSOAPBodyDoesNotContainAllRequiredParts() {
- String s = format("SOAP body does not contain all required parts");
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgSOAPBodyDoesNotContainRequiredPart(String name) {
- String s = format("SOAP body does not contain required part: {0}.", name);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgSoapHeaderMissingRequiredElement(QName elementType) {
- String s = format("SOAP header missing required element: {0}.", elementType);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgBindingOutputNotFound(QName serviceName, String portName, String name) {
- String s = format("Binding output not found: service {0} port {1} name {2}.", serviceName, portName, name);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgUndefinedFault(QName serviceName, String portName, String opname, QName faultName) {
- String s = format("Undefined fault: service {0} port {1} operation {2} fault {3}.", serviceName, portName, opname, faultName);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgOdeMessagePartMissingRequiredElement(QName serviceName, String portName, String opname, QName elementName) {
- String s = format("Message part is missing required element: service {0} port {1} operation {2} element {3}.",
- serviceName, portName, opname, elementName);
- return new IllegalArgumentException(s);
- }
-
- public Throwable msgSoapBodyDoesNotContainExpectedPartWrapper(QName serviceName, String portName, QName rpcWrapQName) {
- String s = format("SOAP body does not contain expected part wrapper: service {0} port {1} wrapper {2}",
- serviceName, portName, rpcWrapQName);
- return new IllegalArgumentException(s);
- }
-
public String msgOdeDbConfigError() {
return format("Error starting database connections, check the database configuration!");
}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java?rev=658024&r1=658023&r2=658024&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java Mon May 19 15:57:24 2008
@@ -45,6 +45,7 @@
import org.apache.ode.axis2.hooks.ODEMessageReceiver;
import org.apache.ode.axis2.service.DeploymentWebService;
import org.apache.ode.axis2.service.ManagementService;
+import org.apache.ode.axis2.httpbinding.HttpExternalService;
import org.apache.ode.bpel.compiler.api.ExtensionValidator;
import org.apache.ode.bpel.connector.BpelServerConnector;
import org.apache.ode.bpel.dao.BpelDAOConnectionFactory;
@@ -65,6 +66,7 @@
import org.apache.ode.scheduler.simple.SimpleScheduler;
import org.apache.ode.store.ProcessStoreImpl;
import org.apache.ode.utils.GUID;
+import org.apache.ode.utils.wsdl.WsdlUtils;
import org.apache.ode.utils.fs.TempFileManager;
import org.apache.ode.bpel.pmapi.InstanceManagement;
import org.apache.ode.bpel.pmapi.ProcessManagement;
@@ -207,8 +209,7 @@
* Shutdown the service engine. This performs cleanup before the BPE is terminated. Once this method has been called, init()
* must be called before the transformation engine can be started again with a call to start().
*
- * @throws AxisFault
- * if the engine is unable to shut down.
+ * @throws AxisFault if the engine is unable to shut down.
*/
public void shutDown() throws AxisFault {
@@ -316,18 +317,27 @@
return odeService;
}
- public ExternalService createExternalService(Definition def, QName serviceName, String portName) throws ContextException {
+ public ExternalService createExternalService(Definition def, QName serviceName, String portName, ProcessConf pconf) throws ContextException {
ExternalService extService = (ExternalService) _externalServices.get(serviceName);
if (extService != null)
return extService;
try {
- extService = new ExternalService(def, serviceName, portName, _axisConfig, _scheduler, _server);
+ if (WsdlUtils.useHTTPBinding(def, serviceName, portName)) {
+ if(__log.isDebugEnabled())__log.debug("Creating HTTP-bound external service " + serviceName);
+ extService = new HttpExternalService(def, serviceName, portName, _server);
+ } else if (WsdlUtils.useSOAPBinding(def, serviceName, portName)) {
+ if(__log.isDebugEnabled())__log.debug("Creating SOAP-bound external service " + serviceName);
+ extService = new SoapExternalService(def, serviceName, portName, _axisConfig, pconf);
+ }
} catch (Exception ex) {
__log.error("Could not create external service.", ex);
- throw new ContextException("Error creating external service.", ex);
+ throw new ContextException("Error creating external service! name:"+serviceName+", port:"+portName, ex);
}
+ // if not SOAP nor HTTP binding
+ if (extService == null) throw new ContextException("Only SOAP and HTTP binding supported!");
+
_externalServices.put(serviceName, portName, extService);
__log.debug("Created external service " + serviceName);
return extService;
@@ -424,7 +434,7 @@
}
protected ProcessStoreImpl createProcessStore(DataSource ds) {
- return new ProcessStoreImpl(ds, _odeConfig.getDAOConnectionFactory(),false);
+ return new ProcessStoreImpl(ds, _odeConfig.getDAOConnectionFactory(), _odeConfig, false);
}
protected Scheduler createScheduler() {
@@ -548,9 +558,9 @@
jdbcext = new JdbcExternalVariableModule();
jdbcext.registerDataSource("ode", _db.getDataSource());
_server.registerExternalVariableEngine(jdbcext);
-
+
}
-
+
private class ProcessStoreListenerImpl implements ProcessStoreListener {
public void onProcessStoreEvent(ProcessStoreEvent event) {
@@ -567,11 +577,8 @@
// bounce the process
_server.unregister(pse.pid);
ProcessConf pconf = _store.getProcessConfiguration(pse.pid);
- if (pconf != null)
- _server.register(pconf);
- else {
- __log.debug("slighly odd: recevied event " + pse + " for process not in store!");
- }
+ if (pconf != null) _server.register(pconf);
+ else __log.debug("slighly odd: recevied event " + pse + " for process not in store!");
break;
case DISABLED:
case UNDEPLOYED:
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEService.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEService.java?rev=658024&r1=658023&r2=658024&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEService.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEService.java Mon May 19 15:57:24 2008
@@ -23,11 +23,13 @@
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.extensions.UnknownExtensibilityElement;
+import javax.wsdl.extensions.http.HTTPAddress;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.xml.namespace.QName;
-import org.apache.axiom.om.OMElement;
-import org.apache.axiom.soap.*;
+import org.apache.axiom.soap.SOAPEnvelope;
+import org.apache.axiom.soap.SOAPFactory;
+import org.apache.axiom.soap.SOAPFault;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisService;
@@ -257,6 +259,10 @@
Element soapAddr = doc.createElementNS(Namespaces.SOAP_NS, "address");
port.appendChild(soapAddr);
soapAddr.setAttribute("location", ((SOAPAddress) extElmt).getLocationURI());
+ } else if (extElmt instanceof HTTPAddress) {
+ Element httpAddr = doc.createElementNS(Namespaces.HTTP_NS, "address");
+ port.appendChild(httpAddr);
+ httpAddr.setAttribute("location", ((HTTPAddress) extElmt).getLocationURI());
} else {
port.appendChild(doc.importNode(((UnknownExtensibilityElement) extElmt).getElement(), true));
}
Copied: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/SoapExternalService.java (from r658020, ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ExternalService.java)
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/SoapExternalService.java?p2=ode/trunk/axis2/src/main/java/org/apache/ode/axis2/SoapExternalService.java&p1=ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ExternalService.java&r1=658020&r2=658024&rev=658024&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ExternalService.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/SoapExternalService.java Mon May 19 15:57:24 2008
@@ -1,27 +1,24 @@
/*
- * 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.
- */
+ * 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.ode.axis2;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Operation;
@@ -29,6 +26,7 @@
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axis2.AxisFault;
+import org.apache.axis2.deployment.ServiceBuilder;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.OperationClient;
import org.apache.axis2.client.Options;
@@ -40,12 +38,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.axis2.util.SoapMessageConverter;
-import org.apache.ode.bpel.iapi.BpelServer;
-import org.apache.ode.bpel.iapi.Message;
-import org.apache.ode.bpel.iapi.MessageExchange;
-import org.apache.ode.bpel.iapi.PartnerRoleChannel;
-import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
-import org.apache.ode.bpel.iapi.Scheduler;
+import org.apache.ode.bpel.iapi.*;
import org.apache.ode.bpel.iapi.MessageExchange.FailureType;
import org.apache.ode.il.OMUtils;
import org.apache.ode.il.epr.EndpointFactory;
@@ -53,46 +46,40 @@
import org.apache.ode.il.epr.WSAEndpoint;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.Namespaces;
+import org.apache.ode.utils.fs.FileWatchDog;
import org.apache.ode.utils.uuid.UUID;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import java.io.File;
+import java.io.InputStream;
+
/**
* Acts as a service not provided by ODE. Used mainly for invocation as a way to maintain the WSDL decription of used services.
*
* @author Matthieu Riou <mriou at apache dot org>
*/
-public class ExternalService implements PartnerRoleChannel {
+public class SoapExternalService implements ExternalService, PartnerRoleChannel {
private static final Log __log = LogFactory.getLog(ExternalService.class);
-
private static final int EXPIRE_SERVICE_CLIENT = 30000;
-
private static ThreadLocal<CachedServiceClient> _cachedClients = new ThreadLocal<CachedServiceClient>();
private Definition _definition;
-
private QName _serviceName;
-
private String _portName;
-
private AxisConfiguration _axisConfig;
-
private SoapMessageConverter _converter;
+ private ProcessConf _pconf;
- private Scheduler _sched;
-
- private BpelServer _server;
-
- public ExternalService(Definition definition, QName serviceName, String portName, AxisConfiguration axisConfig,
- Scheduler sched, BpelServer server) throws AxisFault {
+ public SoapExternalService(Definition definition, QName serviceName, String portName,
+ AxisConfiguration axisConfig, ProcessConf pconf) throws AxisFault {
_definition = definition;
_serviceName = serviceName;
_portName = portName;
_axisConfig = axisConfig;
- _sched = sched;
_converter = new SoapMessageConverter(definition, serviceName, portName);
- _server = server;
+ _pconf = pconf;
}
public void invoke(final PartnerRoleMessageExchange odeMex) {
@@ -118,15 +105,8 @@
options.setTimeOutInMilliSeconds(60000);
options.setExceptionToBeThrownOnSOAPFault(false);
- CachedServiceClient cached = _cachedClients.get();
- long now = System.currentTimeMillis();
- if (cached == null || cached._expire < now) {
- cached = new CachedServiceClient();
- ConfigurationContext ctx = new ConfigurationContext(_axisConfig);
- cached._client = new ServiceClient(ctx, null);
- cached._expire = now + EXPIRE_SERVICE_CLIENT;
- _cachedClients.set(cached);
- }
+ CachedServiceClient cached = getCachedServiceClient();
+
final OperationClient operationClient = cached._client.createClient(isTwoWay ? ServiceClient.ANON_OUT_IN_OP
: ServiceClient.ANON_OUT_ONLY_OP);
operationClient.setOptions(options);
@@ -142,11 +122,8 @@
if (response != null && __log.isDebugEnabled())
__log.debug("Service response:\n" + response.getEnvelope().toString());
- if (flt != null) {
- reply(odeMex, operation, flt, true);
- } else {
- reply(odeMex, operation, response, response.isFault());
- }
+ if (flt != null) reply(odeMex, operation, flt, true);
+ else reply(odeMex, operation, response, response.isFault());
} catch (Throwable t) {
String errmsg = "Error sending message to Axis2 for ODE mex " + odeMex;
__log.error(errmsg, t);
@@ -163,20 +140,32 @@
}
}
+ private CachedServiceClient getCachedServiceClient() throws AxisFault {
+ CachedServiceClient cached = _cachedClients.get();
+ if (cached == null) {
+ cached = new CachedServiceClient(new File(_pconf.getBaseURI().resolve(_serviceName.getLocalPart() + ".axis2")), EXPIRE_SERVICE_CLIENT);
+ _cachedClients.set(cached);
+ }
+ try {
+ // call manually the check procedure
+ // we dont want a dedicated thread for that
+ cached.checkAndConfigure();
+ } catch (Exception e) {
+ throw AxisFault.makeFault(e);
+ }
+ return cached;
+ }
+
/**
* Extracts the action to be used for the given operation. It first checks to see
- * if a value is specified using WS-Addressing in the portType, it then falls back onto
+ * if a value is specified using WS-Addressing in the portType, it then falls back onto
* getting it from the SOAP Binding.
* @param operation the name of the operation to get the Action for
* @return The action value for the specified operation
*/
- private String getAction(String operation)
- {
+ private String getAction(String operation) {
String action = _converter.getWSAInputAction(operation);
- if (action == null || "".equals(action))
- {
- action = _converter.getSoapAction(operation);
- }
+ if (action == null || "".equals(action)) action = _converter.getSoapAction(operation);
return action;
}
@@ -296,11 +285,44 @@
}
- // INNER CLASS
- static class CachedServiceClient {
+
+ /**
+ * This class wraps a {@link org.apache.axis2.client.ServiceClient} and watches changes (deletions,creations,updates)
+ * on a Axis2 service config file named {service-name}.axis2.<p/>
+ * The {@link org.apache.axis2.client.ServiceClient} instance is created from the main Axis2 config instance and
+ * this service-specific config file.
+ */
+ class CachedServiceClient extends FileWatchDog {
ServiceClient _client;
- long _expire;
+ protected CachedServiceClient(File file, long delay) {
+ super(file, delay);
+ }
+
+ protected boolean isInitialized() throws Exception {
+ return _client != null;
+ }
+
+ protected void init() throws Exception {
+ _client = new ServiceClient(new ConfigurationContext(_axisConfig), null);
+ }
+
+ protected void doOnUpdate() throws Exception {
+ // axis2 service configuration
+ // if the config file has been modified (i.e added or updated), re-create a ServiceClient
+ // and load the new config.
+ init(); //reset the ServiceClient instance
+ try {
+ InputStream ais = file.toURI().toURL().openStream();
+ if (ais != null) {
+ if (__log.isDebugEnabled()) __log.debug("Configuring service " + _serviceName + " using: " + file);
+ ServiceBuilder builder = new ServiceBuilder(ais, new ConfigurationContext(_client.getAxisConfiguration()), _client.getAxisService());
+ builder.populateService(builder.buildOM());
+ }
+ } catch (Exception e) {
+ if (__log.isWarnEnabled()) __log.warn("Exception while configuring service: " + _serviceName, e);
+ }
+ }
}
}
Added: 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=658024&view=auto
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java (added)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java Mon May 19 15:57:24 2008
@@ -0,0 +1,153 @@
+/*
+ * 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.ode.axis2.httpbinding;
+
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.ode.utils.wsdl.WsdlUtils;
+
+import javax.wsdl.Binding;
+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 java.util.Map;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
+ */
+public class HttpBindingValidator {
+
+ private static final Messages httpMsgs = Messages.getMessages(Messages.class);
+ private static final org.apache.ode.utils.wsdl.Messages wsdlMsgs = Messages.getMessages(org.apache.ode.utils.wsdl.Messages.class);
+
+ protected Binding binding;
+ private String verb;
+
+ public HttpBindingValidator(Binding binding) {
+ this.binding = binding;
+ if (!WsdlUtils.useHTTPBinding(binding))
+ throw new IllegalArgumentException(httpMsgs.msgHttpBindingNotUsed(binding));
+ HTTPBinding httpBinding = (HTTPBinding) WsdlUtils.getBindingExtension(binding);
+ verb = httpBinding.getVerb();
+ }
+
+ public void validate() throws IllegalArgumentException {
+ validatePort();
+ }
+
+ protected void validatePort() {
+
+ if (!"GET".equalsIgnoreCase(verb)
+ && !"DELETE".equalsIgnoreCase(verb)
+ && !"PUT".equalsIgnoreCase(verb)
+ && !"POST".equalsIgnoreCase(verb)) {
+ throw new IllegalArgumentException(httpMsgs.msgUnsupportedHttpMethod(binding, verb));
+ }
+
+ // Validate the given HttpBinding
+ for (int i = 0; i < binding.getBindingOperations().size(); i++) {
+ BindingOperation bindingOperation = (BindingOperation) binding.getBindingOperations().get(i);
+ validateOperation(bindingOperation);
+ }
+ }
+
+ protected void validateOperation(BindingOperation bindingOperation) {
+ BindingOutput output = bindingOperation.getBindingOutput();
+ String outputContentType = WsdlUtils.getMimeContentType(output.getExtensibilityElements());
+ if (!outputContentType.endsWith("text/xml")) {
+ throw new IllegalArgumentException(httpMsgs.msgUnsupportedContentType(binding, bindingOperation));
+ }
+
+ Map outputParts = bindingOperation.getOperation().getOutput().getMessage().getParts();
+ if (outputParts.size() > 1) {
+ throw new IllegalArgumentException(httpMsgs.msgOnePartOnlyForOutput(binding, bindingOperation));
+ }
+
+ BindingInput input = bindingOperation.getBindingInput();
+ String inputContentType = WsdlUtils.getMimeContentType(input.getExtensibilityElements());
+
+ // multipartRelated not supported
+ if (WsdlUtils.useMimeMultipartRelated(input)) {
+ throw new IllegalArgumentException(httpMsgs.msgMimeMultipartRelatedUnsupported(binding, bindingOperation));
+ }
+
+ // only 2 content-types supported
+ if (inputContentType != null) {
+ if (!inputContentType.endsWith("text/xml") && !PostMethod.FORM_URL_ENCODED_CONTENT_TYPE.equalsIgnoreCase(inputContentType)) {
+ throw new IllegalArgumentException(httpMsgs.msgUnsupportedContentType(binding, bindingOperation));
+ }
+ Map inputParts = bindingOperation.getOperation().getInput().getMessage().getParts();
+ if (inputParts.size() > 1) {
+ if (!PostMethod.FORM_URL_ENCODED_CONTENT_TYPE.equalsIgnoreCase(inputContentType)) {
+ throw new IllegalArgumentException(httpMsgs.msgInvalidContentType(binding, bindingOperation));
+ }
+ }
+ }
+
+ if (WsdlUtils.useUrlReplacement(input)) {
+ validateUrlReplacement(bindingOperation);
+ }
+
+ // other specific validations
+ if ("GET".equalsIgnoreCase(verb) || "DELETE".equalsIgnoreCase(verb)) {
+ validateGetOrDelete(bindingOperation);
+ }
+ }
+
+ protected void validateGetOrDelete(BindingOperation bindingOperation) {
+ BindingInput input = bindingOperation.getBindingInput();
+
+ if (!WsdlUtils.useUrlEncoded(input) && !WsdlUtils.useUrlReplacement(input)) {
+ throw new IllegalArgumentException(httpMsgs.msgOnlySupportsUrlEncodedAndUrlreplacement(binding, bindingOperation));
+ }
+
+ // another test would be to check that all parts use a simple type
+ }
+
+ protected void validateUrlReplacement(BindingOperation bindingOperation) {
+ HTTPOperation httpOperation = (HTTPOperation) WsdlUtils.getOperationExtension(bindingOperation);
+ BindingInput input = bindingOperation.getBindingInput();
+ Map inputParts = bindingOperation.getOperation().getInput().getMessage().getParts();
+
+ // validate the url pattern
+ if (WsdlUtils.useUrlReplacement(input)) {
+ String locationUri = httpOperation.getLocationURI();
+ Set partNames = inputParts.keySet();
+ // Must be *exactly* one search pattern for each message part.
+ for (Iterator it = partNames.iterator(); it.hasNext();) {
+ String name = (String) it.next();
+ Pattern p = Pattern.compile(".*(\\(" + name + "\\)).*");
+ Matcher m = p.matcher(locationUri);
+ // is there a regex to do both validations in one?
+ if (!m.matches() || locationUri.split("(\\(" + name + "\\))", -1).length != 2) {
+ throw new IllegalArgumentException(httpMsgs.msgInvalidURIPattern(binding, bindingOperation, locationUri));
+ }
+ }
+ }
+
+ // another test would be to check that all parts use a simple type
+ }
+
+}
Added: 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=658024&view=auto
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java (added)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java Mon May 19 15:57:24 2008
@@ -0,0 +1,365 @@
+/*
+ * 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.ode.axis2.httpbinding;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.URIException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ode.axis2.ExternalService;
+import org.apache.ode.axis2.ODEService;
+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.MessageExchange;
+import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
+import org.apache.ode.bpel.iapi.Scheduler;
+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.Definition;
+import javax.wsdl.Operation;
+import javax.wsdl.Part;
+import javax.wsdl.Port;
+import javax.wsdl.Service;
+import javax.xml.namespace.QName;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+
+
+/**
+ * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
+ */
+public class HttpExternalService implements ExternalService {
+
+ private static final Log log = LogFactory.getLog(HttpExternalService.class);
+ private static final Messages msgs = Messages.getMessages(Messages.class);
+
+ private MultiThreadedHttpConnectionManager connections = new MultiThreadedHttpConnectionManager();
+
+ protected BpelServer server;
+ protected QName serviceName;
+ protected String portName;
+
+ protected HttpMethodBuilder methodBuilder;
+ protected WSAEndpoint endpointReference;
+
+ public HttpExternalService(Definition definition, QName serviceName, String portName, BpelServer server) {
+ this.portName = portName;
+ this.serviceName = serviceName;
+ this.server = server;
+
+ 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)
+ throw new IllegalArgumentException(msgs.msgBindingNotFound(portName));
+
+ // validate the http binding
+ if (!WsdlUtils.useHTTPBinding(port)) {
+ throw new IllegalArgumentException(msgs.msgNoHTTPBindingForPort(portName));
+ }
+ // throws an IllegalArgumentException if not valid
+ new HttpBindingValidator(binding).validate();
+
+ // initial endpoint reference
+ Element eprElmt = ODEService.genEPRfromWSDL(definition, serviceName, portName);
+ if (eprElmt == null)
+ throw new IllegalArgumentException(msgs.msgPortDefinitionNotFound(serviceName, portName));
+ endpointReference = EndpointFactory.convertToWSA(ODEService.createServiceRef(eprElmt));
+
+ methodBuilder = new HttpMethodBuilder(binding);
+ }
+
+ public String getPortName() {
+ return portName;
+ }
+
+ public QName getServiceName() {
+ return serviceName;
+ }
+
+ public void close() {
+ connections.shutdown();
+ }
+
+ public EndpointReference getInitialEndpointReference() {
+ return endpointReference;
+ }
+
+ public void invoke(PartnerRoleMessageExchange odeMex) {
+ if (log.isDebugEnabled()) log.debug("Preparing " + getClass().getSimpleName() + " invocation...");
+ try {
+ // build the http method
+ final HttpMethod method = methodBuilder.buildHttpMethod(odeMex);
+ // this callable encapsulate 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;
+ if (isTwoWay) {
+ // two way
+ executionCallable = new HttpExternalService.TwoWayCallable(method, odeMex, odeMex.getOperation());
+ executionCallable.call();
+ } else {
+ // one way, just execute and forget
+ executionCallable = new HttpExternalService.OneWayCallable(method, odeMex, odeMex.getOperation());
+ executionCallable.call();
+ odeMex.replyOneWayOk();
+ }
+ } catch (UnsupportedEncodingException e) {
+ String errmsg = "The HTTP encoding returned isn't supported " + odeMex;
+ log.error(errmsg, e);
+ odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, null);
+ } catch (Exception e) {
+ String errmsg = "Unknown HTTP call error for ODE mex " + odeMex;
+ log.error(errmsg, e);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
+ }
+
+ }
+
+
+ private class OneWayCallable implements Callable<Void> {
+ HttpMethod method;
+ PartnerRoleMessageExchange odeMex;
+ Operation operation;
+
+ public OneWayCallable(HttpMethod method, PartnerRoleMessageExchange odeMex, Operation operation) {
+ this.method = method;
+ this.odeMex = odeMex;
+ this.operation = operation;
+ }
+
+ public Void call() {
+ return callOneWay();
+ }
+
+ public Void callOneWay() {
+ try {
+ // simply execute the http method
+ HttpClient client = new HttpClient(connections);
+ 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
+ // 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();
+ // ... and process the response
+ processResponse(statusCode);
+ } catch (final IOException e) {
+ // Shit happened, recording the failure
+ try {
+ String errmsg = "Unable to execute http request : " + e.getMessage();
+ log.error(errmsg, e);
+ odeMex.replyWithFailure(MessageExchange.FailureType.COMMUNICATION_ERROR, errmsg, null);
+ } catch (Exception e1) {
+ String errmsg = "Error executing reply transaction; reply will be lost.";
+ log.error(errmsg, e);
+ }
+ } finally {
+ method.releaseConnection();
+ }
+ return null;
+ }
+
+ public void processResponse(int statusCode) {
+ // a one-way message does not care about the response
+ 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());
+ } else {
+ if (log.isDebugEnabled()) log.debug("OneWay http request ["+method.getURI()+"] status: " + method.getStatusLine());
+ }
+ } catch (URIException e) {
+ if(log.isDebugEnabled()) log.debug(e);
+ }
+ }
+ }
+
+ private class TwoWayCallable extends OneWayCallable {
+ public TwoWayCallable(HttpMethod method, PartnerRoleMessageExchange odeMex, Operation operation) {
+ super(method, odeMex, operation);
+ }
+
+ public void processResponse(final int statusCode) {
+ try {
+ if (statusCode >= 200 && statusCode < 300) {
+ success();
+ } else if (statusCode >= 300 && statusCode < 400) {
+ redirection();
+ } else if (statusCode >= 400 && statusCode < 500) {
+ badRequest();
+ } else if (statusCode >= 500 && statusCode < 600) {
+ serverError();
+ } else {
+ unmanagedStatus();
+ }
+ } catch (Exception e) {
+ String errmsg = "Error executing reply transaction; reply will be lost.";
+ log.error(errmsg, e);
+ }
+ }
+
+ private void unmanagedStatus() {
+ String errmsg = "Unmanaged Status Code! " + method.getStatusLine();
+ log.error(errmsg);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
+ }
+
+ 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()));
+
+ odeMsg.appendChild(odeMsgEl);
+ odeMsgEl.appendChild(statusEl);
+ org.apache.ode.bpel.iapi.Message response = odeMex.createMessage(type);
+ response.setMessage(odeMsgEl);
+
+ log.error("Http Server Error! " + method.getStatusLine());
+ odeMex.replyWithFault(type, response);
+ }
+
+ private void badRequest() {
+ String errmsg = "Bad Request! " + method.getStatusLine();
+ log.error(errmsg);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
+ }
+
+ private void redirection() {
+ String errmsg = "Redirections are not supported! " + method.getStatusLine();
+ log.error(errmsg);
+ odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
+ }
+
+ private void success() {
+ if (log.isDebugEnabled()) log.debug("Http Status Line=" + method.getStatusLine());
+ if (log.isDebugEnabled()) log.debug("Received response for MEX " + odeMex);
+ 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();
+ 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();
+
+ Element partElement = processBodyElement(part, bodyElement);
+ odeResponse.setPart(part.getName(), partElement);
+
+ 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);
+ }
+ }
+ } catch (IOException e) {
+ String errmsg = "Unable to get the request body : " + e.getMessage();
+ log.error(errmsg, e);
+ 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;
+ }
+ }
+
+}
+
Added: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java?rev=658024&view=auto
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java (added)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java Mon May 19 15:57:24 2008
@@ -0,0 +1,200 @@
+/*
+ * 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.ode.axis2.httpbinding;
+
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
+import org.apache.ode.il.epr.MutableEndpoint;
+import org.apache.ode.utils.DOMUtils;
+import org.apache.ode.utils.wsdl.*;
+import org.apache.ode.utils.wsdl.Messages;
+import org.apache.ode.axis2.util.UrlReplacementTransformer;
+import org.apache.ode.axis2.util.URLEncodedTransformer;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.wsdl.Operation;
+import javax.wsdl.BindingOperation;
+import javax.wsdl.Message;
+import javax.wsdl.Part;
+import javax.wsdl.BindingInput;
+import javax.wsdl.Binding;
+import javax.wsdl.extensions.http.HTTPOperation;
+import javax.wsdl.extensions.http.HTTPBinding;
+import javax.xml.namespace.QName;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import com.ibm.wsdl.PartImpl;
+
+/**
+ * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
+ */
+public class HttpMethodBuilder {
+
+ private static final String CONTENT_TYPE_TEXT_XML = "text/xml";
+ private static final Log log = LogFactory.getLog(HttpMethodBuilder.class);
+
+ protected static final org.apache.ode.utils.wsdl.Messages msgs = Messages.getMessages(Messages.class);
+ protected Binding binding;
+ protected String verb;
+
+ public HttpMethodBuilder(Binding binding) {
+ this.binding = binding;
+ HTTPBinding httpBinding = (HTTPBinding) WsdlUtils.getBindingExtension(binding);
+ this.verb = httpBinding.getVerb();
+ }
+
+
+ public HttpMethod buildHttpMethod(PartnerRoleMessageExchange odeMex) 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);
+
+ // build the http method
+ HttpMethod method = prepareHttpMethod(bindingOperation, partElements, url);
+ 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;
+ }
+
+ protected HttpMethod prepareHttpMethod(BindingOperation bindingOperation, Map<String, Element> partValues, final String rootUri) 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);
+ }
+
+ // 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;
+ }
+
+ // 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();
+ }
+
+ // some body-building...
+ if (useUrlEncoded) {
+ requestEntity = new StringRequestEntity(encodedParams, PostMethod.FORM_URL_ENCODED_CONTENT_TYPE, "UTF-8");
+ } 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);
+ }
+ 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
+ ((EntityEnclosingMethod) method).setRequestEntity(requestEntity);
+
+ } else {
+ // should not happen because of HttpBindingValidator, but never say never
+ throw new IllegalArgumentException("Unsupported HTTP method: " + verb);
+ }
+
+ // Settings common to all methods
+ 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;
+ }
+}
Added: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java?rev=658024&view=auto
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java (added)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java Mon May 19 15:57:24 2008
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ode.axis2.httpbinding;
+
+import org.apache.ode.utils.msg.MessageBundle;
+
+import javax.xml.namespace.QName;
+import javax.wsdl.Binding;
+import javax.wsdl.BindingOperation;
+import java.io.File;
+
+/**
+ * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
+ */
+public class Messages extends MessageBundle {
+
+ public String msgUnsupportedHttpMethod(Binding binding, String verb) {
+ return format("Unsupported HTTP method! binding: {0} method: {1}", binding.getQName(), verb);
+ }
+
+ public String msgHttpBindingNotUsed(Binding binding) {
+ return format("This binding does not use http:binding: {0}" + binding.getQName());
+ }
+
+ public String msgUnsupportedContentType(Binding binding, BindingOperation operation) {
+ return format("Unsupported content-type!binding: {0} operation: {1}", binding.getQName(), operation.getName());
+ }
+
+ public String msgOnePartOnlyForOutput(Binding binding, BindingOperation operation) {
+ return format("Output messages may not have more than 1 part! binding: {0} operation: {1}", binding.getQName(), operation.getName());
+ }
+
+ public String msgInvalidURIPattern() {
+ return format("Invalid URI Pattern!");
+ }
+
+ public String msgInvalidURIPattern(Binding binding, BindingOperation operation, String locationUri) {
+ return format("Invalid URI Pattern : all parts must be mentioned exactly once! binding:{0}, operation:{1}, locationUri:{2}", binding.getQName(), operation.getName(), locationUri);
+ }
+
+ public String msgMimeMultipartRelatedUnsupported(Binding binding, BindingOperation operation) {
+ return format("MimeMultipartRelated is not supported! binding:{0}, operation:{1}", binding.getQName(), operation.getName());
+ }
+
+ public String msgInvalidContentType(Binding binding, BindingOperation operation) {
+ return format("Invalid content-type! binding:{0}, operation:{1}", binding.getQName(), operation.getName());
+ }
+
+ public String msgSimpleTypeExpected(String partName){
+ return format("Simple type expected for {0}", partName);
+ }
+
+ public String msgOnlySupportsUrlEncodedAndUrlreplacement(Binding binding, BindingOperation operation) {
+ return format("Only supports urlEncoded or urlReplacement! binding:{0}, operation:{1}", binding.getQName(), operation.getName());
+ }
+
+}
Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/SoapMessageConverter.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/SoapMessageConverter.java?rev=658024&r1=658023&r2=658024&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/SoapMessageConverter.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/SoapMessageConverter.java Mon May 19 15:57:24 2008
@@ -19,6 +19,7 @@
package org.apache.ode.axis2.util;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@@ -59,11 +60,12 @@
import org.apache.axis2.namespace.Constants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.ode.axis2.Messages;
import org.apache.ode.axis2.OdeFault;
import org.apache.ode.il.OMUtils;
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.utils.stl.CollectionsX;
import org.w3c.dom.Element;
@@ -115,17 +117,17 @@
throw new OdeFault(__msgs.msgPortDefinitionNotFound(serviceName, portName));
_binding = _port.getBinding();
if (_binding == null)
- throw new OdeFault(__msgs.msgBindingNotFound(serviceName, portName));
-
+ throw new OdeFault(__msgs.msgBindingNotFound(portName));
- Collection<SOAPBinding> soapBindings = CollectionsX.filter(_binding.getExtensibilityElements(), SOAPBinding.class);
- if (soapBindings.isEmpty())
- throw new OdeFault(__msgs.msgNoSOAPBindingForPort(_portName));
- else if (soapBindings.size() > 1) {
- throw new OdeFault(__msgs.msgMultipleSoapBindingsForPort(_portName));
+ try {
+ if (!WsdlUtils.useSOAPBinding(_port)) {
+ throw new OdeFault(__msgs.msgNoSOAPBindingForPort(_portName));
+ }
+ _soapBinding = (SOAPBinding) WsdlUtils.getBindingExtension(_port);
+ } catch (IllegalArgumentException iae) {
+ throw new OdeFault(iae);
}
- _soapBinding = soapBindings.iterator().next();
String style = _soapBinding.getStyle();
_isRPC = style != null && style.equals("rpc");
Added: 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=658024&view=auto
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/URLEncodedTransformer.java (added)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/URLEncodedTransformer.java Mon May 19 15:57:24 2008
@@ -0,0 +1,55 @@
+/*
+ * 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.ode.axis2.util;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.util.EncodingUtil;
+import org.apache.ode.utils.DOMUtils;
+import org.apache.ode.axis2.httpbinding.Messages;
+import org.w3c.dom.Element;
+
+import javax.wsdl.Part;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
+ */
+public class URLEncodedTransformer {
+
+ private static final Messages msgs = Messages.getMessages(Messages.class);
+
+ public String transform(Map<String, Element> values) {
+ if (values.isEmpty()) return null;
+ NameValuePair[] pairs = new NameValuePair[values.size()];
+ int i = 0;
+ for (Map.Entry<String, Element> e : values.entrySet()) {
+ Element node = e.getValue();
+ String nodeContent = DOMUtils.isEmptyElement(node) ? "" : DOMUtils.getTextContent(node);
+ if (nodeContent == null) {
+ throw new IllegalArgumentException(msgs.msgSimpleTypeExpected(e.getKey()));
+ }
+ NameValuePair p = new NameValuePair(e.getKey(), nodeContent);
+ pairs[i++] = p;
+ }
+ return EncodingUtil.formUrlEncode(pairs, "UTF-8");
+ }
+
+}
Added: 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=658024&view=auto
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/UrlReplacementTransformer.java (added)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/util/UrlReplacementTransformer.java Mon May 19 15:57:24 2008
@@ -0,0 +1,131 @@
+/*
+ * 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.ode.axis2.util;
+
+import org.apache.commons.collections.CollectionUtils;
+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/>
+ *
+ * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
+ */
+public class UrlReplacementTransformer {
+
+ 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.
+ * @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
+ */
+ 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>();
+
+ // initial value
+ result.add(baseUri);
+
+ // replace each part exactly once
+ for (Map.Entry<String, Element> e : values.entrySet()) {
+
+ String partPattern;
+ String replacementValue;
+ {
+ String partName = e.getKey();
+ partPattern = "\\(" + partName + "\\)";
+ Element value = e.getValue();
+ replacementValue = DOMUtils.isEmptyElement(value) ? "" : DOMUtils.getTextContent(value);
+ if (replacementValue == null) {
+ throw new IllegalArgumentException(httpMsgs.msgSimpleTypeExpected(partName));
+ }
+ }
+ replace(result, partPattern, replacementValue);
+ }
+
+ // join all the array elements to form the final url
+ StringBuilder sb = new StringBuilder(128);
+ for (String aResult : result) sb.append(aResult);
+ return sb.toString();
+ }
+
+ private void 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 exactly one match...
+
+ // remove the matching segment
+ result.remove(i);
+ // replace it with the replacement value
+ result.add(i, matches[0]);
+ result.add(i + 1, replacementValue);
+ result.add(i + 2, matches[1]);
+
+ // pattern found and replaced, we're done for this pattern
+ // move on to the next part
+ break;
+ }
+ }
+ }
+
+}