cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ff...@apache.org
Subject svn commit: r687703 - in /cxf/branches/2.0.x-fixes: rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/ rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/ systests/src/test/java/org/apache/cxf/systest/mtom/ testutils/src/main/resou...
Date Thu, 21 Aug 2008 10:50:17 GMT
Author: ffang
Date: Thu Aug 21 03:50:16 2008
New Revision: 687703

URL: http://svn.apache.org/viewvc?rev=687703&view=rev
Log:
[CXF-1760] jms transport don't support MTOM

Added:
    cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopWithJMSTest.java
  (with props)
    cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ServerWithJMS.java
  (with props)
    cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/TestMtomJMSImpl.java
  (with props)
Modified:
    cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
    cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
    cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSTransportBase.java
    cxf/branches/2.0.x-fixes/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSDestinationTest.java
    cxf/branches/2.0.x-fixes/testutils/src/main/resources/wsdl/mtom_xop.wsdl

Modified: cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java?rev=687703&r1=687702&r2=687703&view=diff
==============================================================================
--- cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
(original)
+++ cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
Thu Aug 21 03:50:16 2008
@@ -316,6 +316,9 @@
             }
             
             base.setMessageProperties(headers, jmsMessage);
+            
+            //ensure that the contentType is set to the out jms message header
+            base.setContentToProtocalHeader(outMessage);
             Map<String, List<String>> protHeaders = 
                 CastUtils.cast((Map<?, ?>)outMessage.get(Message.PROTOCOL_HEADERS));
             base.addProtocolHeaders(jmsMessage, protHeaders);
@@ -389,6 +392,7 @@
     }
 
     
+    
     /**
      * Represented decoupled response endpoint.
      */

Modified: cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java?rev=687703&r1=687702&r2=687703&view=diff
==============================================================================
--- cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
(original)
+++ cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
Thu Aug 21 03:50:16 2008
@@ -463,6 +463,8 @@
 
                     setReplyCorrelationID(request, reply);
                     base.setMessageProperties(headers, reply);
+                    //ensure that the contentType is set to the out jms message header
+                    base.setContentToProtocalHeader(outMessage);
                     Map<String, List<String>> protHeaders = 
                         CastUtils.cast((Map<?, ?>)outMessage.get(Message.PROTOCOL_HEADERS));
                     base.addProtocolHeaders(reply, protHeaders);

Modified: cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSTransportBase.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSTransportBase.java?rev=687703&r1=687702&r2=687703&view=diff
==============================================================================
--- cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSTransportBase.java
(original)
+++ cxf/branches/2.0.x-fixes/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSTransportBase.java
Thu Aug 21 03:50:16 2008
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.transport.jms;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -34,6 +35,7 @@
 import javax.jms.TextMessage;
 
 import org.apache.cxf.Bus;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.service.model.EndpointInfo;
 
 
@@ -161,6 +163,10 @@
             props.add(prop);
             
             protHeaders.put(name, Collections.singletonList(val));
+            if (name.equals(org.apache.cxf.message.Message.CONTENT_TYPE)
+                    && val != null) {
+                inMessage.put(org.apache.cxf.message.Message.CONTENT_TYPE, val);
+            }
         }
         inMessage.put(org.apache.cxf.message.Message.PROTOCOL_HEADERS, protHeaders);
         return headers;
@@ -235,4 +241,29 @@
         return JMSConstants.JMS_QUEUE.equals(
             transport.getJMSAddress().getDestinationStyle().value());
     }
+    
+    protected void setContentToProtocalHeader(org.apache.cxf.message.Message message) {
+        String contentType = (String)message.get(org.apache.cxf.message.Message.CONTENT_TYPE);
+        
+        Map<String, List<String>> headers = getSetProtocolHeaders(message);
+        if (headers.get(org.apache.cxf.message.Message.CONTENT_TYPE) == null) {
+            List<String> ct = new ArrayList<String>();
+            ct.add(contentType);
+            headers.put(org.apache.cxf.message.Message.CONTENT_TYPE, ct);
+        }  else {
+            List<String> ct = headers.get(org.apache.cxf.message.Message.CONTENT_TYPE);
+            ct.add(contentType);
+        }
+    }
+    
+    protected Map<String, List<String>> getSetProtocolHeaders(
+            org.apache.cxf.message.Message message) {
+        Map<String, List<String>> headers =
+            CastUtils.cast((Map<?, ?>)message.get(org.apache.cxf.message.Message.PROTOCOL_HEADERS));
       
+        if (null == headers) {
+            headers = new HashMap<String, List<String>>();
+            message.put(org.apache.cxf.message.Message.PROTOCOL_HEADERS, headers);
+        }
+        return headers;
+    }
 }

Modified: cxf/branches/2.0.x-fixes/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSDestinationTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSDestinationTest.java?rev=687703&r1=687702&r2=687703&view=diff
==============================================================================
--- cxf/branches/2.0.x-fixes/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSDestinationTest.java
(original)
+++ cxf/branches/2.0.x-fixes/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSDestinationTest.java
Thu Aug 21 03:50:16 2008
@@ -379,7 +379,12 @@
         
         JMSMessageHeadersType inHeader =
             (JMSMessageHeadersType)inMessage.get(JMSConstants.JMS_CLIENT_RESPONSE_HEADERS);
-        assertTrue("property has been excluded", inHeader.getProperty().isEmpty());
+        
+        
+        assertTrue("property has been excluded, only CONTENT_TYPE should be here", 
+                inHeader.getProperty().size() == 1);
+        assertTrue("property has been excluded, only CONTENT_TYPE should be here", 
+                inHeader.getProperty().get(0).getName().equals(Message.CONTENT_TYPE));
 
         // wait for a while for the jms session recycling
         Thread.sleep(1000);

Added: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopWithJMSTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopWithJMSTest.java?rev=687703&view=auto
==============================================================================
--- cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopWithJMSTest.java
(added)
+++ cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopWithJMSTest.java
Thu Aug 21 03:50:16 2008
@@ -0,0 +1,138 @@
+/**
+ * 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.cxf.systest.mtom;
+
+import java.io.InputStream;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.activation.DataHandler;
+import javax.mail.util.ByteArrayDataSource;
+import javax.xml.namespace.QName;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Holder;
+import javax.xml.ws.soap.SOAPBinding;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.endpoint.ClientImpl;
+import org.apache.cxf.jaxws.JaxWsClientProxy;
+import org.apache.cxf.jaxws.binding.soap.SOAPBindingImpl;
+import org.apache.cxf.jaxws.support.JaxWsEndpointImpl;
+import org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean;
+import org.apache.cxf.mime.TestMtom;
+import org.apache.cxf.service.Service;
+import org.apache.cxf.service.factory.ReflectionServiceFactoryBean;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.systest.jms.EmbeddedJMSBrokerLauncher;
+import org.apache.cxf.test.TestUtilities;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ClientMtomXopWithJMSTest extends AbstractBusClientServerTestBase {
+
+    public static final QName MTOM_PORT = new QName("http://cxf.apache.org/mime", "TestMtomJMSPort");
+    public static final QName MTOM_SERVICE = new QName("http://cxf.apache.org/mime", "TestMtomJMSService");
+
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        Map<String, String> props = new HashMap<String, String>();          
     
+        if (System.getProperty("activemq.store.dir") != null) {
+            props.put("activemq.store.dir", System.getProperty("activemq.store.dir"));
+        }
+        props.put("java.util.logging.config.file", 
+                  System.getProperty("java.util.logging.config.file"));
+        
+        assertTrue("server did not launch correctly", 
+                   launchServer(EmbeddedJMSBrokerLauncher.class, props, null));
+        TestUtilities.setKeepAliveSystemProperty(false);
+        assertTrue("server did not launch correctly", launchServer(ServerWithJMS.class, true));
+    }
+    
+    @AfterClass
+    public static void cleanup() {
+        TestUtilities.recoverKeepAliveSystemProperty();
+    }
+
+    
+    @Test
+    public void testMtomXop() throws Exception {
+        TestMtom mtomPort = createPort(MTOM_SERVICE, MTOM_PORT, TestMtom.class, true);
+        try {
+            InputStream pre = this.getClass().getResourceAsStream("/wsdl/mtom_xop.wsdl");
+            int fileSize = 0;
+            for (int i = pre.read(); i != -1; i = pre.read()) {
+                fileSize++;
+            }
+            Holder<DataHandler> param = new Holder<DataHandler>();
+            
+            int count = 50;
+            byte[] data = new byte[fileSize *  count];
+            for (int x = 0; x < count; x++) {
+                this.getClass().getResourceAsStream("/wsdl/mtom_xop.wsdl").read(data, 
+                                                                                fileSize
* x,
+                                                                                fileSize);
+            }
+            
+            param.value = new DataHandler(new ByteArrayDataSource(data, "application/octet-stream"));
+            Holder<String> name = new Holder<String>("call detail");
+            mtomPort.testXop(name, param);
+            assertEquals("name unchanged", "return detail + call detail", name.value);
+            assertNotNull(param.value);
+            param.value.getInputStream().close();
+            
+        } catch (UndeclaredThrowableException ex) {
+            throw (Exception) ex.getCause();
+        }
+    }
+
+    private static <T> T createPort(QName serviceName, 
+                                    QName portName, 
+                                    Class<T> serviceEndpointInterface,
+                                    boolean enableMTOM)
+        throws Exception {
+        Bus bus = BusFactory.getDefaultBus();
+        ReflectionServiceFactoryBean serviceFactory = new JaxWsServiceFactoryBean();
+        serviceFactory.setBus(bus);
+        serviceFactory.setServiceName(serviceName);
+        serviceFactory.setServiceClass(serviceEndpointInterface);
+        serviceFactory.setWsdlURL(ClientMtomXopTest.class.getResource("/wsdl/mtom_xop.wsdl"));
+        Service service = serviceFactory.create();
+        EndpointInfo ei = service.getEndpointInfo(portName);
+        JaxWsEndpointImpl jaxwsEndpoint = new JaxWsEndpointImpl(bus, service, ei);
+        SOAPBinding jaxWsSoapBinding = new SOAPBindingImpl(ei.getBinding());
+        jaxWsSoapBinding.setMTOMEnabled(enableMTOM);
+        
+        jaxwsEndpoint.getBinding().getInInterceptors().add(new TestMultipartMessageInterceptor());
+        jaxwsEndpoint.getBinding().getOutInterceptors().add(new TestAttachmentOutInterceptor());
+        
+        Client client = new ClientImpl(bus, jaxwsEndpoint);
+        InvocationHandler ih = new JaxWsClientProxy(client, jaxwsEndpoint.getJaxwsBinding());
+        Object obj = Proxy.newProxyInstance(serviceEndpointInterface.getClassLoader(), new
Class[] {
+            serviceEndpointInterface, BindingProvider.class }, ih);
+        return serviceEndpointInterface.cast(obj);
+    }
+}

Propchange: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopWithJMSTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopWithJMSTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ServerWithJMS.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ServerWithJMS.java?rev=687703&view=auto
==============================================================================
--- cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ServerWithJMS.java
(added)
+++ cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ServerWithJMS.java
Thu Aug 21 03:50:16 2008
@@ -0,0 +1,61 @@
+/**
+ * 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.cxf.systest.mtom;
+
+import javax.xml.ws.soap.SOAPBinding;
+
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.interceptor.LoggingInInterceptor;
+import org.apache.cxf.interceptor.LoggingOutInterceptor;
+import org.apache.cxf.jaxws.EndpointImpl;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
+public class ServerWithJMS extends AbstractBusTestServerBase {
+
+    protected void run() {
+        Object implementor = new TestMtomJMSImpl();
+        String address = "http://not.required.for.jms";
+        try {
+            EndpointImpl jaxep = (EndpointImpl) javax.xml.ws.Endpoint.publish(address, implementor);
+            Endpoint ep = jaxep.getServer().getEndpoint();
+            ep.getInInterceptors().add(new TestMultipartMessageInterceptor());
+            ep.getOutInterceptors().add(new TestAttachmentOutInterceptor());
+            ep.getInInterceptors().add(new LoggingInInterceptor());
+            ep.getOutInterceptors().add(new LoggingOutInterceptor());
+            SOAPBinding jaxWsSoapBinding = (SOAPBinding) jaxep.getBinding();
+            jaxWsSoapBinding.setMTOMEnabled(true);
+
+        } catch (Exception e) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    public static void main(String args[]) {
+        try {
+            Server s = new Server();
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally {
+            System.out.println("done!");
+        }
+    }
+}

Propchange: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ServerWithJMS.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/ServerWithJMS.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/TestMtomJMSImpl.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/TestMtomJMSImpl.java?rev=687703&view=auto
==============================================================================
--- cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/TestMtomJMSImpl.java
(added)
+++ cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/TestMtomJMSImpl.java
Thu Aug 21 03:50:16 2008
@@ -0,0 +1,41 @@
+/**
+ * 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.cxf.systest.mtom;
+
+import javax.activation.DataHandler;
+import javax.jws.WebService;
+import javax.xml.ws.Holder;
+
+import org.apache.cxf.mime.TestMtom;
+
+@WebService(serviceName = "TestMtomJMSService", 
+        portName = "TestMtomJMSPort", 
+        targetNamespace = "http://cxf.apache.org/mime", 
+        endpointInterface = "org.apache.cxf.mime.TestMtom",
+        wsdlLocation = "testutils/mtom_xop.wsdl")
+        
+public class TestMtomJMSImpl implements TestMtom {
+
+    public void testXop(Holder<String> name, Holder<DataHandler> attachinfo)
{
+        // TODO Auto-generated method stub
+        name.value = "return detail + " + name.value;
+    }
+
+}

Propchange: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/TestMtomJMSImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/branches/2.0.x-fixes/systests/src/test/java/org/apache/cxf/systest/mtom/TestMtomJMSImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/branches/2.0.x-fixes/testutils/src/main/resources/wsdl/mtom_xop.wsdl
URL: http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/testutils/src/main/resources/wsdl/mtom_xop.wsdl?rev=687703&r1=687702&r2=687703&view=diff
==============================================================================
--- cxf/branches/2.0.x-fixes/testutils/src/main/resources/wsdl/mtom_xop.wsdl (original)
+++ cxf/branches/2.0.x-fixes/testutils/src/main/resources/wsdl/mtom_xop.wsdl Thu Aug 21 03:50:16
2008
@@ -22,6 +22,7 @@
 <wsdl:definitions name="SOAPBuilders-mime-cr-test" xmlns:types="http://cxf.apache.org/mime/types"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
     xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://cxf.apache.org/mime"
+    xmlns:jms="http://cxf.apache.org/transports/jms"
     xmlns:xmime="http://www.w3.org/2005/05/xmlmime" targetNamespace="http://cxf.apache.org/mime">
 
     <wsdl:types>
@@ -79,4 +80,17 @@
         </wsdl:port>
     </wsdl:service>
 
+    <wsdl:service name="TestMtomJMSService">
+        <wsdl:port name="TestMtomJMSPort" binding="tns:TestMtomBinding">
+            <jms:address
+               destinationStyle="queue"
+               jndiConnectionFactoryName="ConnectionFactory"
+               jndiDestinationName="dynamicQueues/person.queue">
+               <jms:JMSNamingProperty name="java.naming.factory.initial" value="org.apache.activemq.jndi.ActiveMQInitialContextFactory"/>
+               <jms:JMSNamingProperty name="java.naming.provider.url" value="tcp://localhost:61500"/>
+          </jms:address>
+
+        </wsdl:port>
+    </wsdl:service>
+
 </wsdl:definitions>



Mime
View raw message