You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by js...@apache.org on 2006/04/03 19:48:51 UTC

svn commit: r391095 - in /incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix: client/ jbi/messaging/

Author: jstrachan
Date: Mon Apr  3 10:48:49 2006
New Revision: 391095

URL: http://svn.apache.org/viewcvs?rev=391095&view=rev
Log:
added an experimental, simple client API which wraps up the concept of endpoints to make it easier to communicate generically with JBI endpoints

Added:
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Client.java   (with props)
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultDestination.java   (with props)
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultJBIClient.java   (with props)
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultNamespaceContext.java   (with props)
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Destination.java   (with props)
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Message.java   (with props)
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/MessageListener.java   (with props)
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/XPathHelper.java   (with props)
Modified:
    incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/messaging/NormalizedMessageImpl.java

Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Client.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Client.java?rev=391095&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Client.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Client.java Mon Apr  3 10:48:49 2006
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.servicemix.client;
+
+import javax.jbi.JBIException;
+import javax.jbi.messaging.MessagingException;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * Provides a way to look up a {@link Destination} via various means such as URIs
+ * so that you can send and receive messages using a simple POJO based API.
+ * 
+ * @version $Revision: $
+ */
+public interface Client {
+
+    /**
+     * Creates the endpoint for the given endpoint URI.
+     * 
+     * The endpoint URI describes the underlying JBI component
+     * using a simple URI syntax. 
+     * 
+     * You can access JBI endpoints using URI syntax
+     * 
+     * <ul>
+     * <li>interface:http:/foo.com/whatever/localName?operation=http://foo.com</li>
+     * <li>service:http:/foo.com/whatever/localName?endpoint=cheese</li>
+     * </ul>
+     * 
+     * Or you can access underlying transports using transport specific URIs
+     * 
+     * <ul>
+     * <li>jms://provider/queue/FOO.BAR</li>
+     * <li>file:/path</li>
+     * </ul>
+     * 
+     * @param uri
+     * @return the endpoint for the given uri
+     * @throws JBIException 
+     */
+    public Destination createEndpoint(URI uri) throws JBIException;
+    
+    /**
+     * Creates the endpoint for the given endpoint URI.
+     * 
+     * @see #createEndpoint(URI)
+     * 
+     * @param uri
+     * @return the endpoint for the given uri
+     * @throws URISyntaxException if the string is not a valid URI syntax
+     */
+    public Destination createEndpoint(String uri) throws JBIException, URISyntaxException;
+}

Propchange: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Client.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultDestination.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultDestination.java?rev=391095&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultDestination.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultDestination.java Mon Apr  3 10:48:49 2006
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.servicemix.client;
+
+import org.apache.servicemix.jbi.messaging.NormalizedMessageImpl;
+
+import javax.jbi.messaging.Fault;
+import javax.jbi.messaging.InOnly;
+import javax.jbi.messaging.InOptionalOut;
+import javax.jbi.messaging.InOut;
+import javax.jbi.messaging.MessageExchange;
+import javax.jbi.messaging.MessagingException;
+import javax.jbi.messaging.NormalizedMessage;
+import javax.jbi.messaging.RobustInOnly;
+
+/**
+ *
+ * @version $Revision: $
+ */
+public class DefaultDestination implements Destination {
+
+    private ServiceMixClient client;
+
+    
+    public void close() {
+        // close any pending exchanges
+        
+        // TODO
+    }
+
+    public void setMessageListener(MessageListener processor) {
+        // registers a processor into the endpoint??
+        
+        // TODO
+        throw new RuntimeException("Unsupported operation");
+    }
+
+    public Message createMessage() {
+        // TODO
+        /*
+        Message message = new NormalizedMessageImpl();
+        return message;
+        */
+        return null;
+    }
+
+    public Message createMessage(Object body) throws MessagingException {
+        // TODO
+        /*
+        Message message = new NormalizedMessageImpl();
+        message.setBody(body);
+        return message;
+        */
+        return null;
+    }
+
+    public void send(NormalizedMessage message) throws MessagingException {
+        // TODO
+        /*
+        configureMessage(message);
+        InOnly exchange = createInOnlyExchange();
+        exchange.setInMessage(message);
+        done(exchange);
+        */
+    }
+    
+    public Message receive() throws MessagingException {
+        // TODO
+        /*
+        MessageExchange exchange = receiveExchange();
+        Message message = (Message) exchange.getMessage("in");
+        return message;
+        */
+        return null;
+    }
+
+    public void receive(MessageListener listener) {
+        
+    }
+
+    public Message waitForResponse(Message requestMessage) {
+        return null;
+    }
+
+    public void send(MessageExchange exchange) throws MessagingException {
+        client.send(exchange);
+    }
+
+    public boolean sendSync(MessageExchange exchange) throws MessagingException {
+        return client.sendSync(exchange);
+    }
+
+    public MessageExchange receiveExchange() throws MessagingException {
+        return client.receive();
+    }
+
+    public MessageExchange receiveExchange(long timeout) throws MessagingException {
+        return client.receive(timeout);
+    }
+
+    public InOnly createInOnlyExchange() throws MessagingException {
+        return client.createInOnlyExchange();
+    }
+
+    public InOut createInOutExchange() throws MessagingException {
+        return client.createInOutExchange();
+    }
+
+    public InOptionalOut createInOptionalOutExchange() throws MessagingException {
+        return client.createInOptionalOutExchange();
+    }
+
+    public RobustInOnly createRobustInOnlyExchange() throws MessagingException {
+        return client.createRobustInOnlyExchange();
+    }
+
+
+    public void done(Message message) throws MessagingException {
+        done(message.getExchange());
+    }
+
+    public void done(MessageExchange exchange) throws MessagingException {
+        client.done(exchange);
+    }
+
+    public void fail(Fault fault) throws MessagingException {
+        Message message = (Message) fault;
+        client.fail(message.getExchange(), fault);
+    }
+
+    public void fail(Message message, Exception fault) throws MessagingException {
+        fail(message.getExchange(), fault);
+    }
+    
+    public void fail(MessageExchange exchange, Exception fault) throws MessagingException {
+        client.fail(exchange, fault);
+    }
+}

Propchange: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultDestination.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultJBIClient.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultJBIClient.java?rev=391095&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultJBIClient.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultJBIClient.java Mon Apr  3 10:48:49 2006
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.servicemix.client;
+
+
+import org.apache.servicemix.client.*;
+import org.apache.servicemix.components.util.ComponentSupport;
+import org.apache.servicemix.jbi.container.ActivationSpec;
+import org.apache.servicemix.jbi.container.JBIContainer;
+
+import javax.jbi.JBIException;
+import javax.jbi.messaging.MessagingException;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ *
+ * @version $Revision: $
+ */
+public class DefaultJBIClient extends ComponentSupport implements Client {
+
+    private JBIContainer container;
+    
+    public DefaultJBIClient() {
+    }
+
+    /**
+     * Provides the JBI container used for message dispatch.
+     */
+    public DefaultJBIClient(JBIContainer container) throws JBIException {
+        this(container, new ActivationSpec());
+    }
+
+    /**
+     * Provides the JBI container and the activation specification, which can be used to register this
+     * client at a specific endpoint so that default container routing rules can be configured via dependency injection
+     * and the client endpoint metadata can be configured to allow services to talk to this client.
+     */
+    public DefaultJBIClient(JBIContainer container, ActivationSpec activationSpec) throws JBIException {
+        activationSpec.setComponent(this);
+        container.activateComponent(activationSpec);
+    }
+
+    public Destination createEndpoint(URI uri) throws JBIException {
+        // TODO
+        /*
+        ensureEndpointCreated(uri);
+        return new DefaultEndpoint(this);
+        */
+        return null;
+    }
+
+    public Destination createEndpoint(String uri) throws URISyntaxException, JBIException {
+        return createEndpoint(new URI(uri));
+    }
+    
+    // Properties
+    // -------------------------------------------------------------------------
+    public JBIContainer getContainer() {
+        if (container == null) {
+            container = createContainer();
+        }
+        return container;
+    }
+
+    public void setContainer(JBIContainer container) {
+        this.container = container;
+    }
+
+    // Implementation methods
+    // -------------------------------------------------------------------------
+    protected JBIContainer createContainer() {
+        return new JBIContainer();
+    }
+
+    protected void ensureEndpointCreated(URI uri) {
+    }
+}

Propchange: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultJBIClient.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultNamespaceContext.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultNamespaceContext.java?rev=391095&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultNamespaceContext.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultNamespaceContext.java Mon Apr  3 10:48:49 2006
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.servicemix.client;
+
+import javax.xml.xpath.*;
+import javax.xml.namespace.NamespaceContext;
+
+import java.util.*;
+
+/**
+ * An implementation of {@link NamespaceContext} which uses a simple Map where
+ * the keys are the prefixes and the values are the URIs
+ * 
+ * @version $Revision: $
+ */
+public class DefaultNamespaceContext implements NamespaceContext {
+
+    private final Map map;
+    private final NamespaceContext parent;
+
+    public DefaultNamespaceContext() {
+        this.map = new HashMap();
+        XPathFactory factory = XPathFactory.newInstance();
+        this.parent = factory.newXPath().getNamespaceContext();
+    }
+
+    public DefaultNamespaceContext(NamespaceContext parent, Map map) {
+        this.parent = parent;
+        this.map = map;
+    }
+
+    /**
+     * A helper method to make it easy to create newly populated instances
+     */
+    public DefaultNamespaceContext add(String prefix, String uri) {
+        map.put(prefix, uri);
+        return this;
+    }
+    
+    public String getNamespaceURI(String prefix) {
+        String answer = (String) map.get(prefix);
+        if (answer == null && parent != null) {
+            return parent.getNamespaceURI(prefix);
+        }
+        return answer;
+    }
+
+    public String getPrefix(String namespaceURI) {
+        for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
+            Map.Entry entry = (Map.Entry) iter.next();
+            if (namespaceURI.equals(entry.getValue())) {
+                return (String) entry.getKey();
+            }
+        }
+        if (parent != null) {
+            return parent.getPrefix(namespaceURI);
+        }
+        return null;
+    }
+
+    public Iterator getPrefixes(String namespaceURI) {
+        Set set = new HashSet();
+        for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
+            Map.Entry entry = (Map.Entry) iter.next();
+            if (namespaceURI.equals(entry.getValue())) {
+                set.add(entry.getKey());
+            }
+        }
+        if (parent != null) {
+            Iterator iter = parent.getPrefixes(namespaceURI);
+            while (iter.hasNext()) {
+                set.add(iter.next());
+            }
+        }
+        return set.iterator();
+    }
+}

