<?xml version="1.0" encoding="ISO-8859-1"?>

<document>
    <properties>
        <title>Apache Synapse - Extending...</title>
    </properties>
    <head>
        <style type="text/css" xml:space="preserve">
            .command {
            border: 1px dashed #3c78b5;
            text-align: left;
            background-color: #f0f0f0;
            padding: 3px;
            font-size: 11px;
            font-family: Courier;
            margin: 10px;
            line-height: 13px;
            }
            .consoleOutput {
            border: 1px dashed #3c78b5;
            font-size: 11px;
            font-family: Courier;
            margin: 10px;
            line-height: 13px;
            background-color: #f0f0f0;
            border-bottom: 1px dashed #3c78b5;
            padding: 3px;
            border-style: solid;
            }
            .info {
            border-style: solid;
            border-width: 1px;
            border-color: #090;
            background-color: #dfd;
            text-align:left;
            margin-top: 5px;
            margin-bottom: 5px;
            }
            li {
            font-family: Verdana, arial, sans-serif;
            font-size: 11px;
            line-height: 16px;
            color: #000000;
            font-weight: normal;
            }
            p {
            font-family: Verdana, arial, sans-serif;
            font-size: 11px;
            line-height: 16px;
            color: #000000;
            font-weight: normal;
            }
            pre {
            padding: 0px;
            margin-top: 5px;
            margin-left: 15px;
            margin-bottom: 5px;
            margin-right: 5px;
            text-align: left;
            background-color: #f0f0f0;
            padding: 3px;
            border: 1px dashed #3c78b5;
            font-size: 11px;
            font-family: Courier;
            margin: 10px;
            line-height: 13px;
            }
            h1 {
            font-size: 24px;
            line-height: normal;
            font-weight: bold;
            background-color: #f0f0f0;
            color: #003366;
            border-bottom: 1px solid #3c78b5;
            padding: 2px;
            margin: 36px 0px 4px 0px;
            }
            h2 {
            font-size: 18px;
            line-height: normal;
            font-weight: bold;
            background-color: #f0f0f0;
            border-bottom: 1px solid #3c78b5;
            padding: 2px;
            margin: 27px 0px 4px 0px;
            }
            h3 {
            font-size: 14px;
            line-height: normal;
            font-weight: bold;
            background-color: #f0f0f0;
            padding: 2px;
            margin: 21px 0px 4px 0px;
            }
            h4 {
            font-size: 12px;
            line-height: normal;
            font-weight: bold;
            background-color: #f0f0f0;
            padding: 2px;
            margin: 18px 0px 4px 0px;
            }
        </style>
    </head>
    <body>
        <div style="margin-top:-40px; float:right; _margin-top:0px;">
            <img alt="Synapse logo"
                 src="images/synapse-logo-web2.png" width="197"
                 height="82"/>
        </div>
        <div>
            <h1>
                Apache Synapse ESB - Extending...
            </h1>
        </div>
        <h2>
            Writing custom Mediator implementations
        </h2>
        <p>
            The primary interface of the Synapse API is the MessageContext interface
            defined below. This essentially defines the per-message context passed
            through the chain of mediators, for each and every message received and
            processed by Synapse. Each message instance is wrapped within a
            MessageContext instance, and the message context is set with the
            references to the SynapseConfiguration and SynapseEnvironment objects. The
            <a href="apidocs/org/apache/synapse/config/SynapseConfiguration.html">
                SynapseConfiguration
            </a>
            object holds the global configuration model that defines
            mediation rules, local registry entries and other and configuration, while
            the
            <a href="apidocs/org/apache/synapse/core/SynapseEnvironment.html">SynapseEnvironment</a>
            object gives access to the underlying SOAP implementation used -
            Axis2. A typical mediator would need to manipulate the MessageContext by
            referring to the SynapseConfiguration. However it is strongly recommended
            that the SynapseConfiguration is not updated by mediator instances as it
            is shared by all messages, and may be updated by Synapse administration or
            configuration modules. Mediator instances may store local message
            properties into the MessageContext for later retrieval by successive
            mediators.
            <br/>
        </p>
        <h4>
            <a
                    href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/MessageContext.java?view=markup">
                MessageContext
                Interface
            </a>
        </h4>
        <p/>
        <pre xml:space="preserve">package org.apache.synapse;

            import ...

            public interface MessageContext {

            /**
            * Get a reference to the current SynapseConfiguration
            *
            * @return the current synapse configuration
            */
            public SynapseConfiguration getConfiguration();

            /**
            * Set or replace the Synapse Configuration instance to be used. May be used to
            * programatically change the configuration at runtime etc.
            *
            * @param cfg The new synapse configuration instance
            */
            public void setConfiguration(SynapseConfiguration cfg);

            /**
            * Returns a reference to the host Synapse Environment
            * @return the Synapse Environment
            */
            public SynapseEnvironment getEnvironment();

            /**
            * Sets the SynapseEnvironment reference to this context
            * @param se the reference to the Synapse Environment
            */
            public void setEnvironment(SynapseEnvironment se);

            /**
            * Get the value of a custom (local) property set on the message instance
            * @param key key to look up property
            * @return value for the given key
            */
            public Object getProperty(String key);

            /**
            * Set a custom (local) property with the given name on the message instance
            * @param key key to be used
            * @param value value to be saved
            */
            public void setProperty(String key, Object value);

            /**
            * Returns the Set of keys over the properties on this message context
            * @return a Set of keys over message properties
            */
            public Set getPropertyKeySet();

            /**
            * Get the SOAP envelope of this message
            * @return the SOAP envelope of the message
            */
            public SOAPEnvelope getEnvelope();

            /**
            * Sets the given envelope as the current SOAPEnvelope for this message
            * @param envelope the envelope to be set
            * @throws org.apache.axis2.AxisFault on exception
            */
            public void setEnvelope(SOAPEnvelope envelope) throws AxisFault;

            /**
            * SOAP message related getters and setters
            */
            public ....get/set()...

            }
        </pre>
        <p>
            The MessageContext interface is based on the Axis2 MessageContext
            interface, and uses the Axis2 EndpointReference and
            SOAPEnvelope classes/interfaces. The purpose of this interface is to
            capture a message as it flows through the system. As you will see the
            message payload is represented using the SOAP infoset. Binary messages can
            be embedded in the Envelope using MTOM or SwA attachments using the AXIOM
            object model.
        </p>
        <h4>
            <a
                    href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/Mediator.java?view=markup">
                Mediator
                interface
            </a>
        </h4>
        <p>
            The second key interface for mediator writers is the Mediator interface:
        </p>
        <pre xml:space="preserve">package org.apache.synapse;

            import org.apache.synapse.MessageContext;

            /**
            * All Synapse mediators must implement this Mediator interface. As a message passes
            * through the synapse system, each mediator's mediate() method is invoked in the
            * sequence/order defined in the SynapseConfiguration.
            */
            public interface<span style="font-weight: bold;">Mediator</span>{

            /**
            * Invokes the mediator passing the current message for mediation. Each
            * mediator performs its mediation action, and returns true if mediation
            * should continue, or false if further mediation should be aborted.
            *
            * @param synCtx the current message for mediation
            * @return true if further mediation should continue
            */
            public boolean mediate(MessageContext synCtx);

            /**
            * This is used for debugging purposes and exposes the type of the current
            * mediator for logging and debugging purposes
            * @return a String representation of the mediator type
            */
            public String getType();
            }
        </pre>
        <p>
            A mediator can read and/or modify the message encapsulated in the MessageContext in
            any suitable manner - adjusting the routing headers or changing the
            message body. If the mediate() method returns false, it signals to the
            Synapse processing model to stop further processing of the message. For
            example, if the mediator is a security agent it may decide that this
            message is dangerous and should not be processed further. This is
            generally the exception as mediators are usually designed to co-operate to
            process the message onwards.
        </p>
        <h3>
            Leaf and Node Mediators, List mediators and Filter mediators
        </h3>
        <p>
            Mediators may be Node mediators (i.e. these that can contain child
            mediators) or Leaf mediators (mediators that does not hold any other child
            mediators). A Node mediator must implement the
            org.apache.synapse.mediators.ListMediator interface listed below, or extend from
            the org.apache.synapse.mediators.AbstractListMediator.
        </p>
        <h4>
            <a
                    href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/ListMediator.java?view=markup">
                The
                ListMediator interface
            </a>
        </h4>
        <pre xml:space="preserve">package org.apache.synapse.mediators;

            import java.util.List;

            /**
            * The List mediator executes a given sequence/list of child mediators
            */
            public interface ListMediator extends Mediator {
            /**
            * Appends the specified mediator to the end of this mediator's (children) list
            * @param m the mediator to be added
            * @return true (as per the general contract of the Collection.add method)
            */
            public boolean addChild(Mediator m);

            /**
            * Appends all of the mediators in the specified collection to the end of this mediator's
            (children)
            * list, in the order that they are returned by the specified collection's iterator
            * @param c the list of mediators to be added
            * @return true if this list changed as a result of the call
            */
            public boolean addAll(List c);

            /**
            * Returns the mediator at the specified position
            * @param pos index of mediator to return
            * @return the mediator at the specified position in this list
            */
            public Mediator getChild(int pos);

            /**
            * Removes the first occurrence in this list of the specified mediator
            * @param m mediator to be removed from this list, if present
            * @return true if this list contained the specified mediator
            */
            public boolean removeChild(Mediator m);

            /**
            * Removes the mediator at the specified position in this list
            * @param pos the index of the mediator to remove
            * @return the mediator previously at the specified position
            */
            public Mediator removeChild(int pos);

            /**
            * Return the list of mediators of this List mediator instance
            * @return the child/sub mediator list
            */
            public List getList();
            }
        </pre>
        <p>
            A ListMediator implementation should call super.mediate(synCtx) to process
            its sub mediator sequence. A FilterMediator is a ListMediator which
            executes its sequence of sub mediators on successful outcome of a test
            condition. The Mediator instance which performs filtering should implement
            the FilterMediator interface.
        </p>
        <h4>
            <a
                    href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/FilterMediator.java?view=markup">
                FilterMediator
                interface
            </a>
        </h4>
        <pre xml:space="preserve">package org.apache.synapse.mediators;

            import org.apache.synapse.MessageContext;

            /**
            * The filter mediator is a list mediator, which executes the given (sub) list of
            mediators
            * if the specified condition is satisfied
            *
            * @see FilterMediator#test(org.apache.synapse.MessageContext)
            */
            public interface<span style="font-weight: bold;">FilterMediator</span>extends
            ListMediator {

            /**
            * Should return true if the sub/child mediators should execute. i.e. if the filter
            * condition is satisfied
            * @param synCtx
            * @return true if the configured filter condition evaluates to true
            */
            public boolean test(MessageContext synCtx);
            }
        </pre>
        <h2>
            Writing custom Configuration implementations for mediators
        </h2>
        <p>
            You may write your own custom configurator for the Mediator implementation
            you write without relying on the Class mediator or Spring extension for
            its initialization. You could thus write a MediatorFactory implementation
            which defines how to digest a custom XML configuration element to be used
            to create and configure the custom mediator instance. A MediatorSerializer
            implementation defines how a configuration should be serialized back into
            an XML configuration. The custom MediatorFactory &amp; MediatorSerializer
            implementations and the mediator class/es must be bundled in a JAR file
            conforming to the J2SE Service Provider model (See the description for
            Extensions below for more details and examples) and placed into the
            SYNAPSE_HOME/lib folder, so that the Synapse runtime could find and load
            the definition. Essentially this means that a custom JAR file must bundle
            your class implementing the Mediator interface, and the MediatorFactory
            implementation class and contain two text files named
            "org.apache.synapse.config.xml.MediatorFactory" and
            "org.apache.synapse.config.xml.MediatorSerializer" which will contain the
            fully qualified name(s) of your MediatorFactory and MediatorSerializer
            implementation classes. You should also place any dependency JARs into the
            same lib folder so that the correct classpath references could be made.
            The MediatorFactory interface listing is given below, which you should
            implement, and its getTagQName() method must define the fully qualified
            element of interest for custom configuration. The Synapse initialization
            will call back to this MediatorFactory instance through the
            createMediator(OMElement elem) method passing in this XML element, so that
            an instance of the mediator could be created utilizing the custom XML
            specification and returned. See the ValidateMediator and the
            ValidateMediatorFactory classes under modules/extensions in the Synapse
            source distribution for examples.
        </p>
        <h4>
            <a
                    href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactory.java?view=markup">
                The
                MediatorFactory interface
            </a>
        </h4>
        <pre xml:space="preserve">package org.apache.synapse.config.xml;

            import ...

            /**
            * A mediator factory capable of creating an instance of a mediator through a given
            * XML should implement this interface
            */
            public interface MediatorFactory {
            /**
            * Creates an instance of the mediator using the OMElement
            * @param elem
            * @return the created mediator
            */
            public Mediator createMediator(OMElement elem);

            /**
            * The QName of this mediator element in the XML config
            * @return QName of the mediator element
            */
            public QName getTagQName();
            }
        </pre>
        <p/>
        <h4>
            <a
                    href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorSerializer.java?view=markup">
                The
                MediatorSerializer interface
            </a>
        </h4>
        <pre xml:space="preserve">package org.apache.synapse.config.xml;

            import ...

            /**
            * Interface which should be implemented by mediator serializers. Does the
            * reverse of the MediatorFactory
            */
            public interface MediatorSerializer {

            /**
            * Return the XML representation of this mediator
            * @param m mediator to be serialized
            * @param parent the OMElement to which the serialization should be attached
            * @return the serialized mediator XML
            */
            public OMElement serializeMediator(OMElement parent, Mediator m);

            /**
            * Return the class name of the mediator which can be serialized
            * @return the class name
            */
            public String getMediatorClassName();
            }
        </pre>
        <h2>
            Configuring mediators
        </h2>
        <p>
            Mediators could access the Synapse registry to load resources and
            configure the local behaviour. Refer to the Spring mediator and Script
            mediator implementations for examples on how this could be achieved.
        </p>
        <h4>
            Loading of Extensions by the Synapse runtime
        </h4>
        <p>
            Synapse loads available extensions from the runtime classpath using the<a
                href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">J2SE
            Service Provider model</a>. This essentially iterates over the
            available JAR files, for a META-INF/services directory within each file,
            and looks for a text file with the name
            org.apache.synapse.config.xml.MediatorFactory which contains a list of
            fully qualified classname that implement the above interface, listing each
            class in a separate line. e.g. The built-in synapse-extensions.jar
            contains the following structure
        </p>
        <pre xml:space="preserve">synapse-extensions.jar
            /META-INF/services
            org.apache.synapse.config.xml.MediatorFactory
            org.apache.synapse.config.xml.MediatorSerializer
            /... the implementation classes as usual...
        </pre>
        <h2 id="synObservers">
            Writing Synapse Observers
        </h2>
        <p>
            A Synapse observer is developed by either implementing the
            org.apache.synapse.config.SynapseObserver interface or by extending the
            org.apache.synapse.config.AbstractSynapseObserver class. A Synapse observer is notified
            by the Synapse configuration when new elements are added to the configuration and
            when existing elements are removed from the configuration. The following event
            handlers are available to the Synapse observer implementations.
        </p>
        <pre xml:space="preserve">
            public void sequenceAdded(Mediator sequence);
            public void sequenceRemoved(Mediator sequence);
            public void entryAdded(Entry entry);
            public void entryRemoved(Entry entry);
            public void endpointAdded(Endpoint endpoint);
            public void endpointRemoved(Endpoint endpoint);
            public void proxyServiceAdded(ProxyService proxy);
            public void proxyServiceRemoved(ProxyService proxy);
            public void startupAdded(Startup startup);
            public void startupRemoved(Startup startup);
            public void eventSourceAdded(SynapseEventSource eventSource);
            public void eventSourceRemoved(SynapseEventSource eventSource);
        </pre>
        <p>
            The AbstractSynapseObserver provides default implementations to all these
            event handlers. It simply logs any received events.
        </p>
        <p>
            In situations where the custom code has access to the SynapseConfiguration class
            observers can be directly registered with the SynapseConfiguration by using the
            registerObserver(SynapseObserver o) method. Otherwise SynapseObserver implementations
            can be defined in the synapse.properties file which resides in the SYNAPSE_HOME/lib
            directory. The following example shows how two observers are registered with the
            Synapse configuration using the synapse.properties file.
        </p>
        <pre xml:space="preserve">synapse.observers=test.LoggingObserverImpl,
            test.SimpleObserverImpl
        </pre>

        <h2 id="synXpathExtensions">
            Synapse Xpath Extension Framework
        </h2>
        <p>
            Synapse configuration language is a powerful and flexible tool to perform
            authentication, validation, transformation, logging, routing based on the content etc.
            It could be easily extended, with configuration extensions , mediation extensions and
            even expression level extension. An expression is a lowest level particle in the
            synapase configuration. To be precise , unlike static values ,expressions can be used to
            define dynamically extracted values (using xpath) in a synapse configuration.
            Mediators extensively uses expressions to extract properties from message context.
            Expression is defined under attribute "expression" of a particular configuration. (see
            property/header/iterator mediator ) .Although expressions can be purely xpath , synapse
            allows extended to define extended expressions as well. These special xpath expressions
            can be two fold , that is ,
        </p>
        <pre xml:space="preserve">
            1.xpath variable expressions
            2.xpath function expressions
        </pre>
        <p>
            Synapse allows us to access xpath variables with "$" . Currently there are several
            predefined synapse xpath variables avaiable.
        </p>
        <pre xml:space="preserve">
            Ie:- $body - message SOAP body
            $header ? message SOAP header
            $ctxt:SOME_PROPERTY ? a property belonging to synapse meessage context scope
            $axis2:SOME_PROPERTY ? a property belonging to axis2 meessage context scope
            $trp:SOME_TRANSPORT_HEADER ? a transport header
        </pre>
        <p>
            Synapse get-property() is an example xpath function expressions. The get-property()
            function allows any XPath expression used in a configuration to lookup information from
            the current message context. Similar to above , It is possible to retrieve properties
            previously set with the property mediator, and/or information from the Synapse or Axis2
            message contexts or transport header using get-property().
        </p>
        <p>
            see synapse documentation for more details on usage of these expressions.
            Synapse Xpath extension framework allows users to further extend xpath expressions to
            suite user requirement. More specifically it allows users to define custom xpath
            expressions and custom xpath functions that is required in a specific usecase
            configuration scenario. Let's see how we can do this. We start by writng our HELLO_WORLD
            custom xpath variable and hello-world() custom xpath function.
        </p>
        <h4>
            Implementing HELLO_WORLD custom xpath variable
        </h4>
        <p>
            Before going into implementation details , let me first define our final objective here.
            What we need to do is to expose an HELLO_WORLD message in xml format to outside , so
            that users would be able to access it using a xpath expression="$HELLOWORLD/...".
            Following is the HELLO_WORLD mesasge we have.
        </p>
        <pre xml:space="preserve">
            &lt;HELLO_WORLD&gt;
            &lt;name&gt;Synapse&lt;/name&gt;
            &lt;version&gt;2.0.0&lt;/version&gt;
            &lt;release_date&gt;20/12/2010&lt;/release_date&gt;
            &lt;/HELLO_WORLD&gt;
        </pre>
        <p>Every custom synapse xpath extension should implement
            org.apache.synapse.util.xpath.ext.SynapseXpathVariableResolver interface to expose a
            custom xpath variable. This interface consists of two methods , #getResolvingQName ,
            #resolve . First interface method is used to indicate Synapse the fully qualified
            variable name that this extesion support (in our case it is HELLO_WORLD). Later method
            should contain what ever resolving logic required to give the desired output.(in our
            case it should return HELLO_WORLD element) . Following is the implementation of our
            custom xpath variable HELLO_WORLD,
        </p>
        <pre xml:space="preserve">
            package org.sample;

            import org.apache.axiom.om.OMAbstractFactory;
            import org.apache.axiom.om.OMElement;
            import org.apache.axiom.om.OMFactory;
            import org.apache.synapse.MessageContext;
            import org.apache.synapse.util.xpath.ext.SynapseXpathVariableResolver;

            import javax.xml.namespace.QName;

            public class HelloWorldXpathVariableResolver implements SynapseXpathVariableResolver {

            public static final QName HELLO_WORLD = new QName("HELLO_WORLD");

            public Object resolve(MessageContext messageContext) {
                //create Hello world message
                OMFactory factory = OMAbstractFactory.getOMFactory();
                OMElement helloWorldElement = factory.createOMElement(HELLO_WORLD);

                OMElement nameElement = factory.createOMElement(new QName("name"));
                nameElement.setText("synapse");
                OMElement versionElem = factory.createOMElement(new QName("version"));
                versionElem.setText("3.1.0");
                OMElement releaseDateElem = factory.createOMElement(new QName("release_date"));
                releaseDateElem.setText("12/12/2010");

                helloWorldElement.addChild(nameElement);
                helloWorldElement.addChild(versionElem);
                helloWorldElement.addChild(releaseDateElem);

                return helloWorldElement;
            }

            public QName getResolvingQName() {
                //to support xpath expression="$HELLO_WORLD"
                return HELLO_WORLD;
            }

            }
        </pre>
        <p>
            with implementation in place mediators can refer version , name , release date on
            HELLO_WORLD message using expression="$HELLO_WORLD/version" , etc
        </p>
        <h4>
            Implementing hello-world() custom xpath function
        </h4>
        <p>
            Having an xpath function extension is easy as implementing an xpath variable extension.
            In this case Extension class should implement
            org.apache.synapse.util.xpath.ext.SynapseXpathFunctionContextProvider . This interface
            also do have methods , #getResolvingQName and #getInitializedExtFunction . First method
            serves the same purpose as in the previous example. However later method should be
            implementated in such a way that this extension should return a custom jaxen function to
            synapse , initialized with synapse message context. It is extension developers
            responsibility to provide a properly initialized xpath function so that it can be
            resolved at runtime. Our sample implementation is shown below
        </p>
        <pre xml:space="preserve">
            package org.sample;

            import org.apache.synapse.MessageContext;
            import org.apache.synapse.util.xpath.ext.SynapseXpathFunctionContextProvider;
            import org.jaxen.Function;
            import javax.xml.namespace.QName;

            public class HelloWorldXpathFunctionProvider implements SynapseXpathFunctionContextProvider {

            public Function getInitializedExtFunction(MessageContext messageContext) {
                CustomHelloWorldFunction helloWorldFunction = new CustomHelloWorldFunction(messageContext);
                return helloWorldFunction;
            }

            public QName getResolvingQName() {
                //letting know synapse new hello-world extension function
                return new QName("hello-world");
            }
            }

        </pre>
        <p>
            Shown bellow is the custom xpath function returned by our xpath function extension. Note
            that this should implement org.jaxen.Function to resolve xpath .
        </p>
        <pre xml:space="preserve">
            package org.sample;

            import org.apache.axiom.om.OMAbstractFactory;
            import org.apache.axiom.om.OMElement;
            import org.apache.axiom.om.OMFactory;
            import org.apache.commons.logging.Log;
            import org.apache.commons.logging.LogFactory;
            import org.apache.synapse.MessageContext;
            import org.apache.synapse.SynapseConstants;
            import org.jaxen.Context;
            import org.jaxen.Function;
            import org.jaxen.FunctionCallException;
            import org.jaxen.function.StringFunction;

            import javax.xml.namespace.QName;
            import java.util.List;


            public class CustomHelloWorldFunction implements Function {
            private MessageContext synCtx;

            private Log log = LogFactory.getLog(CustomHelloWorldFunction.class);
            private static final Log trace = LogFactory.getLog(SynapseConstants.TRACE_LOGGER);

            private String NULL_STRING = "";
            public static final QName HELLO_WORLD = new QName("HELLO_WORLD");
            private OMElement helloWorld;

            public CustomHelloWorldFunction(MessageContext ctxt) {
                this.synCtx = ctxt;
                //create hello world message
                OMFactory factory = OMAbstractFactory.getOMFactory();
                OMElement helloWorldElement = factory.createOMElement(HELLO_WORLD);

                OMElement nameElement = factory.createOMElement(new QName("name"));
                nameElement.setText("synapse");
                OMElement versionElem = factory.createOMElement(new QName("version"));
                versionElem.setText("3.1.0");
                OMElement releaseDateElem = factory.createOMElement(new QName("release_date"));
                releaseDateElem.setText("12/12/2010");

                helloWorldElement.addChild(nameElement);
                helloWorldElement.addChild(versionElem);
                helloWorldElement.addChild(releaseDateElem);
                this.helloWorld = helloWorldElement;
            }

            /**
            * Returns the string value of the hello world message for the corresponding child
            proeprty
            * arguments are hello-world(name | version | release_date)
            *
            * @param context the context at the point in the expression when the function is called
            * @param args arguments of the functions
            * @return The string value of the property
            * @throws org.jaxen.FunctionCallException
            *
            */
            public Object call(Context context, List args) throws FunctionCallException {

                if (synCtx == null) {
                    if (log.isDebugEnabled()) {
                    log.debug("Synapse message context has not been set for the " +
                    "XPath extension function 'synapse:hello-world(arg_name)'");
                    }
                    return null;
                }

                boolean traceOn = synCtx.getTracingState() == SynapseConstants.TRACING_ON;
                boolean traceOrDebugOn = traceOn || log.isDebugEnabled();

                if (args == null || args.size() == 0) {
                    if (traceOrDebugOn) {
                        traceOrDebug(traceOn, "argument key value for lookup is not specified");
                    }
                    return NULL_STRING;
                } else
                {
                    int size = args.size();
                    if (size == 1) {
                        String argument = StringFunction.evaluate(args.get(0), context.getNavigator());
                    if ("name".equals(argument) || "version".equals(argument) ||
                        "release_date".equals(argument)) {
                         return helloWorld.getFirstChildWithName(new QName(argument));
                    }else{
                        return helloWorld;
                    }
                }
                }
                return NULL_STRING;
            }

            private void traceOrDebug(boolean traceOn, String msg) {
                if (traceOn) {
                    trace.info(msg);
                }
                if (log.isDebugEnabled()) {
                    log.debug(msg);
                }
            }

            }
        </pre>
        <p>
            Here we basically select an child element or the whole Hello World message based on the
            aguments. Please refer to org.jaxen.Function for further details on the implementation.
            With this extension in place synapse configuration can refer to a particular element of
            our Hello World message with expression = "hello-world('name')" ,expression =
            "hello-world('version')" , etc
        </p>
        <h4>
            Registering Extensions
        </h4>
        <p>
            We need one additional step to make all these extensions integrate into Synapse.
            Registering extensions is done by declaring them in synapse.properties file.
            synapse.properties can be found $SYNAPSE_HOME/repository/conf . Functions should be
            declared under property synapse.xpath.func.extensions while Variables should be under
            synapse.xpath.var.extensions .
        </p>
        <pre xml:space="preserve">
            synapse.xpath.var.extensions=org.sample.HelloWorldXpathVariableResolver
            synapse.xpath.func.extensions=org.sample. HelloWorldXpathFunctionProvider
        </pre>
        <p>
            If multiple function / variable extesnions are needed comma delimited list can be
            declared. Synapse at startup will register all these declared extensions (defined under
            its CLASSPATH) and our HELLO-WORLD xpath extensions will be ready to roll.
        </p>


    </body>
</document>