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/10/21 14:49:36 UTC

svn commit: r706613 - in /servicemix/smx4/nmr/trunk/nmr: api/src/main/java/org/apache/servicemix/nmr/api/ core/src/main/java/org/apache/servicemix/nmr/core/ core/src/main/java/org/apache/servicemix/nmr/core/util/ core/src/test/java/org/apache/servicemi...

Author: gnodet
Date: Tue Oct 21 05:49:36 2008
New Revision: 706613

URL: http://svn.apache.org/viewvc?rev=706613&view=rev
Log:
SMX4NMR-51: Exchanges should be logged at debug level as in smx3

Added:
    servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/NmrRuntimeException.java
    servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/util/ExchangeUtils.java
    servicemix/smx4/nmr/trunk/nmr/core/src/test/java/org/apache/servicemix/nmr/core/util/ExchangeUtilsTest.java
Modified:
    servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Exchange.java
    servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Message.java
    servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ChannelImpl.java
    servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ExchangeImpl.java
    servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/MessageImpl.java

Modified: servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Exchange.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Exchange.java?rev=706613&r1=706612&r2=706613&view=diff
==============================================================================
--- servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Exchange.java (original)
+++ servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Exchange.java Tue Oct 21 05:49:36 2008
@@ -305,16 +305,21 @@
      * attachments are transformed to re-readable sources.
      * This method will be called by the framework when persisting
      * the exchange or when displaying it
-     *
-     * TODO: do we really need that?
      */
     void ensureReReadable();
 
     /**
-     * TODO: is toString() sufficient 
+     * Returns a string representation of this exchange.
+     * The <code>displayContent</code> property can be specified to
+     * control wether the content should be displayed or not.
+     * If set to <code>true</code>, the content and attachments will
+     * be converted into re-readable objects (for java.io.InputStream
+     * and javax.xml.transform.Source objects) and printed.
      *
-     * @param displayContent
-     * @return
+     * @param displayContent if the content and attachments of the exchange
+     *                       should be transformed if needed and displayed
+     *                       or left unmodified
+     * @return the string representation
      */
     String display(boolean displayContent);
 

Modified: servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Message.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Message.java?rev=706613&r1=706612&r2=706613&view=diff
==============================================================================
--- servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Message.java (original)
+++ servicemix/smx4/nmr/trunk/nmr/api/src/main/java/org/apache/servicemix/nmr/api/Message.java Tue Oct 21 05:49:36 2008
@@ -235,12 +235,22 @@
      * attachments are transformed to re-readable sources.
      * This method will be called by the framework when persisting
      * the message or when displaying it.
-     *
-     * TODO: do we really need this method
      */
-    void        ensureReReadable();
+    void ensureReReadable();
 
-    // TODO: is toString() sufficient ?
-    String      display(boolean displayContent);
+    /**
+     * Returns a string representation of this message.
+     * The <code>displayContent</code> property can be specified to
+     * control wether the content should be displayed or not.
+     * If set to <code>true</code>, the content and attachments will
+     * be converted into re-readable objects (for java.io.InputStream
+     * and javax.xml.transform.Source objects) and printed.
+     *
+     * @param displayContent if the content and attachments of the exchange
+     *                       should be transformed if needed and displayed
+     *                       or left unmodified
+     * @return the string representation
+     */
+    String display(boolean displayContent);
 
 }

