You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by gn...@apache.org on 2008/06/05 14:23:01 UTC

svn commit: r663580 - in /servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support: BeanSupport.java ExchangeTarget.java TransformBeanSupport.java

Author: gnodet
Date: Thu Jun  5 05:23:01 2008
New Revision: 663580

URL: http://svn.apache.org/viewvc?rev=663580&view=rev
Log:
SM-1305: Provide convenient base classes to simplify servicemix-bean component development (including IN-only MEP Transforms)

Added:
    servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java   (with props)
    servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java   (with props)
    servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java   (with props)

Added: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java
URL: http://svn.apache.org/viewvc/servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java?rev=663580&view=auto
==============================================================================
--- servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java (added)
+++ servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java Thu Jun  5 05:23:01 2008
@@ -0,0 +1,426 @@
+/*
+ * 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.servicemix.bean.support;
+
+import javax.annotation.Resource;
+import javax.jbi.component.ComponentContext;
+import javax.jbi.messaging.DeliveryChannel;
+import javax.jbi.messaging.ExchangeStatus;
+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.MessageExchangeFactory;
+import javax.jbi.messaging.MessagingException;
+import javax.jbi.messaging.NormalizedMessage;
+import javax.jbi.messaging.RobustInOnly;
+import javax.management.ObjectName;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.servicemix.JbiConstants;
+import org.apache.servicemix.bean.BeanEndpoint;
+import org.apache.servicemix.components.util.CopyTransformer;
+import org.apache.servicemix.components.util.MessageHelper;
+import org.apache.servicemix.components.util.MessageTransformer;
+import org.apache.servicemix.jbi.FaultException;
+import org.apache.servicemix.jbi.NoInMessageAvailableException;
+
+/**
+ * A useful base class for servicemix-bean POJOs
+ *
+ * @version $$
+ */
+public abstract class BeanSupport {
+
+    protected Log logger = LogFactory.getLog(getClass());
+    
+    @Resource
+    private ComponentContext context;
+    
+    @Resource
+    private DeliveryChannel channel;
+    
+    @Resource
+    private BeanEndpoint beanEndpoint;
+    
+    private ObjectName extensionMBeanName;
+    private MessageExchangeFactory exchangeFactory;
+    private MessageTransformer messageTransformer = CopyTransformer.getInstance();
+    
+    protected BeanSupport() {
+    }
+    
+    // Helper methods
+    //-------------------------------------------------------------------------
+
+    /**
+     * A helper method to return the body of the message as a POJO which could be a
+     * bean or some DOMish model of the body.
+     *
+     * @param message the message on which to extract the body
+     * @return the body of the message as a POJO or DOM object
+     * @throws MessagingException
+     */
+    public Object getBody(NormalizedMessage message) throws MessagingException {
+        return MessageHelper.getBody(message);
+    }
+
+    /**
+     * Sets the body of the message as a POJO
+     *
+     * @param message the message on which to set the body
+     * @param body    the POJO or DOMish model to set
+     * @throws MessagingException
+     */
+    public void setBody(NormalizedMessage message, Object body) throws MessagingException {
+        MessageHelper.setBody(message, body);
+    }
+
+
+    // Properties
+    //-------------------------------------------------------------------------
+    public ObjectName getExtensionMBeanName() {
+        return extensionMBeanName;
+    }
+
+    public void setExtensionMBeanName(ObjectName extensionMBeanName) {
+        this.extensionMBeanName = extensionMBeanName;
+    }
+
+    public ComponentContext getContext() {
+        return context;
+    }
+    
+    public void setContext(ComponentContext context) {
+        this.context = context;
+    }
+
+    public BeanEndpoint getBeanEndpoint() {
+        return beanEndpoint;
+    }
+    
+    public void setBeanEndpoint(BeanEndpoint beanEndpoint) {
+        this.beanEndpoint = beanEndpoint;
+    }
+    
+    /**
+     * Provide access to the default message exchange exchangeFactory, lazily creating one.
+     */
+    public MessageExchangeFactory getExchangeFactory() throws MessagingException {
+        if (exchangeFactory == null && context != null) {
+            exchangeFactory = getDeliveryChannel().createExchangeFactory();
+        }
+        return exchangeFactory;
+    }
+
+    public DeliveryChannel getDeliveryChannel() throws MessagingException {
+        if (channel == null) {
+            channel = context.getDeliveryChannel();
+        }
+        return channel;
+    }
+
+    /**
+     * A helper method to indicate that the message exchange is complete
+     * which will set the status to {@link ExchangeStatus#DONE} and send the message
+     * on the delivery channel.
+     *
+     * @param exchange
+     * @throws MessagingException
+     */
+    public void done(MessageExchange exchange) throws MessagingException {
+        exchange.setStatus(ExchangeStatus.DONE);
+        getDeliveryChannel().send(exchange);
+    }
+
+    public void send(MessageExchange exchange) throws MessagingException {
+        getDeliveryChannel().send(exchange);
+    }
+    
+    public boolean sendSync(MessageExchange exchange) throws MessagingException {
+        return getDeliveryChannel().sendSync(exchange);
+    }
+
+    public boolean sendSync(MessageExchange exchange, long timeMillis) throws MessagingException {
+        return getDeliveryChannel().sendSync(exchange, timeMillis);
+    }
+
+    /**
+     * A helper method to indicate that the message exchange should be
+     * continued with the given response and send the message
+     * on the delivery channel.
+     *
+     * @param exchange
+     * @throws MessagingException
+     */
+    public void answer(MessageExchange exchange, NormalizedMessage answer) throws MessagingException {
+        exchange.setMessage(answer, "out");
+        getDeliveryChannel().send(exchange);
+    }
+
+    /**
+     * A helper method which fails and completes the given exchange with the specified fault
+     */
+    public void fail(MessageExchange exchange, Fault fault) throws MessagingException {
+        if (exchange instanceof InOnly || fault == null) {
+            exchange.setError(new FaultException("Fault occured for in-only exchange", exchange, fault));
+        } else {
+            exchange.setFault(fault);
+        }
+        getDeliveryChannel().send(exchange);
+    }
+
+    /**
+     * A helper method which fails and completes the given exchange with the specified error
+     * @throws MessagingException 
+     */
+    public void fail(MessageExchange exchange, Exception error) throws MessagingException {
+        if (exchange instanceof InOnly || !(error instanceof FaultException)) {
+            exchange.setError(error);
+        } else {
+            FaultException faultException = (FaultException) error;
+            exchange.setFault(faultException.getFault());
+        }
+        getDeliveryChannel().send(exchange);
+    }
+
+
+    /**
+     * A helper method which will return true if the exchange is capable of both In and Out such as InOut,
+     * InOptionalOut etc.
+     *
+     * @param exchange
+     * @return true if the exchange can handle both input and output
+     */
+    protected boolean isInAndOut(MessageExchange exchange) {
+        return exchange instanceof InOut || exchange instanceof InOptionalOut;
+    }
+
+    /**
+     * Returns the in message or throws an exception if there is no in message.
+     */
+    protected NormalizedMessage getInMessage(MessageExchange exchange) throws NoInMessageAvailableException {
+        NormalizedMessage message = exchange.getMessage("in");
+        if (message == null) {
+            throw new NoInMessageAvailableException(exchange);
+        }
+        return message;
+    }
+
+    public MessageTransformer getMessageTransformer() {
+        return messageTransformer;
+    }
+
+    public void setMessageTransformer(MessageTransformer transformer) {
+        this.messageTransformer = transformer;
+    }
+
+    /**
+     * Performs an invocation where the service, operation or interface name could be specified
+     *
+     * @param exchange
+     * @param in
+     * @param service
+     * @param interfaceName
+     * @param operation
+     */
+    public void invoke(MessageExchange exchange, NormalizedMessage in, 
+                       QName service, QName interfaceName, QName operation) throws MessagingException {
+        InOnly outExchange = createInOnlyExchange(service, interfaceName, operation);
+        forwardToExchange(exchange, outExchange, in, operation);
+    }
+
+    /**
+     * Creates a new InOnly exchange for the given service, interface and/or operation (any of which can be null).
+     */
+    public InOnly createInOnlyExchange(QName service, QName interfaceName, QName operation) throws MessagingException {
+        MessageExchangeFactory factory = null;
+        if (service != null) {
+            factory = getDeliveryChannel().createExchangeFactoryForService(service);
+        } else if (interfaceName != null) {
+            factory = getDeliveryChannel().createExchangeFactory(interfaceName);
+        } else {
+            factory = getExchangeFactory();
+        }
+        InOnly outExchange = factory.createInOnlyExchange();
+        if (service != null) {
+            outExchange.setService(service);
+        }
+        if (interfaceName != null) {
+            outExchange.setInterfaceName(interfaceName);
+        }
+        if (operation != null) {
+            outExchange.setOperation(operation);
+        }
+        return outExchange;
+    }
+
+    public InOnly createInOnlyExchange(QName service, QName interfaceName, 
+                                       QName operation, MessageExchange beforeExchange) throws MessagingException {
+        InOnly inOnly = createInOnlyExchange(service, interfaceName, operation);
+        propagateCorrelationId(beforeExchange, inOnly);
+        return inOnly;
+    }
+
+    /**
+     * Creates a new InOut exchange for the given service, interface and/or operation (any of which can be null).
+     */
+    public InOut createInOutExchange(QName service, QName interfaceName, QName operation) throws MessagingException {
+        MessageExchangeFactory factory = null;
+        if (service != null) {
+            factory = getDeliveryChannel().createExchangeFactoryForService(service);
+        } else if (interfaceName != null) {
+            factory = getDeliveryChannel().createExchangeFactory(interfaceName);
+        } else {
+            factory = getExchangeFactory();
+        }
+        InOut outExchange = factory.createInOutExchange();
+        if (service != null) {
+            outExchange.setService(service);
+        }
+        if (interfaceName != null) {
+            outExchange.setInterfaceName(interfaceName);
+        }
+        if (operation != null) {
+            outExchange.setOperation(operation);
+        }
+        return outExchange;
+    }
+
+    public InOut createInOutExchange(QName service, QName interfaceName, 
+                                    QName operation, MessageExchange srcExchange) throws MessagingException {
+        InOut inOut = createInOutExchange(service, interfaceName, operation);
+        propagateCorrelationId(srcExchange, inOut);
+        return inOut;
+    }
+
+    /**
+     * Creates an InOnly exchange and propagates the correlation id from the given exchange
+     * to the newly created exchange
+     * @param srcExchange
+     * @return InOnly
+     * @throws MessagingException
+     */
+    public InOnly createInOnlyExchange(MessageExchange srcExchange) throws MessagingException {
+        MessageExchangeFactory factory = getExchangeFactory();
+        InOnly inOnly = factory.createInOnlyExchange();
+
+        propagateCorrelationId(srcExchange, inOnly);
+
+        return inOnly;
+    }
+
+    /**
+     * Creates an InOptionalOut exchange and propagates the correlation id from the given exchange
+     * to the newly created exchange
+     * @param srcExchange
+     * @return InOptionalOut
+     * @throws MessagingException
+     */
+    public InOptionalOut createInOptionalOutExchange(MessageExchange srcExchange) throws MessagingException {
+        MessageExchangeFactory factory = getExchangeFactory();
+        InOptionalOut inOptionalOut = factory.createInOptionalOutExchange();
+
+        propagateCorrelationId(srcExchange, inOptionalOut);
+
+        return inOptionalOut;
+    }
+
+    /**
+     * Creates an InOut exchange and propagates the correlation id from the given exchange
+     * to the newly created exchange
+     * @param srcExchange
+     * @return InOut
+     * @throws MessagingException
+     */
+    public InOut createInOutExchange(MessageExchange srcExchange) throws MessagingException {
+        MessageExchangeFactory factory = getExchangeFactory();
+        InOut inOut = factory.createInOutExchange();
+
+        propagateCorrelationId(srcExchange, inOut);
+
+        return inOut;
+    }
+
+    /**
+     * Creates an RobustInOnly exchange and propagates the correlation id from the given exchange
+     * to the newly created exchange
+     * @param srcExchange
+     * @return RobustInOnly the created exchange
+     * @throws MessagingException
+     */
+    public RobustInOnly createRobustInOnlyExchange(MessageExchange srcExchange) throws MessagingException {
+        MessageExchangeFactory factory = getExchangeFactory();
+        RobustInOnly robustInOnly = factory.createRobustInOnlyExchange();
+
+        propagateCorrelationId(srcExchange, robustInOnly);
+
+        return robustInOnly;
+    }
+
+    /**
+     * Propagates the correlation id from an exchange to a newly created exchange
+     * @param source Exchange which already exists
+     * @param dest Newly created exchange which should get the correlation id
+     */
+    public void propagateCorrelationId(MessageExchange source, MessageExchange dest) {
+        if (source == null || dest == null) {
+            return;
+        }
+        String correlationId = (String) source.getProperty(JbiConstants.CORRELATION_ID);
+        if (correlationId != null) {
+            dest.setProperty(JbiConstants.CORRELATION_ID, correlationId);
+        } else {
+            dest.setProperty(JbiConstants.CORRELATION_ID, source.getExchangeId());
+        }
+    }
+
+    protected void forwardToExchange(MessageExchange exchange, InOnly outExchange, 
+                                     NormalizedMessage in, QName operationName) throws MessagingException {
+        if (operationName != null) {
+            exchange.setOperation(operationName);
+        }
+        forwardToExchange(exchange, outExchange, in);
+    }
+
+    protected void forwardToExchange(MessageExchange exchange, InOnly outExchange, NormalizedMessage in) throws MessagingException {
+        NormalizedMessage out = outExchange.createMessage();
+        outExchange.setInMessage(out);
+        getMessageTransformer().transform(exchange, in, out);
+        getDeliveryChannel().send(outExchange);
+    }
+    
+    protected QName getService() {
+        QName service = null;
+        if (beanEndpoint != null) {
+            service = beanEndpoint.getService();
+        }
+        return service;
+    }
+
+    protected String getEndpoint() {
+        String endpoint = null;
+        if (beanEndpoint != null) {
+            endpoint = beanEndpoint.getEndpoint();
+        }
+        return endpoint;
+    }
+
+}

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/BeanSupport.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java
URL: http://svn.apache.org/viewvc/servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java?rev=663580&view=auto
==============================================================================
--- servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java (added)
+++ servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java Thu Jun  5 05:23:01 2008
@@ -0,0 +1,159 @@
+/*
+ * 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.servicemix.bean.support;
+
+import javax.jbi.component.ComponentContext;
+import javax.jbi.messaging.MessageExchange;
+import javax.jbi.messaging.MessagingException;
+import javax.jbi.servicedesc.ServiceEndpoint;
+import javax.xml.namespace.QName;
+
+import org.apache.servicemix.jbi.resolver.URIResolver;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * An ExchangeTarget may be used to specify the target of an exchange,
+ * while retaining all the JBI features (interface based routing, service
+ * name based routing or endpoint routing).
+ *   
+ * @author gnodet
+ * @version $Revision$
+ * @org.apache.xbean.XBean element="exchange-target"
+ */
+public class ExchangeTarget implements InitializingBean {
+
+    private QName interf;
+
+    private QName operation;
+
+    private QName service;
+
+    private String endpoint;
+    
+    private String uri;
+
+    /**
+     * @return Returns the endpoint.
+     */
+    public String getEndpoint() {
+        return endpoint;
+    }
+
+    /**
+     * @param endpoint
+     *            The endpoint to set.
+     */
+    public void setEndpoint(String endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    /**
+     * @return Returns the interface name.
+     */
+    public QName getInterface() {
+        return interf;
+    }
+
+    /**
+     * @param interface name
+     *            The interface name to set.
+     */
+    public void setInterface(QName itf) {
+        this.interf = itf;
+    }
+
+    /**
+     * @return Returns the operation name.
+     */
+    public QName getOperation() {
+        return operation;
+    }
+
+    /**
+     * @param operation
+     *            The operation to set.
+     */
+    public void setOperation(QName operation) {
+        this.operation = operation;
+    }
+
+    /**
+     * @return Returns the service.
+     */
+    public QName getService() {
+        return service;
+    }
+
+    /**
+     * @param service
+     *            The service to set.
+     */
+    public void setService(QName service) {
+        this.service = service;
+    }
+
+    /**
+     * @return the uri
+     */
+    public String getUri() {
+        return uri;
+    }
+
+    /**
+     * @param uri the uri to set
+     */
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    /**
+     * Configures the target on the newly created exchange 
+     * @param exchange the exchange to configure
+     * @throws MessagingException if the target could not be configured
+     */
+    public void configureTarget(MessageExchange exchange, ComponentContext context) throws MessagingException {
+        if (interf == null && service == null && uri == null) {
+            throw new MessagingException("interface, service or uri should be specified");
+        }
+        if (uri != null) {
+            URIResolver.configureExchange(exchange, context, uri);
+        }
+        if (interf != null) {
+            exchange.setInterfaceName(interf);
+        }
+        if (operation != null) {
+            exchange.setOperation(operation);
+        }
+        if (service != null) {
+            exchange.setService(service);
+            if (endpoint != null) {
+                ServiceEndpoint se = context.getEndpoint(service, endpoint);
+                exchange.setEndpoint(se);
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+     */
+    public void afterPropertiesSet() throws Exception {
+        if (interf == null && service == null && uri == null) {
+            throw new MessagingException("interface, service or uri should be specified");
+        }
+    }
+
+}

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/ExchangeTarget.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java
URL: http://svn.apache.org/viewvc/servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java?rev=663580&view=auto
==============================================================================
--- servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java (added)
+++ servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java Thu Jun  5 05:23:01 2008
@@ -0,0 +1,157 @@
+/*
+ * 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.servicemix.bean.support;
+
+import javax.annotation.Resource;
+import javax.jbi.messaging.ExchangeStatus;
+import javax.jbi.messaging.InOnly;
+import javax.jbi.messaging.MessageExchange;
+import javax.jbi.messaging.MessagingException;
+import javax.jbi.messaging.NormalizedMessage;
+
+import org.apache.servicemix.JbiConstants;
+import org.apache.servicemix.MessageExchangeListener;
+import org.apache.servicemix.components.util.CopyTransformer;
+
+/**
+ * A useful base class for a transform component.
+ *
+ * @version $Revision$
+ */
+public abstract class TransformBeanSupport extends BeanSupport implements MessageExchangeListener {
+    
+    @Resource
+    private ExchangeTarget target;
+
+    private boolean copyProperties = true;
+    private boolean copyAttachments = true;
+
+    protected TransformBeanSupport() {
+    }
+
+    public void onMessageExchange(MessageExchange exchange) {
+        // Skip done exchanges
+        if (exchange.getStatus() == ExchangeStatus.DONE) {
+            return;
+        // Handle error exchanges
+        } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
+            return;
+        }
+        try {
+            InOnly outExchange = null;
+            NormalizedMessage in = getInMessage(exchange);
+            NormalizedMessage out;
+            if (isInAndOut(exchange)) {
+                out = exchange.createMessage();
+            } else {
+                if (target == null) {
+                    throw new IllegalStateException("An IN-ONLY TransformBean has no Target specified");
+                }
+                outExchange = getExchangeFactory().createInOnlyExchange();
+                target.configureTarget(exchange, getContext());
+                outExchange.setProperty(JbiConstants.SENDER_ENDPOINT, getService() + ":" + getEndpoint());
+                String processCorrelationId = (String)exchange.getProperty(JbiConstants.CORRELATION_ID);
+                if (processCorrelationId != null) {
+                    outExchange.setProperty(JbiConstants.CORRELATION_ID, processCorrelationId);
+                }
+                out = outExchange.createMessage();
+            }
+            boolean txSync = exchange.isTransacted() && Boolean.TRUE.equals(exchange.getProperty(JbiConstants.SEND_SYNC));
+            copyPropertiesAndAttachments(exchange, in, out);
+            if (transform(exchange, in, out)) {
+                if (isInAndOut(exchange)) {
+                    exchange.setMessage(out, "out");
+                    if (txSync) {
+                        getDeliveryChannel().sendSync(exchange);
+                    } else {
+                        getDeliveryChannel().send(exchange);
+                    }
+                } else {
+                    outExchange.setMessage(out, "in");
+                    if (txSync) {
+                        getDeliveryChannel().sendSync(outExchange);
+                    } else {
+                        getDeliveryChannel().send(outExchange);
+                    }
+                    exchange.setStatus(ExchangeStatus.DONE);
+                    getDeliveryChannel().send(exchange);
+                }
+            } else {
+                exchange.setStatus(ExchangeStatus.DONE);
+                getDeliveryChannel().send(exchange);
+            }
+        } catch (Exception e) {
+            try {
+                fail(exchange, e);
+            } catch (Exception e2) {
+                logger.warn("Unable to handle error: " + e2, e2);
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Original error: " + e, e);
+                }
+            }
+        }
+    }
+
+
+    // Implementation methods
+    //-------------------------------------------------------------------------
+
+    /**
+     * Transforms the given out message
+     */
+    protected abstract boolean transform(MessageExchange exchange, NormalizedMessage in, NormalizedMessage out) throws Exception;
+
+
+    public boolean isCopyProperties() {
+        return copyProperties;
+    }
+
+
+    public void setCopyProperties(boolean copyProperties) {
+        this.copyProperties = copyProperties;
+        if (getMessageTransformer() instanceof CopyTransformer) {
+            ((CopyTransformer) getMessageTransformer()).setCopyProperties(copyProperties);
+        }
+    }
+
+
+    public boolean isCopyAttachments() {
+        return copyAttachments;
+    }
+
+
+    public void setCopyAttachments(boolean copyAttachments) {
+        this.copyAttachments = copyAttachments;
+        if (getMessageTransformer() instanceof CopyTransformer) {
+            ((CopyTransformer) getMessageTransformer()).setCopyAttachments(copyAttachments);
+        }
+    }
+
+
+    /**
+     * If enabled the properties and attachments are copied to the destination message
+     */
+    protected void copyPropertiesAndAttachments(MessageExchange exchange, NormalizedMessage in, 
+                                                NormalizedMessage out) throws MessagingException {
+        if (isCopyProperties()) {
+            CopyTransformer.copyProperties(in, out);
+        }
+        if (isCopyAttachments()) {
+            CopyTransformer.copyAttachments(in, out);
+        }
+    }
+}

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: servicemix/smx3/trunk/deployables/serviceengines/servicemix-bean/src/main/java/org/apache/servicemix/bean/support/TransformBeanSupport.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain