This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/main by this push:
     new 5b32eaf34f CXF-8669: Multipart annotation not working 3.4.6 onwards 
(#1078)
5b32eaf34f is described below

commit 5b32eaf34f5a233d0ad8c69d82b30b4ba10eecb6
Author: Andriy Redko <drr...@gmail.com>
AuthorDate: Sat Mar 4 11:49:19 2023 -0500

    CXF-8669: Multipart annotation not working 3.4.6 onwards (#1078)
---
 .../cxf/attachment/AttachmentDataSource.java       |   6 +-
 .../cxf/attachment/AttachmentDeserializer.java     |   2 +-
 .../org/apache/cxf/attachment/AttachmentUtil.java  |  23 ++++-
 .../java/org/apache/cxf/message/MessageUtils.java  |  12 +++
 .../cxf/attachment/AttachmentDeserializerTest.java | 101 +++++++++++++++++++++
 .../apache/cxf/jaxrs/ext/MessageContextImpl.java   |   3 +-
 .../security/wss4j/AttachmentCallbackHandler.java  |  13 ++-
 7 files changed, 151 insertions(+), 9 deletions(-)

diff --git 
a/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java 
b/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java
index 8fc76cdb06..2e013144e7 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java
@@ -31,7 +31,6 @@ import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.message.Message;
 
 public class AttachmentDataSource implements DataSource {
-
     private String ct;
     private CachedOutputStream cache;
     private InputStream ins;
@@ -77,9 +76,10 @@ public class AttachmentDataSource implements DataSource {
 
     public String getContentType() {
         if (StringUtils.isEmpty(ct)) {
-            ct = "application/octet-stream";
+            return "application/octet-stream";
+        } else {
+            return ct;
         }
-        return ct;
     }
 
     public InputStream getInputStream() {
diff --git 
a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java 
b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
index a6c18572a4..9782c8be11 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
@@ -325,7 +325,7 @@ public class AttachmentDeserializer {
                                       this);
         createCount++;
 
-        return AttachmentUtil.createAttachment(partStream, headers);
+        return AttachmentUtil.createAttachment(partStream, headers, message);
     }
 
     public boolean isLazyLoading() {
diff --git a/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java 
b/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
index e585d26ca1..a8859cb7f0 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
@@ -65,6 +65,10 @@ import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
 
 public final class AttachmentUtil {
+    // The default values for {@link AttachmentDataSource} content type in 
case when
+    // "Content-Type" header is not present.
+    public static final String ATTACHMENT_CONTENT_TYPE = 
"org.apache.cxf.attachment.content-type"; 
+
     // The xop:include "href" attribute 
(https://www.w3.org/TR/xop10/#xop_href) may include 
     // arbitrary URL which we should never follow (unless explicitly allowed).
     public static final String ATTACHMENT_XOP_FOLLOW_URLS_PROPERTY = 
"org.apache.cxf.attachment.xop.follow.urls";
@@ -393,14 +397,27 @@ public final class AttachmentUtil {
     static String getHeader(Map<String, List<String>> headers, String h, 
String delim) {
         return getHeaderValue(headers.get(h), delim);
     }
-    public static Attachment createAttachment(InputStream stream, Map<String, 
List<String>> headers)
-        throws IOException {
+
+    /**
+     * @deprecated use createAttachment(InputStream stream, Map<String, 
List<String>> headers, Message message)
+     */
+    public static Attachment createAttachment(InputStream stream, Map<String, 
List<String>> headers) 
+            throws IOException {
+        return createAttachment(stream, headers, null /* no Message */);
+    }
+
+    public static Attachment createAttachment(InputStream stream, Map<String, 
List<String>> headers, Message message)
+            throws IOException {
 
         String id = cleanContentId(getHeader(headers, "Content-ID"));
 
         AttachmentImpl att = new AttachmentImpl(id);
 
-        final String ct = getHeader(headers, "Content-Type");
+        String ct = getHeader(headers, "Content-Type");
+        if (StringUtils.isEmpty(ct)) {
+            ct = MessageUtils.getContextualString(message, 
ATTACHMENT_CONTENT_TYPE, "application/octet-stream");
+        }
+
         String cd = getHeader(headers, "Content-Disposition");
         String fileName = getContentDispositionFileName(cd);
 
diff --git a/core/src/main/java/org/apache/cxf/message/MessageUtils.java 
b/core/src/main/java/org/apache/cxf/message/MessageUtils.java
index 50d5fee2c6..b00cfbeedf 100644
--- a/core/src/main/java/org/apache/cxf/message/MessageUtils.java
+++ b/core/src/main/java/org/apache/cxf/message/MessageUtils.java
@@ -211,6 +211,18 @@ public final class MessageUtils {
         return defaultValue;
     }
 
+    public static String getContextualString(Message m, String key, String 
defaultValue) {
+        if (m != null) {
+            final Object o = m.getContextualProperty(key);
+            if (o instanceof String) {
+                return (String) o;
+            } else if (o != null) {
+                return o.toString();
+            }
+        }
+        return defaultValue;
+    }
+
     public static Object getContextualProperty(Message m, String 
propPreferred, String propDefault) {
         Object prop = null;
         if (m != null) {
diff --git 
a/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java 
b/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
index d3854ff4ea..69008ea0e0 100644
--- 
a/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
+++ 
b/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
@@ -786,6 +786,107 @@ public class AttachmentDeserializerTest {
         assertEquals("passwd", dataSource.getName());
     }
 
+    @Test
+    public void testDefaultContentTypeIfNotSet() throws Exception {
+        StringBuilder sb = new StringBuilder(1000);
+
+        sb.append("SomeHeader: foo\n")
+            .append("------=_Part_34950_1098328613.1263781527359\n")
+            .append("Content-Type: text/xml; charset=UTF-8\n")
+            .append("Content-Transfer-Encoding: binary\n")
+            .append("Content-Id: 
<318731183421.1263781527359.IBM.WEBSERVICES@auhpap02>\n")
+            .append('\n')
+            .append("<envelope/>\n");
+        
+        sb.append("------=_Part_34950_1098328613.1263781527359\n")
+            .append("Content-Transfer-Encoding: binary\n")
+            .append("Content-Id: <b86a5f2d-e7af-4e5e-b71a-9f6f2307cab0>\n")
+            .append('\n')
+            .append("<message>\n")
+            .append("------=_Part_34950_1098328613.1263781527359--\n");
+            
+        msg = new MessageImpl();
+        msg.setContent(InputStream.class, new 
ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8)));
+        msg.put(Message.CONTENT_TYPE, "multipart/related");
+
+        AttachmentDeserializer ad = new AttachmentDeserializer(msg);
+        ad.initializeAttachments();
+
+        // Force it to load the attachments
+        assertEquals(1, msg.getAttachments().size());
+        Attachment attachment = msg.getAttachments().iterator().next();
+        AttachmentDataSource dataSource = 
(AttachmentDataSource)attachment.getDataHandler().getDataSource();
+        assertEquals("application/octet-stream", dataSource.getContentType());
+    }
+
+    @Test
+    public void testContentTypeIfNotSet() throws Exception {
+        StringBuilder sb = new StringBuilder(1000);
+
+        sb.append("SomeHeader: foo\n")
+            .append("------=_Part_34950_1098328613.1263781527359\n")
+            .append("Content-Type: text/xml; charset=UTF-8\n")
+            .append("Content-Transfer-Encoding: binary\n")
+            .append("Content-Id: 
<318731183421.1263781527359.IBM.WEBSERVICES@auhpap02>\n")
+            .append('\n')
+            .append("<envelope/>\n");
+        
+        sb.append("------=_Part_34950_1098328613.1263781527359\n")
+            .append("Content-Transfer-Encoding: binary\n")
+            .append("Content-Id: <b86a5f2d-e7af-4e5e-b71a-9f6f2307cab0>\n")
+            .append('\n')
+            .append("<message>\n")
+            .append("------=_Part_34950_1098328613.1263781527359--\n");
+            
+        msg = new MessageImpl();
+        msg.setContent(InputStream.class, new 
ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8)));
+        msg.put(Message.CONTENT_TYPE, "multipart/related");
+        msg.put(AttachmentUtil.ATTACHMENT_CONTENT_TYPE, "text/plain");
+
+        AttachmentDeserializer ad = new AttachmentDeserializer(msg);
+        ad.initializeAttachments();
+
+        // Force it to load the attachments
+        assertEquals(1, msg.getAttachments().size());
+        Attachment attachment = msg.getAttachments().iterator().next();
+        AttachmentDataSource dataSource = 
(AttachmentDataSource)attachment.getDataHandler().getDataSource();
+        assertEquals("text/plain", dataSource.getContentType());
+    }
+
+    @Test
+    public void testContentType() throws Exception {
+        StringBuilder sb = new StringBuilder(1000);
+
+        sb.append("SomeHeader: foo\n")
+            .append("------=_Part_34950_1098328613.1263781527359\n")
+            .append("Content-Type: text/xml; charset=UTF-8\n")
+            .append("Content-Transfer-Encoding: binary\n")
+            .append("Content-Id: 
<318731183421.1263781527359.IBM.WEBSERVICES@auhpap02>\n")
+            .append('\n')
+            .append("<envelope/>\n");
+        
+        sb.append("------=_Part_34950_1098328613.1263781527359\n")
+            .append("Content-Transfer-Encoding: binary\n")
+            .append("Content-Id: <b86a5f2d-e7af-4e5e-b71a-9f6f2307cab0>\n")
+            .append("Content-Type: text/xml; charset=UTF-8\n")
+            .append('\n')
+            .append("<message>\n")
+            .append("------=_Part_34950_1098328613.1263781527359--\n");
+            
+        msg = new MessageImpl();
+        msg.setContent(InputStream.class, new 
ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8)));
+        msg.put(Message.CONTENT_TYPE, "multipart/related");
+
+        AttachmentDeserializer ad = new AttachmentDeserializer(msg);
+        ad.initializeAttachments();
+
+        // Force it to load the attachments
+        assertEquals(1, msg.getAttachments().size());
+        Attachment attachment = msg.getAttachments().iterator().next();
+        AttachmentDataSource dataSource = 
(AttachmentDataSource)attachment.getDataHandler().getDataSource();
+        assertEquals("text/xml; charset=UTF-8", dataSource.getContentType());
+    }
+
     @Test
     public void testCXF8706() {
         final DataSource ds = AttachmentUtil
diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java
 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java
index 829b3190b6..ad74ad85ca 100644
--- 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java
+++ 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java
@@ -289,7 +289,8 @@ public class MessageContextImpl implements MessageContext {
 
             Attachment first = new Attachment(AttachmentUtil.createAttachment(
                                      inMessage.getContent(InputStream.class),
-                                     headers),
+                                     headers,
+                                     inMessage),
                                      new ProvidersImpl(inMessage));
             newAttachments.add(first);
         } catch (IOException ex) {
diff --git 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AttachmentCallbackHandler.java
 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AttachmentCallbackHandler.java
index b72cd555f9..ee7adedf98 100644
--- 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AttachmentCallbackHandler.java
+++ 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AttachmentCallbackHandler.java
@@ -34,8 +34,11 @@ import 
javax.security.auth.callback.UnsupportedCallbackException;
 
 import jakarta.activation.DataHandler;
 import org.apache.cxf.attachment.AttachmentDataSource;
+import org.apache.cxf.attachment.AttachmentUtil;
+import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.message.Attachment;
 import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
 import org.apache.wss4j.common.ext.AttachmentRemovalCallback;
 import org.apache.wss4j.common.ext.AttachmentRequestCallback;
 import org.apache.wss4j.common.ext.AttachmentResultCallback;
@@ -46,16 +49,19 @@ import org.apache.wss4j.common.ext.AttachmentResultCallback;
 public class AttachmentCallbackHandler implements CallbackHandler {
 
     private final Collection<org.apache.cxf.message.Attachment> attachments;
+    private final String defaultMimeType;
 
     public AttachmentCallbackHandler(Message message) {
         if (message.getAttachments() == null) {
             message.setAttachments(new ArrayList<Attachment>());
         }
         attachments = message.getAttachments();
+        defaultMimeType = MessageUtils.getContextualString(message, 
AttachmentUtil.ATTACHMENT_CONTENT_TYPE, "application/octet-stream");
     }
 
     public 
AttachmentCallbackHandler(Collection<org.apache.cxf.message.Attachment> 
attachments) {
         this.attachments = attachments;
+        this.defaultMimeType = null;
     }
 
     @Override
@@ -76,12 +82,17 @@ public class AttachmentCallbackHandler implements 
CallbackHandler {
             } else if (callback instanceof AttachmentResultCallback) {
                 AttachmentResultCallback attachmentResultCallback = 
(AttachmentResultCallback) callback;
 
+                String mimeType = 
attachmentResultCallback.getAttachment().getMimeType();
+                if (StringUtils.isEmpty(mimeType)) {
+                    mimeType = defaultMimeType;
+                }
+
                 org.apache.cxf.attachment.AttachmentImpl securedAttachment =
                     new org.apache.cxf.attachment.AttachmentImpl(
                         attachmentResultCallback.getAttachmentId(),
                         new DataHandler(
                             new AttachmentDataSource(
-                                
attachmentResultCallback.getAttachment().getMimeType(),
+                                mimeType,
                                 
attachmentResultCallback.getAttachment().getSourceStream())
                         )
                     );

Reply via email to