Modified: servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ChannelImpl.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ChannelImpl.java?rev=706613&r1=706612&r2=706613&view=diff
==============================================================================
--- servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ChannelImpl.java (original)
+++ servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ChannelImpl.java Tue Oct 21 05:49:36 2008
@@ -46,7 +46,7 @@
  */
 public class ChannelImpl implements InternalChannel {
 
-    private static final Log LOG = LogFactory.getLog(ChannelImpl.class);
+    private static final Log LOG = LogFactory.getLog(NMR.class);
 
     private final InternalEndpoint endpoint;
     private final Executor executor;
@@ -163,6 +163,12 @@
      * @param exchange the exchange to delivery
      */
     public void deliver(final InternalExchange exchange) {
+        // Log the exchange
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Channel " + name + " delivering exchange: " + exchange.display(true));
+        } else if (LOG.isDebugEnabled()) {
+            LOG.debug("Channel " + name + " delivering exchange: " + exchange.display(false));
+        }
         // Handle case where the exchange has been sent synchronously
         Semaphore lock = exchange.getRole() == Role.Provider ? exchange.getConsumerLock(false)
                 : exchange.getProviderLock(false);
@@ -211,8 +217,11 @@
      * @param exchange the exchange to dispatch
      */
     protected void dispatch(InternalExchange exchange) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Channel " + name + " dispatching exchange " + exchange);
+        // Log the exchange
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Channel " + name + " dispatching exchange: " + exchange.display(true));
+        } else if (LOG.isDebugEnabled()) {
+            LOG.debug("Channel " + name + " dispatching exchange: " + exchange.display(false));
         }
         // Set source endpoint
         if (exchange.getSource() == null) {

Modified: servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ExchangeImpl.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ExchangeImpl.java?rev=706613&r1=706612&r2=706613&view=diff
==============================================================================
--- servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ExchangeImpl.java (original)
+++ servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/ExchangeImpl.java Tue Oct 21 05:49:36 2008
@@ -33,6 +33,7 @@
 import org.apache.servicemix.nmr.api.Type;
 import org.apache.servicemix.nmr.api.internal.InternalEndpoint;
 import org.apache.servicemix.nmr.api.internal.InternalExchange;
+import org.apache.servicemix.nmr.core.util.ExchangeUtils;
 
 /**
  * The default {@link Exchange} implementation.
@@ -375,15 +376,7 @@
     }
 
     public void ensureReReadable() {
-        if (in != null) {
-            in.ensureReReadable();
-        }
-        if (out != null) {
-            out.ensureReReadable();
-        }
-        if (fault != null) {
-            fault.ensureReReadable();
-        }
+        ExchangeUtils.ensureReReadable(this);
     }
 
     /**
@@ -422,18 +415,11 @@
     }
 
     public String display(boolean displayContent) {
-        if (displayContent) {
-            ensureReReadable();
-        }
-        StringBuilder sb = new StringBuilder();
-        sb.append("Exchange [");
-        sb.append("id=").append(id);
-        sb.append("]");
-        return sb.toString();
+        return ExchangeUtils.display(this, displayContent);
     }
 
     public String toString() {
-        return display(true);
+        return display(false);
     }
 
     public InternalEndpoint getSource() {

Modified: servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/MessageImpl.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/MessageImpl.java?rev=706613&r1=706612&r2=706613&view=diff
==============================================================================
--- servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/MessageImpl.java (original)
+++ servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/MessageImpl.java Tue Oct 21 05:49:36 2008
@@ -23,6 +23,7 @@
 import javax.security.auth.Subject;
 
 import org.apache.servicemix.nmr.api.Message;
+import org.apache.servicemix.nmr.core.util.ExchangeUtils;
 
 /**
  * The default {@link Message} implementation.
@@ -311,10 +312,9 @@
      * This method will be called by the framework when persisting
      * the message or when displaying it.
      * <p/>
-     * TODO: do we really need this method
      */
     public void ensureReReadable() {
-        // TODO: implement        
+        ExchangeUtils.ensureReReadable(this);
     }
 
     /**
@@ -385,6 +385,6 @@
     }
 
     public String toString() {
-        return display(true);
+        return display(false);
     }
 }

Added: servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/NmrRuntimeException.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/NmrRuntimeException.java?rev=706613&view=auto
==============================================================================
--- servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/NmrRuntimeException.java (added)
+++ servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/NmrRuntimeException.java Tue Oct 21 05:49:36 2008
@@ -0,0 +1,35 @@
+/*
+ * 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.nmr.core;
+
+public class NmrRuntimeException extends RuntimeException {
+
+    public NmrRuntimeException() {
+    }
+
+    public NmrRuntimeException(String message) {
+        super(message);
+    }
+
+    public NmrRuntimeException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public NmrRuntimeException(Throwable cause) {
+        super(cause);
+    }
+}

Added: servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/util/ExchangeUtils.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/util/ExchangeUtils.java?rev=706613&view=auto
==============================================================================
--- servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/util/ExchangeUtils.java (added)
+++ servicemix/smx4/nmr/trunk/nmr/core/src/main/java/org/apache/servicemix/nmr/core/util/ExchangeUtils.java Tue Oct 21 05:49:36 2008
@@ -0,0 +1,235 @@
+/*
+ * 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.nmr.core.util;
+
+import java.util.Arrays;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.servicemix.nmr.api.Exchange;
+import org.apache.servicemix.nmr.api.Message;
+import org.apache.servicemix.nmr.api.Type;
+import org.apache.servicemix.nmr.core.NmrRuntimeException;
+
+public class ExchangeUtils {
+
+    public static final int MAX_MSG_DISPLAY_SIZE = 1500;
+
+    public static String display(Exchange exchange, boolean displayContent) {
+        if (displayContent) {
+            ensureReReadable(exchange);
+        }
+        StringBuffer sb = new StringBuffer();
+        sb.append("[\n");
+        sb.append("  id:        ").append(exchange.getId()).append('\n');
+        sb.append("  mep:       ").append(exchange.getPattern()).append('\n');
+        sb.append("  status:    ").append(exchange.getStatus()).append('\n');
+        sb.append("  role:      ").append(exchange.getRole()).append('\n');
+        if (exchange.getTarget() != null) {
+            sb.append("  target:    ").append(exchange.getTarget()).append('\n');
+        }
+        if (exchange.getOperation() != null) {
+            sb.append("  operation: ").append(exchange.getOperation()).append('\n');
+        }
+        if (exchange.getProperties().size() > 0) {
+            sb.append("  properties: [").append('\n');
+            for (String key : exchange.getProperties().keySet()) {
+                sb.append("      ").append(key).append(" = ");
+                Object contents = exchange.getProperty(key);
+                sb.append(convertDisplay(contents));
+                sb.append('\n');
+            }
+            sb.append("  ]").append('\n');
+        }
+        display(exchange, Type.In, sb);
+        display(exchange, Type.Out, sb);
+        display(exchange, Type.Fault, sb);
+        sb.append("]\n");
+        return sb.toString();
+    }
+
+    public static void display(Exchange exchange, Type type, StringBuffer sb) {
+        Message message = exchange.getMessage(type, false);
+        if (message != null) {
+            sb.append("  ").append(type).append(": [").append('\n');
+            sb.append("    content: ");
+            try {
+                if (message.getBody() != null) {
+                    Object contents = message.getBody();
+                    sb.append(convertDisplay(contents));
+                } else {
+                    sb.append("null");
+                }
+            } catch (Exception e) {
+                sb.append("Unable to display: ").append(e);
+            }
+            sb.append('\n');
+            if (message.getAttachments().size() > 0) {
+                sb.append("    attachments: [").append('\n');
+                for (String key : message.getAttachments().keySet()) {
+                    Object contents = message.getAttachment(key);
+                    sb.append("      ").append(key).append(" = ").append(convertDisplay(contents)).append('\n');
+                }
+                sb.append("    ]").append('\n');
+            }
+            if (message.getHeaders().size() > 0) {
+                sb.append("    properties: [").append('\n');
+                for (String key : message.getHeaders().keySet()) {
+                    sb.append("      ").append(key).append(" = ");
+                    Object contents = message.getHeader(key);
+                    sb.append(convertDisplay(contents));
+                    sb.append('\n');
+                }
+                sb.append("    ]").append('\n');
+            }
+            sb.append("  ]").append('\n');
+        }
+    }
+
+    private static String convertDisplay(Object object) {
+        try {
+            String result;
+            if (object instanceof ByteArrayInputStream) {
+                InputStream is = (InputStream) object;
+                byte[] data = new byte[is.available()];
+                is.mark(0);
+                is.read(data);
+                is.reset();
+                // Heuristic to check if this is a string
+                if (isBinary(data)) {
+                    result = Arrays.toString(data);
+                } else {
+                    result = new String(data);
+                }
+            } else if (object instanceof DOMSource) {
+                StringWriter buffer = new StringWriter();
+                Transformer transformer = TransformerFactory.newInstance().newTransformer();
+                transformer.transform((DOMSource) object, new StreamResult(buffer));
+                result = buffer.toString();
+            } else if (object != null) {
+                result = object.toString();
+            } else {
+                result = "<null>";
+            }
+            // trim if too long
+            if (result.length() > MAX_MSG_DISPLAY_SIZE) {
+                result = result.substring(0, MAX_MSG_DISPLAY_SIZE) + "...";
+            }
+            return result;
+        } catch (Exception e) {
+            return "Error display value (" + e.toString() + ")";
+        }
+    }
+
+    private static boolean isBinary(byte[] data) {
+        if (data.length == 0) {
+            return true;
+        }
+        double prob_bin = 0;
+        for (int i = 0; i < data.length; i++) {
+            int j = (int) data[i];
+            if (j < 32 || j > 127) {
+                prob_bin++;
+            }
+        }
+        double pb = prob_bin / data.length;
+        return pb > 0.5;
+    }
+
+    public static void ensureReReadable(Exchange exchange) throws NmrRuntimeException {
+        try {
+            if (exchange != null) {
+                for (String prop : exchange.getProperties().keySet()) {
+                    exchange.setProperty(prop, convert(exchange.getProperty(prop)));
+                }
+                ensureReReadable(exchange.getIn(false));
+                ensureReReadable(exchange.getOut(false));
+                ensureReReadable(exchange.getFault(false));
+            }
+        } catch (IOException e) {
+            throw new NmrRuntimeException(e);
+        } catch (TransformerException e) {
+            throw new NmrRuntimeException(e);
+        }
+    }
+
+    public static void ensureReReadable(Message message) throws NmrRuntimeException {
+        try {
+            if (message != null) {
+                message.setBody(convert(message.getBody()));
+                for (String hdr : message.getHeaders().keySet()) {
+                    message.setHeader(hdr, convert(message.getHeader(hdr)));
+                }
+                for (String id : message.getAttachments().keySet()) {
+                    message.addAttachment(id, convert(message.getAttachment(id)));
+                }
+            }
+        } catch (IOException e) {
+            throw new NmrRuntimeException(e);
+        } catch (TransformerException e) {
+            throw new NmrRuntimeException(e);
+        }
+    }
+
+    private static Object convert(Object object) throws IOException, TransformerException {
+        if (object instanceof InputStream) {
+            object = convertInputStream((InputStream) object);
+        } else if (object instanceof Source) {
+            object = convertSource((Source) object);
+        }
+        return object;
+    }
+
+    private static InputStream convertInputStream(InputStream is) throws IOException {
+        if (!(is instanceof ByteArrayInputStream)) {
+            if (!(is instanceof BufferedInputStream)) {
+                is = new BufferedInputStream(is);
+            }
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            byte[] buffer = new byte[8192];
+            int len;
+            while ((len = is.read(buffer)) > 0) {
+                baos.write(buffer, 0, len);
+            }
+            is.close();
+            is = new ByteArrayInputStream(baos.toByteArray());
+        }
+        return is;
+    }
+
+    private static Source convertSource(Source src) throws TransformerException {
+        if (!(src instanceof DOMSource)) {
+            DOMResult result = new DOMResult();
+            Transformer transformer = TransformerFactory.newInstance().newTransformer();
+            transformer.transform(src, result);
+            return new DOMSource(result.getNode());
+        }
+        return src;
+    }
+}

Added: servicemix/smx4/nmr/trunk/nmr/core/src/test/java/org/apache/servicemix/nmr/core/util/ExchangeUtilsTest.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/nmr/core/src/test/java/org/apache/servicemix/nmr/core/util/ExchangeUtilsTest.java?rev=706613&view=auto
==============================================================================
--- servicemix/smx4/nmr/trunk/nmr/core/src/test/java/org/apache/servicemix/nmr/core/util/ExchangeUtilsTest.java (added)
+++ servicemix/smx4/nmr/trunk/nmr/core/src/test/java/org/apache/servicemix/nmr/core/util/ExchangeUtilsTest.java Tue Oct 21 05:49:36 2008
@@ -0,0 +1,78 @@
+/*
+ * 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.nmr.core.util;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+
+import javax.xml.namespace.QName;
+import javax.xml.transform.dom.DOMSource;
+
+import junit.framework.TestCase;
+import org.apache.servicemix.nmr.api.Exchange;
+import org.apache.servicemix.nmr.api.Pattern;
+import org.apache.servicemix.nmr.api.Status;
+import org.apache.servicemix.nmr.api.Message;
+import org.apache.servicemix.nmr.core.ExchangeImpl;
+import org.apache.camel.converter.jaxp.StringSource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class ExchangeUtilsTest extends TestCase {
+
+    private static final Log LOG = LogFactory.getLog(ExchangeUtilsTest.class);
+
+    public void testReReadable() throws Exception {
+        Exchange e = new ExchangeImpl(Pattern.InOnly);
+        Message msg = e.getIn();
+        msg.addAttachment("id", new BufferedInputStream(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 })));
+        msg.setBody(new StringSource("<hello/>"));
+
+        e.ensureReReadable();
+
+        assertNotNull(msg.getBody());
+        assertTrue(msg.getBody() instanceof DOMSource);
+        assertNotNull(msg.getAttachment("id"));
+        assertTrue(msg.getAttachment("id") instanceof ByteArrayInputStream);
+    }
+
+    public void testDisplay() throws Exception {
+        Exchange e = new ExchangeImpl(Pattern.InOnly);
+        e.setOperation(new QName("op"));
+        e.setProperty("key", "value");
+        e.setStatus(Status.Done);
+        Message msg = e.getIn();
+        msg.setHeader("header", "value");
+        msg.addAttachment("id", new BufferedInputStream(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 })));
+        msg.setBody(new StringSource("<hello/>"));
+
+        String str = e.display(false);
+        LOG.info(str);
+        assertNotNull(msg.getBody());
+        assertTrue(msg.getBody() instanceof StringSource);
+        assertNotNull(msg.getAttachment("id"));
+        assertTrue(msg.getAttachment("id") instanceof BufferedInputStream);
+
+        str = e.display(true);
+        LOG.info(str);
+        assertNotNull(msg.getBody());
+        assertTrue(msg.getBody() instanceof DOMSource);
+        assertNotNull(msg.getAttachment("id"));
+        assertTrue(msg.getAttachment("id") instanceof ByteArrayInputStream);
+    }
+
+}