Propchange: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/DefaultNamespaceContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Destination.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Destination.java?rev=391095&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Destination.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Destination.java Mon Apr  3 10:48:49 2006
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.servicemix.client;
+
+import javax.jbi.messaging.Fault;
+import javax.jbi.messaging.InOnly;
+import javax.jbi.messaging.InOptionalOut;
+import javax.jbi.messaging.InOut;
+import javax.jbi.messaging.MessageExchange;
+import javax.jbi.messaging.MessagingException;
+import javax.jbi.messaging.NormalizedMessage;
+import javax.jbi.messaging.RobustInOnly;
+
+/**
+ * Represents a JBI endpoint you can communicate with
+ * 
+ * @version $Revision: $
+ */
+public interface Destination {
+
+    /**
+     * Indicates that the endpoint is no longer required
+     */
+    void close();
+
+    // Simple one-way messaging API
+    // -------------------------------------------------------------------------
+
+    /**
+     * Registers an asynchronous listener to messages so that they can be
+     * processed as they become available
+     */
+    public void setMessageListener(MessageListener processor);
+
+    /**
+     * Creates a message ready to be sent to the endpoint via
+     * {@link #sendMessage(NormalizedMessage)}
+     * 
+     * @return
+     */
+    Message createMessage();
+
+    /**
+     * Creates a message ready to be sent to the endpoint via
+     * {@link #sendMessage(NormalizedMessage)}. The message has the given body
+     * attached
+     * 
+     * @return
+     * @throws MessagingException
+     */
+    Message createMessage(Object body) throws MessagingException;
+
+    /**
+     * Sends the message to the endpoint
+     * 
+     * @throws MessagingException
+     */
+    public void send(NormalizedMessage message) throws MessagingException;
+
+    // Methods which can block for a long time
+    // -------------------------------------------------------------------------
+
+    /**
+     * Receives a message from the endpoint.
+     * 
+     * Depending on the implementation this method could work with a declarative
+     * transaction model to know when you have completed processing the message
+     * correctly, otherwise for RobustInOnly then the message is acknowedged
+     * immediately.
+     * 
+     * @throws MessagingException
+     */
+    Message receive() throws MessagingException;
+
+    /**
+     * Pulls a single message from the endpoint and processes it ensuring that
+     * the message exchange is complete as soon as this method is called.
+     * 
+     * This method implicitly defines a unit of work around the message exchange
+     */
+    public void receive(MessageListener listener);
+
+    /**
+     * Performs a request response with the endpoint blocking until a response
+     * is available.
+     */
+    Message waitForResponse(Message requestMessage);
+
+    // Send and receive of message exchanges
+    // -------------------------------------------------------------------------
+
+    /**
+     * Sends the message exchange to the endpoint.
+     * 
+     * @param exchange
+     * @throws MessagingException
+     */
+    void send(MessageExchange exchange) throws MessagingException;
+
+    /**
+     * Sends the message exchange to the endpoint, blocking until the send has
+     * completed.
+     * 
+     * @param exchange
+     * @throws MessagingException
+     * @return true if the exchange has been processed and returned by the
+     *         servicing component, false otherwise.
+     */
+    boolean sendSync(MessageExchange exchange) throws MessagingException;
+
+    /**
+     * Receives an inbound message exchange, blocking forever until one is
+     * available.
+     * 
+     * @return the received message exchange
+     * @throws MessagingException
+     */
+    MessageExchange receiveExchange() throws MessagingException;
+
+    /**
+     * Receives an inbound message exchange, blocking until the given timeout
+     * period.
+     * 
+     * @param timeout
+     *            the maximum amount of time to wait for a message
+     * @return the received message exchange or null if the timeout occurred.
+     * @throws MessagingException
+     */
+    MessageExchange receiveExchange(long timeout) throws MessagingException;
+
+    // Factory methods to make MessageExchange instances
+    // -------------------------------------------------------------------------
+
+    /**
+     * Creates an {@link InOnly} (one way) message exchange.
+     * 
+     * @return the newly created message exchange
+     * @throws MessagingException
+     */
+    InOnly createInOnlyExchange() throws MessagingException;
+
+    /**
+     * Creates an {@link InOut} (request-reply) message exchange.
+     * 
+     * @return the newly created message exchange
+     * @throws MessagingException
+     */
+    InOut createInOutExchange() throws MessagingException;
+
+    /**
+     * Creates an {@link InOptionalOut} (optional request-reply) message
+     * exchange.
+     * 
+     * @return the newly created message exchange
+     * @throws MessagingException
+     */
+    InOptionalOut createInOptionalOutExchange() throws MessagingException;
+
+    /**
+     * Creates an {@link RobustInOnly} (one way) message exchange.
+     * 
+     * @return the newly created message exchange
+     * @throws MessagingException
+     */
+    RobustInOnly createRobustInOnlyExchange() throws MessagingException;
+
+    // API to explicitly acknowledge an inbound message as being complete
+    // -------------------------------------------------------------------------
+    
+    /**
+     * Marks this exchange as being complete; typically used for inbound
+     * messages
+     * 
+     * @throws MessagingException
+     */
+    public void done(MessageExchange message) throws MessagingException;
+
+    /**
+     * Marks this exchange as being complete; typically used for inbound
+     * messages
+     * 
+     * @throws MessagingException
+     */
+    public void done(Message message) throws MessagingException;
+
+    /**
+     * Marks this exchange as being failed with a fault
+     * 
+     * @throws MessagingException
+     */
+    public void fail(Fault fault) throws MessagingException;
+
+    /**
+     * Marks this exchange as being failed with an error
+     * 
+     * @throws MessagingException
+     */
+    public void fail(Message message, Exception fault) throws MessagingException;
+    
+    /**
+     * Marks this exchange as being failed with an error
+     * 
+     * @throws MessagingException
+     */
+    public void fail(MessageExchange exchange, Exception fault) throws MessagingException;
+}

