You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@synapse.apache.org by ch...@apache.org on 2007/03/26 13:13:51 UTC

svn commit: r522482 - in /webservices/synapse/trunk/java/modules/core/src: main/java/org/apache/synapse/config/xml/endpoints/ main/java/org/apache/synapse/config/xml/endpoints/utils/ main/java/org/apache/synapse/endpoints/ main/java/org/apache/synapse/...

Author: chathura_ce
Date: Mon Mar 26 04:13:48 2007
New Revision: 522482

URL: http://svn.apache.org/viewvc?view=rev&rev=522482
Log:
Implemented the session affinity based load balancing for Synapse. Now Synapse can bind sessions to endpoints based on ServiceGroupID or any user defined binding mechanism. A simple client session based dispatcher, which identifies sessions based on ClientID header of request soap messages is provided to demonstrate this functionality.

Added the support for providing inline WSDLs for WSDL endpoints. Improved the WSDL endpoint factory and serializer. Added a test case to test WSDL endpoint serialization.

Added:
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointFactory.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointSerializer.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/SALoadbalanceEndpoint.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/Dispatcher.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SimpleClientSessionDispatcher.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SoapSessionDispatcher.java
    webservices/synapse/trunk/java/modules/core/src/test/resources/esbservice.wsdl
Modified:
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractFactory.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractSerializer.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointFactory.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointSerializer.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/WSDL11EndpointBuilder.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/WSDLEndpoint.java
    webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/builtin/SendMediator.java
    webservices/synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/config/xml/SendMediatorSerializationTest.java

Modified: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractFactory.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractFactory.java?view=diff&rev=522482&r1=522481&r2=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractFactory.java (original)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractFactory.java Mon Mar 26 04:13:48 2007
@@ -62,8 +62,15 @@
         OMElement lbElement = configElement.getFirstChildWithName
                 (new QName(Constants.SYNAPSE_NAMESPACE, "loadbalance"));
         if (lbElement != null) {
-            EndpointFactory endpointFactory = LoadbalanceEndpointFactory.getInstance();
-            return endpointFactory;
+            OMElement sessionElement = configElement.
+                    getFirstChildWithName(new QName(Constants.SYNAPSE_NAMESPACE, "session"));
+            if (sessionElement != null) {
+                EndpointFactory endpointFactory = SALoadbalanceEndpointFactory.getInstance();
+                return endpointFactory;
+            } else {
+                EndpointFactory endpointFactory = LoadbalanceEndpointFactory.getInstance();
+                return endpointFactory;
+            }            
         }
 
         OMElement foElement = configElement.getFirstChildWithName

Modified: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractSerializer.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractSerializer.java?view=diff&rev=522482&r1=522481&r2=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractSerializer.java (original)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/EndpointAbstractSerializer.java Mon Mar 26 04:13:48 2007
@@ -45,6 +45,8 @@
             return new IndirectEndpointSerializer();
         } else if (endpoint instanceof LoadbalanceEndpoint) {
             return new LoadbalanceEndpointSerializer();
+        } else if (endpoint instanceof SALoadbalanceEndpoint) {
+            return new SALoadbalanceEndpointSerializer();
         } else if (endpoint instanceof FailoverEndpoint) {
             return new FailoverEndpointSerializer();
         }

Added: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointFactory.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointFactory.java?view=auto&rev=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointFactory.java (added)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointFactory.java Mon Mar 26 04:13:48 2007
@@ -0,0 +1,181 @@
+/*
+ *  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.synapse.config.xml.endpoints;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.synapse.endpoints.Endpoint;
+import org.apache.synapse.endpoints.LoadbalanceEndpoint;
+import org.apache.synapse.endpoints.SALoadbalanceEndpoint;
+import org.apache.synapse.endpoints.dispatch.Dispatcher;
+import org.apache.synapse.endpoints.dispatch.SoapSessionDispatcher;
+import org.apache.synapse.endpoints.dispatch.SimpleClientSessionDispatcher;
+import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
+import org.apache.synapse.Constants;
+import org.apache.synapse.SynapseException;
+import org.apache.synapse.config.xml.endpoints.utils.LoadbalanceAlgorithmFactory;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMAttribute;
+import org.apache.axiom.om.OMNode;
+
+import javax.xml.namespace.QName;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Creates SALoadbalanceEndpoint from a XML configuration.
+ *
+ * <endpoint [name="name"]>
+ *    <session type="soap | ..other session types.." />
+ *    <loadbalance policy="policy">
+ *       <endpoint>+
+ *    </loadbalance>
+ * </endpoint>
+ */
+public class SALoadbalanceEndpointFactory implements EndpointFactory {
+
+    private static Log log = LogFactory.getLog(LoadbalanceEndpointFactory.class);
+
+    private static SALoadbalanceEndpointFactory instance = new SALoadbalanceEndpointFactory();
+
+    private SALoadbalanceEndpointFactory() {}
+
+    public static SALoadbalanceEndpointFactory getInstance() {
+        return instance;
+    }
+
+    public Endpoint createEndpoint(OMElement epConfig, boolean anonymousEndpoint) {
+
+        // create the endpoint, manager and the algorithms
+        SALoadbalanceEndpoint loadbalanceEndpoint = new SALoadbalanceEndpoint();
+
+        // get the session for this endpoint
+        OMElement sessionElement = epConfig.
+                getFirstChildWithName(new QName(Constants.SYNAPSE_NAMESPACE, "session"));
+        if (sessionElement != null) {
+
+            String type = sessionElement.getAttributeValue(new QName("type"));
+
+            if (type.equalsIgnoreCase("soap")) {
+                Dispatcher soapDispatcher = new SoapSessionDispatcher();
+                loadbalanceEndpoint.setDispatcher(soapDispatcher);
+
+            } else if (type.equalsIgnoreCase("simpleClientSession")) {
+                Dispatcher csDispatcher = new SimpleClientSessionDispatcher();
+                loadbalanceEndpoint.setDispatcher(csDispatcher);
+            }
+        } else {
+            handleException("Session affinity endpoints should have a session element in the configuration.");
+        }
+
+        // set endpoint name
+        OMAttribute name = epConfig.getAttribute(new QName(
+                org.apache.synapse.config.xml.Constants.NULL_NAMESPACE, "name"));
+
+        if (name != null) {
+            loadbalanceEndpoint.setName(name.getAttributeValue());
+        }
+
+        OMElement loadbalanceElement =  null;
+        loadbalanceElement = epConfig.getFirstChildWithName
+                (new QName(Constants.SYNAPSE_NAMESPACE, "loadbalance"));
+
+        if(loadbalanceElement != null) {
+
+            // set endpoints
+            ArrayList endpoints = getEndpoints(loadbalanceElement, loadbalanceEndpoint);
+            loadbalanceEndpoint.setEndpoints(endpoints);
+
+            // set load balance algorithm
+            LoadbalanceAlgorithm algorithm = LoadbalanceAlgorithmFactory.
+                    createLoadbalanceAlgorithm(loadbalanceElement, endpoints);
+            loadbalanceEndpoint.setAlgorithm(algorithm);
+
+            // set abandon time
+            //long abandonTime = 0;
+            //OMAttribute atAttribute = loadbalanceElement.getAttribute
+            //        (new QName(null, org.apache.synapse.config.xml.Constants.RETRY_AFTER_FAILURE_TIME));
+            //if(atAttribute != null) {
+            //    String at = atAttribute.getAttributeValue();
+            //    abandonTime = Long.parseLong(at);
+            //    loadbalanceEndpoint.setAbandonTime(abandonTime);
+            //}
+
+            //long retryInterval = 30000;
+            //OMAttribute riAttribute = loadbalanceElement.getAttribute
+            //        (new QName(null, Constants.RETRY_INTERVAL));
+            //
+            //if(riAttribute != null) {
+            //    String ri = riAttribute.getAttributeValue();
+            //    retryInterval = Long.parseLong(ri);
+            //}
+
+            //int maximumRetries = 0;
+            //OMAttribute mrAttribute = loadbalanceElement.getAttribute
+            //        (new QName(null, Constants.MAXIMUM_RETRIES));
+            //
+            //if(mrAttribute != null) {
+            //    String mr = mrAttribute.getAttributeValue();
+            //    maximumRetries = Integer.parseInt(mr);
+            //}
+
+            return loadbalanceEndpoint;
+        }
+
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public Object getObjectFromOMNode(OMNode om) {
+        if (om instanceof OMElement) {
+            return createEndpoint((OMElement) om, false);
+        } else {
+            handleException("Invalid XML configuration for an Endpoint. OMElement expected");
+        }
+        return null;
+    }
+
+    private ArrayList getEndpoints(OMElement loadbalanceElement, Endpoint parent) {
+
+        ArrayList endpoints = new ArrayList();
+        Iterator iter = loadbalanceElement.getChildrenWithName
+                (org.apache.synapse.config.xml.Constants.ENDPOINT_ELT);
+        while (iter.hasNext()) {
+
+            OMElement endptElem = (OMElement) iter.next();
+
+            EndpointFactory epFac = EndpointAbstractFactory.getEndpointFactroy(endptElem);
+            Endpoint endpoint = epFac.createEndpoint(endptElem, true);
+            endpoint.setParentEndpoint(parent);
+            endpoints.add(endpoint);
+        }
+
+        return endpoints;
+    }
+
+    private static void handleException(String msg) {
+        log.error(msg);
+        throw new SynapseException(msg);
+    }
+
+    private static void handleException(String msg, Exception e) {
+        log.error(msg, e);
+        throw new SynapseException(msg, e);
+    }
+}

Added: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointSerializer.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointSerializer.java?view=auto&rev=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointSerializer.java (added)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/SALoadbalanceEndpointSerializer.java Mon Mar 26 04:13:48 2007
@@ -0,0 +1,102 @@
+/*
+ *  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.synapse.config.xml.endpoints;
+
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.synapse.endpoints.Endpoint;
+import org.apache.synapse.endpoints.SALoadbalanceEndpoint;
+import org.apache.synapse.endpoints.dispatch.Dispatcher;
+import org.apache.synapse.endpoints.dispatch.SoapSessionDispatcher;
+import org.apache.synapse.endpoints.dispatch.SimpleClientSessionDispatcher;
+import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
+import org.apache.synapse.endpoints.algorithms.RoundRobin;
+import org.apache.synapse.SynapseException;
+import org.apache.synapse.Constants;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.xml.namespace.QName;
+import java.util.ArrayList;
+
+public class SALoadbalanceEndpointSerializer implements EndpointSerializer {
+
+    private static final Log log = LogFactory.getLog(SALoadbalanceEndpointSerializer.class);
+
+    private OMFactory fac = null;
+
+    public OMElement serializeEndpoint(Endpoint endpoint) {
+
+        if (!(endpoint instanceof SALoadbalanceEndpoint)) {
+            handleException("Invalid endpoint type for serializing. " +
+                    "Expected: SALoadbalanceEndpoint Found: " + endpoint.getClass().getName());
+        }
+
+        SALoadbalanceEndpoint loadbalanceEndpoint = (SALoadbalanceEndpoint) endpoint;
+
+        fac = OMAbstractFactory.getOMFactory();
+        OMElement endpointElement = fac.createOMElement("endpoint", Constants.SYNAPSE_OMNAMESPACE);
+
+        String name = loadbalanceEndpoint.getName();
+        if (name != null) {
+            endpointElement.addAttribute("name", name, null);
+        }
+
+        Dispatcher dispatcher = loadbalanceEndpoint.getDispatcher();
+
+        if (dispatcher instanceof SoapSessionDispatcher) {
+            OMElement sessionElement = fac.createOMElement("session", Constants.SYNAPSE_OMNAMESPACE);
+            sessionElement.addAttribute("type", "soap", null);
+            endpointElement.addChild(sessionElement);
+
+        } else if (dispatcher instanceof SimpleClientSessionDispatcher) {
+            OMElement sessionElement = fac.createOMElement("session", Constants.SYNAPSE_OMNAMESPACE);
+            sessionElement.addAttribute("type", "clientSession", null);
+            endpointElement.addChild(sessionElement);
+        }
+
+        OMElement loadbalanceElement = fac.createOMElement("loadbalance", Constants.SYNAPSE_OMNAMESPACE);
+        endpointElement.addChild(loadbalanceElement);
+
+        LoadbalanceAlgorithm algorithm = loadbalanceEndpoint.getAlgorithm();
+        String algorithmName = "roundRobin";
+        if (algorithm instanceof RoundRobin) {
+             algorithmName = "roundRobin";
+        }
+        loadbalanceElement.addAttribute("algorithm", algorithmName, null);
+
+        ArrayList endpoints = loadbalanceEndpoint.getEndpoints();
+        for (int i = 0; i < endpoints.size(); i++) {
+            Endpoint childEndpoint = (Endpoint) endpoints.get(i);
+            EndpointSerializer serializer = EndpointAbstractSerializer.
+                    getEndpointSerializer(childEndpoint);
+            OMElement aeElement = serializer.serializeEndpoint(childEndpoint);
+            loadbalanceElement.addChild(aeElement);
+        }
+
+        return endpointElement;
+    }
+
+    private void handleException(String msg) {
+        log.error(msg);
+        throw new SynapseException(msg);
+    }
+}

Modified: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointFactory.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointFactory.java?view=diff&rev=522482&r1=522481&r2=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointFactory.java (original)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointFactory.java Mon Mar 26 04:13:48 2007
@@ -41,7 +41,7 @@
  * Creates an WSDL based endpoint from a XML configuration.
  *
  * <endpoint [name="name"]>
- *    <wsdl uri="wsdl uri" service="service name" port="port name">
+ *    <wsdl uri="wsdl uri" service="service name" port="port name"> 
  *       .. extensibility ..
  *    </wsdl>
  * </endpoint>
@@ -85,28 +85,71 @@
 
         if (wsdlElement != null) {
 
+            EndpointDefinition endpoint = null;
+
+            // get the service name and port name. at this point we should not worry about the presence
+            // of those parameters. they are handled by corresponding WSDL builders.
+            String serviceName = wsdlElement.getAttributeValue(new QName("service"));
+            String portName = wsdlElement.getAttributeValue(new QName("port"));
+
+            // check if wsdl is supplied as a URI
             String wsdlURI = wsdlElement.getAttributeValue(new QName("uri"));
-            try {
-                EndpointDefinition endpoint = new EndpointDefinition();
 
-                URL wsdlURL = new URL(wsdlURI);
-                StAXOMBuilder OMBuilder = new StAXOMBuilder(wsdlURL.openConnection().getInputStream());
-                OMElement docElement = OMBuilder.getDocumentElement();
-                String ns = docElement.getNamespace().getNamespaceURI();
-
-                if (org.apache.axis2.namespace.Constants.NS_URI_WSDL11.equals(ns)) {
-                    endpoint = new WSDL11EndpointBuilder().
-                            createEndpointDefinitionFromWSDL(wsdlElement);
-                } else if (WSDLConstants.WSDL20_2006Constants.DEFAULT_NAMESPACE_URI.equals(ns)) {
-                    //endpoint = new WSDL20EndpointBuilder().
-                    //        createEndpointDefinitionFromWSDL(wsdlElement);
-                    handleException("WSDL 2.0 Endpoints are currently not supported");
+            // set serviceName and portName in the endpoint. it does not matter if these are
+            // null at this point. we are setting them only for serialization purpose.
+            wsdlEndpoint.setServiceName(serviceName);
+            wsdlEndpoint.setPortName(portName);
+
+            if (wsdlURI != null) {
+                wsdlEndpoint.setWsdlURI(wsdlURI);
+
+                try {
+                    URL wsdlURL = new URL(wsdlURI);
+                    StAXOMBuilder OMBuilder = new StAXOMBuilder(wsdlURL.openConnection().getInputStream());
+                    OMElement docElement = OMBuilder.getDocumentElement();
+                    String ns = docElement.getNamespace().getNamespaceURI();
+
+                    if (org.apache.axis2.namespace.Constants.NS_URI_WSDL11.equals(ns)) {
+                        endpoint = new WSDL11EndpointBuilder().
+                                createEndpointDefinitionFromWSDL(wsdlURI, serviceName, portName);
+
+                    } else if (WSDLConstants.WSDL20_2006Constants.DEFAULT_NAMESPACE_URI.equals(ns)) {
+                        //endpoint = new WSDL20EndpointBuilder().
+                        //        createEndpointDefinitionFromWSDL(wsdlElement);
+                        handleException("WSDL 2.0 Endpoints are currently not supported");
+                    }
+
+                } catch (Exception e) {
+                    handleException("Couldn't create endpoint from the given WSDL URI.");
                 }
+            }
+
+            // check if the wsdl 1.1 document is suppled inline
+            OMElement definitionElement = wsdlElement.getFirstChildWithName
+                    (new QName(org.apache.axis2.namespace.Constants.NS_URI_WSDL11, "definitions"));
+            if (endpoint == null && definitionElement != null) {
+                wsdlEndpoint.setWsdlDoc(definitionElement);
+
+                endpoint = new WSDL11EndpointBuilder().
+                        createEndpointDefinitionFromWSDL(definitionElement, serviceName, portName);
+            }
 
+            // check if a wsdl 2.0 document is supplied inline
+            OMElement descriptionElement = wsdlElement.getFirstChildWithName
+                    (new QName(org.apache.axis2.namespace.Constants.NS_URI_WSDL11, "description"));
+            if (endpoint == null && descriptionElement != null) {
+                wsdlEndpoint.setWsdlDoc(descriptionElement);
+
+                handleException("WSDL 2.0 Endpoints are currently not supported.");
+            }
+
+            if (endpoint != null) {
+                // for now, QOS information has to be provided explicitly.
+                extractQOSInformation(endpoint, wsdlElement);
 
                 wsdlEndpoint.setEndpointDefinition(endpoint);
-            } catch (Exception e1) {
-                handleException("Unable to create endpoint from the given WSDL.", e1);
+            } else {
+                handleException("WSDL is not specified for WSDL endpoint.");
             }
         }
 
@@ -121,5 +164,69 @@
     private static void handleException(String msg, Exception e) {
         log.error(msg, e);
         throw new SynapseException(msg, e);
+    }
+
+    private void extractQOSInformation(EndpointDefinition endpointDefinition, OMElement wsdlElement) {
+
+        OMAttribute format = wsdlElement.getAttribute(new QName(
+                org.apache.synapse.config.xml.Constants.NULL_NAMESPACE, "format"));
+        OMAttribute optimize = wsdlElement.getAttribute(new QName(
+                org.apache.synapse.config.xml.Constants.NULL_NAMESPACE, "optimize"));
+
+        if (format != null)
+        {
+            String forceValue = format.getAttributeValue().trim().toLowerCase();
+            if (forceValue.equals("pox")) {
+                endpointDefinition.setForcePOX(true);
+            } else if (forceValue.equals("soap")) {
+                endpointDefinition.setForceSOAP(true);
+            } else {
+                handleException("force value -\""+forceValue+"\" not yet implemented");
+            }
+        }
+
+        if (optimize != null && optimize.getAttributeValue().length() > 0) {
+            String method = optimize.getAttributeValue().trim();
+            if ("mtom".equalsIgnoreCase(method)) {
+                endpointDefinition.setUseMTOM(true);
+            } else if ("swa".equalsIgnoreCase(method)) {
+                endpointDefinition.setUseSwa(true);
+            }
+        }
+
+        OMElement wsAddr = wsdlElement.getFirstChildWithName(new QName(
+                org.apache.synapse.config.xml.Constants.SYNAPSE_NAMESPACE, "enableAddressing"));
+        if (wsAddr != null) {
+            endpointDefinition.setAddressingOn(true);
+            String useSepList = wsAddr.getAttributeValue(new QName(
+                    "separateListener"));
+            if (useSepList != null) {
+                if (useSepList.trim().toLowerCase().startsWith("tr")
+                        || useSepList.trim().startsWith("1")) {
+                    endpointDefinition.setUseSeparateListener(true);
+                }
+            }
+        }
+
+        OMElement wsSec = wsdlElement.getFirstChildWithName(new QName(
+                org.apache.synapse.config.xml.Constants.SYNAPSE_NAMESPACE, "enableSec"));
+        if (wsSec != null) {
+            endpointDefinition.setSecurityOn(true);
+            OMAttribute policy = wsSec.getAttribute(new QName(
+                    org.apache.synapse.config.xml.Constants.NULL_NAMESPACE, "policy"));
+            if (policy != null) {
+                endpointDefinition.setWsSecPolicyKey(policy.getAttributeValue());
+            }
+        }
+        OMElement wsRm = wsdlElement.getFirstChildWithName(new QName(
+                org.apache.synapse.config.xml.Constants.SYNAPSE_NAMESPACE, "enableRM"));
+        if (wsRm != null) {
+            endpointDefinition.setReliableMessagingOn(true);
+            OMAttribute policy = wsRm.getAttribute(new QName(
+                    org.apache.synapse.config.xml.Constants.NULL_NAMESPACE, "policy"));
+            if (policy != null) {
+                endpointDefinition.setWsRMPolicyKey(policy.getAttributeValue());
+            }
+        }
     }
 }

Modified: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointSerializer.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointSerializer.java?view=diff&rev=522482&r1=522481&r2=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointSerializer.java (original)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/WSDLEndpointSerializer.java Mon Mar 26 04:13:48 2007
@@ -27,6 +27,8 @@
 import org.apache.synapse.SynapseException;
 import org.apache.synapse.Constants;
 import org.apache.synapse.endpoints.utils.EndpointDefinition;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
  * Serializes an WSDL based endpoint to an XML configuration.
@@ -39,7 +41,9 @@
  */
 public class WSDLEndpointSerializer implements EndpointSerializer {
 
-   private OMFactory fac = null;
+    private static Log log = LogFactory.getLog(WSDLEndpointSerializer.class);
+
+    private OMFactory fac = null;
 
     public OMElement serializeEndpoint(Endpoint endpoint) {
 
@@ -56,15 +60,88 @@
             endpointElement.addAttribute("name", name, null);
         }
 
+        OMElement wsdlElement = fac.createOMElement("wsdl", Constants.SYNAPSE_OMNAMESPACE);
+        String serviceName = wsdlEndpoint.getServiceName();
+        if (serviceName != null) {
+            wsdlElement.addAttribute("service", serviceName, null);
+        }
+
+        String portName = wsdlEndpoint.getPortName();
+        if (portName != null) {
+            wsdlElement.addAttribute("port", portName, null);
+        }
+
+        String uri = wsdlEndpoint.getWsdlURI();
+        if (uri != null) {
+            wsdlElement.addAttribute("uri", uri, null);
+        }
+
+        OMElement wsdlDoc = wsdlEndpoint.getWsdlDoc();
+        if (wsdlDoc != null) {
+            wsdlElement.addChild(wsdlDoc);
+        }
+
+        // currently, we have to get QOS information from the endpoint definition and set them as
+        // special elements under the wsdl element. in future, these information should be
+        // extracted from the wsdl.
         EndpointDefinition epAddress = wsdlEndpoint.getEndpointDefinition();
-        OMElement wsdlElement = serializeWSDL(epAddress);
+        serializeQOSInformation(epAddress, wsdlElement);
+
         endpointElement.addChild(wsdlElement);
 
         return endpointElement;
     }
 
-    public OMElement serializeWSDL(EndpointDefinition epDef) {
+    public void serializeQOSInformation
+            (EndpointDefinition endpointDefinition, OMElement wsdlElement) {
+
+        if (endpointDefinition.isForcePOX()) {
+            wsdlElement.addAttribute(fac.createOMAttribute("format", null, "pox"));
+        } else if (endpointDefinition.isForceSOAP()) {
+            wsdlElement.addAttribute(fac.createOMAttribute("format", null, "soap"));
+        }        
+
+        int isEnableStatistics = endpointDefinition.getStatisticsEnable();
+        String statisticsValue = null;
+        if (isEnableStatistics == org.apache.synapse.Constants.STATISTICS_ON) {
+            statisticsValue = org.apache.synapse.config.xml.Constants.STATISTICS_ENABLE;
+        } else if (isEnableStatistics == org.apache.synapse.Constants.STATISTICS_OFF) {
+            statisticsValue = org.apache.synapse.config.xml.Constants.STATISTICS_DISABLE;
+        }
+        if (statisticsValue != null) {
+            wsdlElement.addAttribute(fac.createOMAttribute(
+                    org.apache.synapse.config.xml.Constants.STATISTICS_ATTRIB_NAME, null, statisticsValue));
+        }
+        if (endpointDefinition.isAddressingOn()) {
+            OMElement addressing = fac.createOMElement("enableAddressing", Constants.SYNAPSE_OMNAMESPACE);
+            if (endpointDefinition.isUseSeparateListener()) {
+                addressing.addAttribute(fac.createOMAttribute(
+                        "separateListener", null, "true"));
+            }
+            wsdlElement.addChild(addressing);
+        }
+
+        if (endpointDefinition.isReliableMessagingOn()) {
+            OMElement rm = fac.createOMElement("enableRM", Constants.SYNAPSE_OMNAMESPACE);
+            if (endpointDefinition.getWsRMPolicyKey() != null) {
+                rm.addAttribute(fac.createOMAttribute(
+                        "policy", null, endpointDefinition.getWsRMPolicyKey()));
+            }
+            wsdlElement.addChild(rm);
+        }
+
+        if (endpointDefinition.isSecurityOn()) {
+            OMElement sec = fac.createOMElement("enableSec", Constants.SYNAPSE_OMNAMESPACE);
+            if (endpointDefinition.getWsSecPolicyKey() != null) {
+                sec.addAttribute(fac.createOMAttribute(
+                        "policy", null, endpointDefinition.getWsSecPolicyKey()));
+            }
+            wsdlElement.addChild(sec);
+        }
+    }
 
-        return null;
+    private static void handleException(String msg) {
+        log.error(msg);
+        throw new SynapseException(msg);
     }
 }

Modified: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/WSDL11EndpointBuilder.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/WSDL11EndpointBuilder.java?view=diff&rev=522482&r1=522481&r2=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/WSDL11EndpointBuilder.java (original)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/WSDL11EndpointBuilder.java Mon Mar 26 04:13:48 2007
@@ -22,6 +22,9 @@
 import org.apache.synapse.endpoints.utils.EndpointDefinition;
 import org.apache.synapse.SynapseException;
 import org.apache.axiom.om.OMElement;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
 
 import javax.wsdl.factory.WSDLFactory;
 import javax.wsdl.WSDLException;
@@ -32,71 +35,133 @@
 import javax.wsdl.extensions.soap12.SOAP12Address;
 import javax.wsdl.xml.WSDLReader;
 import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
 import java.util.List;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 
 /**
  * Builds the EndpointDefinition containing the details for an epr using a WSDL 1.1 document.
  */
 public class WSDL11EndpointBuilder {
 
-    public EndpointDefinition createEndpointDefinitionFromWSDL(OMElement wsdlElement) {
+    private static Log log = LogFactory.getLog(WSDL11EndpointBuilder.class);
 
-        EndpointDefinition endpointDefinition = null;
-        String serviceURL = null;
+    /**
+     * Creates an EndpointDefinition for WSDL endpoint from an inline WSDL supplied in the WSDL
+     * endpoint configuration.
+     *
+     * @param wsdl OMElement representing the inline WSDL
+     * @param service Service of the endpoint
+     * @param port Port of the endpoint
+     *
+     * @return EndpointDefinition containing the information retrieved from the WSDL
+     */
+    public EndpointDefinition createEndpointDefinitionFromWSDL
+            (OMElement wsdl, String service, String port) {
 
-        String wsdlURI = wsdlElement.getAttributeValue(new QName("uri"));
-        String serviceName = wsdlElement.getAttributeValue(new QName("service"));
-        String portName = wsdlElement.getAttributeValue(new QName("port"));
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try {
+            wsdl.serialize(baos);
+            InputStream in = new ByteArrayInputStream(baos.toByteArray());
+            InputSource inputSource = new InputSource(in);
+            WSDLFactory fac = WSDLFactory.newInstance();
+            WSDLReader reader = fac.newWSDLReader();
+            Definition definition = reader.readWSDL(null, inputSource);
 
-        if (wsdlURI == null) {
-            throw new SynapseException("WSDL is not specified.");
-        }
+            return createEndpointDefinitionFromWSDL(definition, service, port);
 
-        if (serviceName == null) {
-            throw new SynapseException("Service is not specified.");
+        } catch (XMLStreamException e) {
+            handleException("Error retrieving the WSDL definition from the inline WSDL.");
+        } catch (WSDLException e) {
+            handleException("Error retrieving the WSDL definition from the inline WSDL.");
         }
 
-        if (portName == null) {
-            throw new SynapseException("Port is not specified.");
-        }
+        return null;
+    }
+
+    /**
+     * Creates an EndpointDefinition for WSDL endpoint from a WSDL document residing in the given URI.
+     *
+     * @param wsdlURI URI of the WSDL document
+     * @param service Service of the endpoint
+     * @param port Port of the endpoint
+     *
+     * @return EndpointDefinition containing the information retrieved from the WSDL
+     */
+    public EndpointDefinition createEndpointDefinitionFromWSDL
+            (String wsdlURI, String service, String port) {
 
         try {
             WSDLFactory fac = WSDLFactory.newInstance();
             WSDLReader reader = fac.newWSDLReader();
             Definition definition = reader.readWSDL(wsdlURI);
-            String tns = definition.getTargetNamespace();
-            Service service = definition.getService(new QName(tns, serviceName));
-            if (service != null) {
-                Port port = service.getPort(portName);
-                if (port != null) {
-                    List ext = port.getExtensibilityElements();
-                    for (int i = 0; i < ext.size(); i++) {
-                        Object o = ext.get(i);
-                        if (o instanceof SOAPAddress) {
-                            SOAPAddress address = (SOAPAddress) o;
-                            serviceURL = address.getLocationURI();
-                            break;
-                        } else if (o instanceof SOAP12Address) {
-                            SOAP12Address address = (SOAP12Address) o;
-                            serviceURL = address.getLocationURI();
-                            break;
-                        }
+
+            return createEndpointDefinitionFromWSDL(definition, service, port);
+
+        } catch (WSDLException e) {
+            handleException("Error retrieving the WSDL definition from the WSDL URI.");
+        }
+
+        return null;
+    }
+
+    private EndpointDefinition createEndpointDefinitionFromWSDL
+            (Definition definition, String serviceName, String portName) {
+
+        if (definition == null) {
+            handleException("WSDL is not specified.");
+        }
+
+        if (serviceName == null) {
+            handleException("Service is not specified.");
+        }
+
+        if (portName == null) {
+            handleException("Port is not specified.");
+        }
+
+
+        String serviceURL = null;
+        String tns = definition.getTargetNamespace();
+        Service service = definition.getService(new QName(tns, serviceName));
+        if (service != null) {
+            Port port = service.getPort(portName);
+            if (port != null) {
+                List ext = port.getExtensibilityElements();
+                for (int i = 0; i < ext.size(); i++) {
+                    Object o = ext.get(i);
+                    if (o instanceof SOAPAddress) {
+                        SOAPAddress address = (SOAPAddress) o;
+                        serviceURL = address.getLocationURI();
+                        break;
+                    } else if (o instanceof SOAP12Address) {
+                        SOAP12Address address = (SOAP12Address) o;
+                        serviceURL = address.getLocationURI();
+                        break;
                     }
                 }
             }
-
-        } catch (WSDLException e) {
-            throw new SynapseException("Unable create endpoint definition from WSDL.");
         }
 
         if (serviceURL != null) {
-            endpointDefinition = new EndpointDefinition();
+            EndpointDefinition endpointDefinition = new EndpointDefinition();
             endpointDefinition.setAddress(serviceURL);
 
-            // todo: determine this using wsdl and policy
-            endpointDefinition.setAddressingOn(true);
+            // todo: determine this using wsdl and policy                                    
+
+            return endpointDefinition;
+
+        } else {
+            handleException("Couldn't retrieve endpoint information from the WSDL.");
         }
 
-        return endpointDefinition;
+        return null;
+    }
+
+    private static void handleException(String msg) {
+        log.error(msg);
+        throw new SynapseException(msg);
     }
 }

Added: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/SALoadbalanceEndpoint.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/SALoadbalanceEndpoint.java?view=auto&rev=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/SALoadbalanceEndpoint.java (added)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/SALoadbalanceEndpoint.java Mon Mar 26 04:13:48 2007
@@ -0,0 +1,191 @@
+/*
+ *  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.synapse.endpoints;
+
+import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
+import org.apache.synapse.endpoints.dispatch.Dispatcher;
+import org.apache.synapse.MessageContext;
+import org.apache.synapse.FaultHandler;
+import org.apache.synapse.core.axis2.Axis2MessageContext;
+import org.apache.axis2.context.OperationContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SALoadbalanceEndpoint supports session affinity based load balancing. Each of this endpoint
+ * maintains a list of dispatchers. These dispatchers will be updated for both request (for client
+ * initiated sessions) and response (for server initiated sessions). Once updated, each dispatcher
+ * will check if has already encountered that session. If not, it will update the
+ * session -> endpoint map. To update sessions for response messages, all SALoadbalanceEndpoint
+ * objects are kept in a global property. When a message passes through SALoadbalanceEndpoints, each
+ * endpoint appends its "Synapse unique ID" to the operation context. Once the response for that
+ * message arrives, response sender checks first endpoint of the endpoint sequence from the operation
+ * context and get that endpoint from the above mentioned global property. Then it will invoke
+ * updateSession(...) method of that endpoint. After that, each endpoint will call updateSession(...)
+ * method of their appropriate child endpoint, so that all the sending endpoints for the session will
+ * be updated.
+ *
+ * This endpoint gets the target endpoint first from the dispatch manager, which will ask all listed
+ * dispatchers for a matching session. If a matching session is found it will just invoke the send(...)
+ * method of that endpoint. If not it will find an endpoint using the loadbalance policy and send to
+ * that endpoint.
+ */
+public class SALoadbalanceEndpoint implements Endpoint {
+
+    private ArrayList endpoints = null;
+    private LoadbalanceAlgorithm algorithm = null;
+    private String name = null;
+    private boolean active = true;
+    private Endpoint parentEndpoint = null;
+    private Dispatcher dispatcher = null;
+
+    public void send(MessageContext synMessageContext) {
+
+        Endpoint endpoint = null;
+
+        // first check if this session is associated with a session. if so, get the endpoint
+        // associated for that session.
+        endpoint = dispatcher.getEndpoint(synMessageContext);
+        if (endpoint == null) {
+            // there is no endpoint associated with this session. get a new endpoint using the
+            // load balance policy.
+            endpoint = algorithm.getNextEndpoint(synMessageContext);
+
+            // this is a start of a new session. so update session map.
+            if (dispatcher.isServerInitiatedSession()) {
+                // add this endpoint to the endpoint sequence of operation context.
+                Axis2MessageContext axis2MsgCtx = (Axis2MessageContext) synMessageContext;
+                OperationContext opCtx = axis2MsgCtx.getAxis2MessageContext().getOperationContext();
+                Object o = opCtx.getProperty("endpointList");
+                if (o != null) {
+                    List endpointList = (List) o;
+                    endpointList.add(this);
+
+                    // if the next endpoint is not a session affinity one, endpoint sequence ends
+                    // here. but we have to add the next endpoint to the list.
+                    if (!(endpoint instanceof SALoadbalanceEndpoint)) {
+                        endpointList.add(endpoint);
+                    }
+                } else {
+                    // this is the first endpoint in the heirachy. so create the queue and insert
+                    // this as the first element.
+                    List endpointList = new ArrayList();
+                    endpointList.add(this);
+
+                    // if the next endpoint is not a session affinity one, endpoint sequence ends
+                    // here. but we have to add the next endpoint to the list.
+                    if (!(endpoint instanceof SALoadbalanceEndpoint)) {
+                        endpointList.add(endpoint);
+                    }
+
+                    opCtx.setProperty("endpointList", endpointList);
+                }
+
+            } else {
+                dispatcher.updateSession(synMessageContext, endpoint);
+            }
+        }
+
+        if (endpoint != null) {
+            endpoint.send(synMessageContext);
+        } else {
+            if (parentEndpoint != null) {
+                parentEndpoint.onChildEndpointFail(this, synMessageContext);
+            } else {
+                Object o = synMessageContext.getFaultStack().pop();
+                ((FaultHandler) o).handleFault(synMessageContext);
+            }
+        }
+    }
+
+    /**
+     * This will be called for the response of the first message of each server initiated session.
+     *
+     * @param responseMsgCtx
+     * @param endpointList
+     */
+    public void updateSession(MessageContext responseMsgCtx, List endpointList) {
+        Endpoint endpoint = (Endpoint) endpointList.remove(0);
+        dispatcher.updateSession(responseMsgCtx, endpoint);
+        if (endpoint instanceof SALoadbalanceEndpoint) {
+            ((SALoadbalanceEndpoint) endpoint).updateSession(responseMsgCtx, endpointList);
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public LoadbalanceAlgorithm getAlgorithm() {
+        return algorithm;
+    }
+
+    public void setAlgorithm(LoadbalanceAlgorithm algorithm) {
+        this.algorithm = algorithm;
+    }
+
+    public boolean isActive() {
+        return active;
+    }
+
+    public void setActive(boolean active) {
+        this.active = active;
+    }
+
+    public ArrayList getEndpoints() {
+        return endpoints;
+    }
+
+    public void setEndpoints(ArrayList endpoints) {
+        this.endpoints = endpoints;
+    }
+
+    public void setParentEndpoint(Endpoint parentEndpoint) {
+        this.parentEndpoint = parentEndpoint;
+    }
+
+    public Dispatcher getDispatcher() {
+        return dispatcher;
+    }
+
+    public void setDispatcher(Dispatcher dispatcher) {
+        this.dispatcher = dispatcher;
+    }
+
+    /**
+     * It is logically incorrect to failover a session affinity endpoint. If we redirect a message
+     * belonging to a particular session, new endpoint is not aware of the session. So we can't handle
+     * anything more at the endpoint level. Therefore, this method just deactivate the failed
+     * endpoint and give the fault to the next fault handler.
+     *
+     * @param endpoint Failed endpoint.
+     * @param synMessageContext MessageContext of the failed message.
+     */
+    public void onChildEndpointFail(Endpoint endpoint, MessageContext synMessageContext) {
+        endpoint.setActive(false);
+        Object o = synMessageContext.getFaultStack().pop();
+        ((FaultHandler)o).handleFault(synMessageContext);
+    }
+}

Modified: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/WSDLEndpoint.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/WSDLEndpoint.java?view=diff&rev=522482&r1=522481&r2=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/WSDLEndpoint.java (original)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/WSDLEndpoint.java Mon Mar 26 04:13:48 2007
@@ -28,6 +28,7 @@
 import org.apache.axis2.addressing.EndpointReference;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.axiom.om.OMElement;
 
 import java.util.Stack;
 
@@ -45,6 +46,11 @@
     private static final Log log = LogFactory.getLog(AddressEndpoint.class);
 
     private String name;
+    private String wsdlURI;
+    private OMElement wsdlDoc;
+    private String serviceName;
+    private String portName;
+
     private boolean active = true;
     private Endpoint parentEndpoint = null;
     private EndpointDefinition endpointDefinition = null;
@@ -155,6 +161,38 @@
 
     public void setName(String name) {
         this.name = name;
+    }
+
+    public String getWsdlURI() {
+        return wsdlURI;
+    }
+
+    public void setWsdlURI(String wsdlURI) {
+        this.wsdlURI = wsdlURI;
+    }
+
+    public OMElement getWsdlDoc() {
+        return wsdlDoc;
+    }
+
+    public void setWsdlDoc(OMElement wsdlDoc) {
+        this.wsdlDoc = wsdlDoc;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public void setServiceName(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    public String getPortName() {
+        return portName;
+    }
+
+    public void setPortName(String portName) {
+        this.portName = portName;
     }
 
     public boolean isActive() {

Added: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/Dispatcher.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/Dispatcher.java?view=auto&rev=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/Dispatcher.java (added)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/Dispatcher.java Mon Mar 26 04:13:48 2007
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.synapse.endpoints.dispatch;
+
+import org.apache.synapse.endpoints.Endpoint;
+import org.apache.synapse.MessageContext;
+
+public interface Dispatcher {
+
+    /**
+     * Dispatcher should check the session id pattern in the synapseMessageContext and return the
+     * matching endpoint for that session id, if availabale. If the session id in the given
+     * synapseMessageContext is not found it should return null.
+     *
+     * @param synCtx client -> esb message context.
+     * @return Endpoint Endpoint associated with this session.
+     */
+    public Endpoint getEndpoint(MessageContext synCtx);
+    
+    /**
+     * Updates the session maps for client initiated sessions. This should be called in
+     * client -> esb -> server flow.
+     *
+     * @param synCtx SynapseMessageContext
+     * @param endpoint Selected endpoint for this session.
+     */
+    public void updateSession(MessageContext synCtx, Endpoint endpoint);
+
+    /**
+     * Determine whether the session supported by the implementing dispatcher is intiated by the
+     * server (e.g. soap session) or by the client. This can be used for optimizing session updates.
+     *
+     * @return true, if the session is initiated by the server. false, otherwise.
+     */
+    public boolean isServerInitiatedSession();
+}

Added: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SimpleClientSessionDispatcher.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SimpleClientSessionDispatcher.java?view=auto&rev=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SimpleClientSessionDispatcher.java (added)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SimpleClientSessionDispatcher.java Mon Mar 26 04:13:48 2007
@@ -0,0 +1,77 @@
+/*
+ *  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.synapse.endpoints.dispatch;
+
+import org.apache.synapse.endpoints.Endpoint;
+import org.apache.synapse.MessageContext;
+import org.apache.axiom.soap.SOAPHeader;
+import org.apache.axiom.om.OMElement;
+
+import javax.xml.namespace.QName;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * This dispatcher is implemented to demonstrate a sample client session. It will detect sessions
+ * based on the <syn:ClientID xmlns:syn="http://ws.apache.org/namespaces/synapse"> soap header of the
+ * request message. Therefore, above header has to be included in the request soap messages by the
+ * client who want to initiate and maintain a session.
+ */
+public class SimpleClientSessionDispatcher implements Dispatcher {
+
+    private Map sessionMap = new HashMap();
+
+    public Endpoint getEndpoint(MessageContext synCtx) {
+
+        SOAPHeader header = synCtx.getEnvelope().getHeader();
+
+        if(header != null) {
+            OMElement csID = header.getFirstChildWithName(
+                    new QName("http://ws.apache.org/namespaces/synapse", "ClientID", "syn"));
+            if(csID != null && csID.getText() != null) {
+                if (sessionMap.containsKey(csID.getText())) {
+                    Endpoint endpoint = (Endpoint)sessionMap.get(csID.getText());
+                    return endpoint;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public void updateSession(MessageContext synCtx, Endpoint endpoint) {
+
+        SOAPHeader header = synCtx.getEnvelope().getHeader();
+
+        if(header != null) {
+            OMElement csID = header.getFirstChildWithName(
+                    new QName("http://ws.apache.org/namespaces/synapse", "ClientID", "syn"));
+            if(csID != null && csID.getText() != null) {
+                if (!sessionMap.containsKey(csID.getText())) {
+                    sessionMap.put(csID.getText(), endpoint);
+                }
+            }
+        }
+    }
+
+    public boolean isServerInitiatedSession() {
+        return false;
+    }
+}

Added: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SoapSessionDispatcher.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SoapSessionDispatcher.java?view=auto&rev=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SoapSessionDispatcher.java (added)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/dispatch/SoapSessionDispatcher.java Mon Mar 26 04:13:48 2007
@@ -0,0 +1,109 @@
+/*
+ *  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.synapse.endpoints.dispatch;
+
+import org.apache.synapse.endpoints.Endpoint;
+import org.apache.synapse.MessageContext;
+import org.apache.synapse.core.axis2.Axis2MessageContext;
+import org.apache.axiom.soap.SOAPHeader;
+import org.apache.axiom.om.OMElement;
+import org.apache.axis2.context.OperationContext;
+import org.apache.axis2.AxisFault;
+
+import javax.xml.namespace.QName;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SoapSessionDispatcher implements Dispatcher {
+
+    private Map sessionMap = new HashMap();
+
+    /**
+     * Gives the endpoint based on the service group context ID of the request message.
+     *
+     * @param synCtx Request MessageContext, possibly containing a service group context ID.
+     *
+     * @return Endpoint associated with the soap session, if current message is a soap session
+     * message and if current message is not the first message of the session. Returns null, if
+     * an Endpoint could not be found for the session.
+     */
+    public Endpoint getEndpoint(MessageContext synCtx) {
+        Endpoint endpoint = null;
+
+        SOAPHeader header = synCtx.getEnvelope().getHeader();
+
+        if(header != null) {
+            OMElement sgcID = header.getFirstChildWithName(
+                    new QName("http://ws.apache.org/namespaces/axis2", "ServiceGroupId", "axis2"));
+            if(sgcID != null && sgcID.getText() != null) {
+                if (sessionMap.containsKey(sgcID.getText())) {  
+                    endpoint = (Endpoint)sessionMap.get(sgcID);
+                }
+            }
+        }
+
+        return endpoint;
+    }
+
+    /**
+     * As this is a server initiated session, this method will only be called for response messages.
+     * It extracts the service group context ID (if available) from the message and updates the
+     * session (service group context ID) -> endpoint map.
+     *
+     * @param synCtx MessageContext of the response message.
+     * @param endpoint Endpoint to associate with the session.
+     */
+    public void updateSession(MessageContext synCtx, Endpoint endpoint) {
+        // get the service group context id
+        // check if service group context id is a key of any entry
+        // if not, add an entry <service group context id, endpoint>
+
+
+        SOAPHeader header = synCtx.getEnvelope().getHeader();
+
+        if(header != null) {
+            OMElement replyTo = header.getFirstChildWithName
+                    (new QName("http://www.w3.org/2005/08/addressing", "ReplyTo", "wsa"));
+
+            if(replyTo != null) {
+                OMElement referenceParameters = replyTo.getFirstChildWithName(new QName(
+                        "http://www.w3.org/2005/08/addressing", "ReferenceParameters", "wsa"));
+
+                if(referenceParameters != null) {
+                    OMElement sgcID = referenceParameters.getFirstChildWithName(new QName(
+                            "http://ws.apache.org/namespaces/axis2", "ServiceGroupId", "axis2"));
+
+                    if(!sessionMap.containsKey(sgcID)) {
+                        sessionMap.put(sgcID.getText(), endpoint);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Soap session is initiated by the server. So this method always returns true.
+     *
+     * @return true
+     */
+    public boolean isServerInitiatedSession() {
+        return true;
+    }
+}

Modified: webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/builtin/SendMediator.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/builtin/SendMediator.java?view=diff&rev=522482&r1=522481&r2=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/builtin/SendMediator.java (original)
+++ webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/builtin/SendMediator.java Mon Mar 26 04:13:48 2007
@@ -25,7 +25,11 @@
 import org.apache.synapse.MessageContext;
 import org.apache.synapse.core.axis2.Axis2MessageContext;
 import org.apache.synapse.endpoints.Endpoint;
+import org.apache.synapse.endpoints.SALoadbalanceEndpoint;
 import org.apache.synapse.mediators.AbstractMediator;
+import org.apache.axis2.context.OperationContext;
+
+import java.util.List;
 
 /**
  * SendMediator sends a message using specified semantics. If it contains an endpoint it will send the
@@ -65,6 +69,22 @@
                     log.debug("SOAPAction: " + (synCtx.getWSAAction() != null ?
                             synCtx.getWSAAction() : "null"));
                     log.debug("Body : \n" + synCtx.getEnvelope());
+                }
+
+                if (synCtx.isResponse()) {
+                    Axis2MessageContext axis2MsgCtx = (Axis2MessageContext) synCtx;
+                    OperationContext opCtx = axis2MsgCtx.getAxis2MessageContext().getOperationContext();
+                    Object o = opCtx.getProperty("endpointList");
+                    if (o != null) {
+                        // we are in the response of the first message of a server initiated session.
+                        // so update all session maps.
+                        List endpointList = (List) o;
+                        Object e = endpointList.remove(0);
+                        if (e != null && e instanceof SALoadbalanceEndpoint) {
+                            SALoadbalanceEndpoint saLoadbalanceEndpoint = (SALoadbalanceEndpoint) e;
+                            saLoadbalanceEndpoint.updateSession(synCtx, endpointList);
+                        }
+                    }
                 }
                 synCtx.getEnvironment().send(null, synCtx);
 

Modified: webservices/synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/config/xml/SendMediatorSerializationTest.java
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/config/xml/SendMediatorSerializationTest.java?view=diff&rev=522482&r1=522481&r2=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/config/xml/SendMediatorSerializationTest.java (original)
+++ webservices/synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/config/xml/SendMediatorSerializationTest.java Mon Mar 26 04:13:48 2007
@@ -25,6 +25,7 @@
 import org.apache.synapse.endpoints.LoadbalanceEndpoint;
 import org.apache.synapse.endpoints.AddressEndpoint;
 import org.apache.synapse.endpoints.FailoverEndpoint;
+import org.apache.synapse.endpoints.WSDLEndpoint;
 
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLInputFactory;
@@ -196,6 +197,43 @@
                 children2.get(0) instanceof AddressEndpoint);
         assertTrue("Children of the fail over endpoint should be address endpoints.",
                 children2.get(1) instanceof AddressEndpoint);
+    }
+
+    public void testWSDLEndpointSerialization() {      
+
+        String sendConfig = "<send xmlns=\"http://ws.apache.org/ns/synapse\">" +
+                     "<endpoint>" +
+                          "<wsdl uri='file:src/test/resources/esbservice.wsdl' service='esbservice' port='esbserviceSOAP11port_http'>" +
+                               "<enableAddressing/>" +
+                          "</wsdl>" +
+                     "</endpoint>" +
+                "</send>";
+
+        OMElement config1 = createOMElement(sendConfig);
+        SendMediator send1 = (SendMediator) factory.createMediator(config1);
+
+        OMElement config2 = serializer.serializeMediator(null, send1);
+        SendMediator send2 = (SendMediator) factory.createMediator(config2);
+
+        assertTrue("Top level endpoint should be a WSDL endpoint.",
+                send1.getEndpoint() instanceof WSDLEndpoint);
+        WSDLEndpoint ep1 = (WSDLEndpoint) send1.getEndpoint();
+
+        assertTrue("Top level endpoint should be a WSDL endpoint.",
+                send2.getEndpoint() instanceof WSDLEndpoint);
+        WSDLEndpoint ep2 = (WSDLEndpoint) send2.getEndpoint();
+
+        assertEquals("Service name is not serialized properly.",
+                ep1.getServiceName(), ep2.getServiceName());
+
+        assertEquals("Port name is not serialized properly", ep1.getPortName(), ep2.getPortName());
+
+        assertEquals("WSDL URI is not serialized properly", ep1.getWsdlURI(), ep2.getWsdlURI());
+
+        assertEquals(
+                "Addressing information is not serialized properly",
+                ep1.getEndpointDefinition().isAddressingOn(),
+                ep2.getEndpointDefinition().isAddressingOn());
     }
 
     protected OMElement createOMElement(String xml) {

Added: webservices/synapse/trunk/java/modules/core/src/test/resources/esbservice.wsdl
URL: http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/test/resources/esbservice.wsdl?view=auto&rev=522482
==============================================================================
--- webservices/synapse/trunk/java/modules/core/src/test/resources/esbservice.wsdl (added)
+++ webservices/synapse/trunk/java/modules/core/src/test/resources/esbservice.wsdl Mon Mar 26 04:13:48 2007
@@ -0,0 +1,83 @@
+<wsdl:definitions xmlns:axis2="http://ws.apache.org/axis2" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:ns0="http://ws.apache.org/axis2/xsd" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.apache.org/axis2">
+    <wsdl:documentation>
+        New web service to test esb
+    </wsdl:documentation>
+    <wsdl:types>
+        <xs:schema xmlns:ns="http://ws.apache.org/axis2/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ws.apache.org/axis2/xsd">
+            <xs:element name="multiply">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="x" nillable="true" type="xs:double" />
+                        <xs:element name="y" nillable="true" type="xs:double" />
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="multiplyResponse">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="return" nillable="true" type="xs:double" />
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+        </xs:schema>
+    </wsdl:types>
+    <wsdl:message name="multiplyMessage">
+        <wsdl:part name="part1" element="ns0:multiply" />
+    </wsdl:message>
+    <wsdl:message name="multiplyResponse">
+        <wsdl:part name="part1" element="ns0:multiplyResponse" />
+    </wsdl:message>
+    <wsdl:portType name="esbservicePortType">
+        <wsdl:operation name="multiply">
+            <wsdl:input xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" message="axis2:multiplyMessage" wsaw:Action="urn:multiply" />
+            <wsdl:output message="axis2:multiplyResponse" />
+        </wsdl:operation>
+    </wsdl:portType>
+    <wsdl:binding name="esbserviceSOAP11Binding" type="axis2:esbservicePortType">
+        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
+        <wsdl:operation name="multiply">
+            <soap:operation soapAction="urn:multiply" style="document" />
+            <wsdl:input>
+                <soap:body use="literal" />
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal" />
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:binding name="esbserviceSOAP12Binding" type="axis2:esbservicePortType">
+        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
+        <wsdl:operation name="multiply">
+            <soap12:operation soapAction="urn:multiply" style="document" />
+            <wsdl:input>
+                <soap12:body use="literal" />
+            </wsdl:input>
+            <wsdl:output>
+                <soap12:body use="literal" />
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:binding name="esbserviceHttpBinding" type="axis2:esbservicePortType">
+        <http:binding verb="POST" />
+        <wsdl:operation name="multiply">
+            <http:operation location="multiply" />
+            <wsdl:input>
+                <mime:content type="text/xml" />
+            </wsdl:input>
+            <wsdl:output>
+                <mime:content type="text/xml" />
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:service name="esbservice">
+        <wsdl:port name="esbserviceSOAP11port_http" binding="axis2:esbserviceSOAP11Binding">
+            <soap:address location="http://localhost:9001/axis2/services/Service1" />
+        </wsdl:port>
+        <wsdl:port name="esbserviceSOAP12port_http" binding="axis2:esbserviceSOAP12Binding">
+            <soap12:address location="http://localhost:9001/axis2/services/Service1" />
+        </wsdl:port>
+        <wsdl:port name="esbserviceHttpport1" binding="axis2:esbserviceHttpBinding">
+            <http:address location="http://localhost:9001/axis2/services/Service1" />
+        </wsdl:port>
+    </wsdl:service>
+</wsdl:definitions>



---------------------------------------------------------------------
To unsubscribe, e-mail: synapse-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: synapse-dev-help@ws.apache.org