Propchange: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Destination.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Message.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Message.java?rev=391095&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Message.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Message.java Mon Apr  3 10:48:49 2006
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.servicemix.client;
+
+import javax.jbi.messaging.Fault;
+import javax.jbi.messaging.MessageExchange;
+import javax.jbi.messaging.MessagingException;
+import javax.jbi.messaging.NormalizedMessage;
+
+/**
+ * An extension of the standard {@link NormalizedMessage} which allows you to
+ * work directly with message bodies as POJOs ignoring the XML stuff or passing a binary
+ * message around as a ByteBuffer or byte[]
+ * 
+ * @version $Revision: 359151 $
+ */
+public interface Message extends NormalizedMessage {
+
+    /**
+     * Returns the body as a POJO. Depending on the implementation this could be
+     * a Java POJO, a DOM tree or a byte[]
+     */
+    public Object getBody() throws MessagingException;
+
+    /**
+     * Sets the body as a POJO
+     */
+    public void setBody(Object body) throws MessagingException;
+
+    /**
+     * Returns the message exchange
+     */
+    public MessageExchange getExchange();
+
+    /**
+     * Helper method to create a new fault for this message exchange
+     */
+    public Fault createFault() throws MessagingException;
+}

Propchange: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/Message.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/MessageListener.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/MessageListener.java?rev=391095&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/MessageListener.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/MessageListener.java Mon Apr  3 10:48:49 2006
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.servicemix.client;
+
+import javax.jbi.messaging.MessageExchange;
+
+/**
+ * A listener which is called when a message is available to be processed.
+ * 
+ * @version $Revision: $
+ */
+public interface MessageListener {
+
+    /**
+     * Processes the message. By the completion of this method call, without exceptions
+     * being thrown the message is assumed to be processed unless the status is updated
+     * on the exchange.
+     * 
+     * @param exchange
+     * @param message
+     * @throws Exception if the message could not be processed correctly
+     */
+    public void onMessage(MessageExchange exchange, Message message) throws Exception;
+}

Propchange: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/MessageListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/XPathHelper.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/XPathHelper.java?rev=391095&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/XPathHelper.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/XPathHelper.java Mon Apr  3 10:48:49 2006
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.servicemix.client;
+
+
+import javax.jbi.messaging.NormalizedMessage;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.transform.Source;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathFunctionResolver;
+import javax.xml.xpath.XPathVariableResolver;
+
+import java.util.Map;
+
+/**
+ * A helper class for working with XPath and {@link Message} instances.
+ * 
+ * @version $Revision: $
+ */
+public class XPathHelper {
+    private Source content;
+    private XPathFactory xPathFactory;
+    private XPath xPath;
+
+    public XPathHelper() {
+    }
+
+    public XPathHelper(NormalizedMessage message) {
+        setMessage(message);
+    }
+
+    public XPathHelper(Source content) {
+        setContent(content);
+    }
+
+    public XPathHelper(Message message, Map namespaces) {
+        this(message);
+        setNamespaces(namespaces);
+    }
+
+    public XPathHelper(Message message, NamespaceContext namespaces) {
+        this(message);
+        setNamespaceContext(namespaces);
+    }
+
+    public Object evaluate(String expression, QName arg2) throws XPathExpressionException {
+        return getXPath().evaluate(expression, getItem(), arg2);
+    }
+
+    public String evaluate(String expression) throws XPathExpressionException {
+        return getXPath().evaluate(expression, getItem());
+    }
+
+    public void reset() {
+        if (xPath != null) {
+            getXPath().reset();
+        }
+    }
+
+    // Properties
+    // -------------------------------------------------------------------------
+    public void setMessage(NormalizedMessage message) {
+        setContent(message.getContent());
+    }
+
+    public void setContent(Source content) {
+        this.content = content;
+    }
+
+    public NamespaceContext getNamespaceContext() {
+        return getXPath().getNamespaceContext();
+    }
+
+    public XPathFunctionResolver getXPathFunctionResolver() {
+        return getXPath().getXPathFunctionResolver();
+    }
+
+    public XPathVariableResolver getXPathVariableResolver() {
+        return getXPath().getXPathVariableResolver();
+    }
+
+    public void setNamespaceContext(NamespaceContext context) {
+        getXPath().setNamespaceContext(context);
+    }
+
+    public void setXPathFunctionResolver(XPathFunctionResolver resolver) {
+        getXPath().setXPathFunctionResolver(resolver);
+    }
+
+    public void setXPathVariableResolver(XPathVariableResolver resolver) {
+        getXPath().setXPathVariableResolver(resolver);
+    }
+
+    public XPathFactory getXPathFactory() {
+        if (xPathFactory == null) {
+            xPathFactory = XPathFactory.newInstance();
+        }
+        return xPathFactory;
+    }
+
+    public void setXPathFactory(XPathFactory factory) {
+        this.xPathFactory = factory;
+    }
+
+    public Source getContent() {
+        return content;
+    }
+
+    public XPath getXPath() {
+        if (xPath == null) {
+            xPath = getXPathFactory().newXPath();
+        }
+        return xPath;
+    }
+
+    /**
+     * Sets the namespace context to the given map where the keys are namespace
+     * prefixes and the values are the URIs
+     */
+    public void setNamespaces(Map namespaces) {
+        setNamespaceContext(new DefaultNamespaceContext(getNamespaceContext(), namespaces));
+
+    }
+
+    // Implementation methods
+    // -------------------------------------------------------------------------
+    protected Object getItem() {
+        return content;
+    }
+}

Propchange: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/client/XPathHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/messaging/NormalizedMessageImpl.java
URL: http://svn.apache.org/viewcvs/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/messaging/NormalizedMessageImpl.java?rev=391095&r1=391094&r2=391095&view=diff
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/messaging/NormalizedMessageImpl.java (original)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/messaging/NormalizedMessageImpl.java Mon Apr  3 10:48:49 2006
@@ -15,12 +15,16 @@
  */
 package org.apache.servicemix.jbi.messaging;
 
+import org.apache.servicemix.client.Message;
+import org.apache.servicemix.jbi.RuntimeJBIException;
 import org.apache.servicemix.jbi.jaxp.BytesSource;
 import org.apache.servicemix.jbi.jaxp.ResourceSource;
 import org.apache.servicemix.jbi.jaxp.SourceTransformer;
 import org.apache.servicemix.jbi.jaxp.StringSource;
 
 import javax.activation.DataHandler;
+import javax.jbi.messaging.Fault;
+import javax.jbi.messaging.MessageExchange;
 import javax.jbi.messaging.MessagingException;
 import javax.jbi.messaging.NormalizedMessage;
 import javax.security.auth.Subject;
@@ -44,12 +48,13 @@
  *
  * @version $Revision$
  */
-public class NormalizedMessageImpl implements NormalizedMessage, Externalizable {
+public class NormalizedMessageImpl implements NormalizedMessage, Externalizable, Message {
     
     private static final long serialVersionUID = 9179194301410526549L;
     
     protected transient MessageExchangeImpl exchange;
     private transient Source content;
+    private transient Object body;
     private Subject securitySubject;
     private Map properties;
     private Map attachments;
@@ -79,6 +84,14 @@
      * @return the content of the message
      */
     public synchronized Source getContent() {
+        if (content == null && body != null) {
+            try {
+                getMarshaler().marshal(exchange, this, body);
+            }
+            catch (MessagingException e) {
+                throw new RuntimeJBIException(e);
+            }
+        }
         return content;
     }
 
@@ -210,11 +223,14 @@
     //-------------------------------------------------------------------------
 
     public Object getBody() throws MessagingException {
-        return getMarshaler().unmarshal(exchange, this);
+        if (body == null) {
+            body = getMarshaler().unmarshal(exchange, this);
+        }
+        return body;
     }
 
     public void setBody(Object body) throws MessagingException {
-        getMarshaler().marshal(exchange, this, body);
+        this.body = body;
     }
 
     public String getBodyText() throws TransformerException {
@@ -225,8 +241,16 @@
         setContent(new StringSource(xml));
     }
 
-    public  PojoMarshaler getMarshaler() {
+    public PojoMarshaler getMarshaler() {
         return exchange.getMarshaler();
+    }
+
+    public MessageExchange getExchange() {
+        return exchange;
+    }
+
+    public Fault createFault() throws MessagingException {
+        return getExchange().createFault();
     }