You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by or...@apache.org on 2026/01/30 08:24:56 UTC
(camel) 02/02: (chores): reduce cognitive complexity in MimeMultipartDataFormat
This is an automated email from the ASF dual-hosted git repository.
orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
commit b712b0f5bbcaead57df71dfe3a7458d3c526a605
Author: Otavio Rodolfo Piske <an...@gmail.com>
AuthorDate: Tue Jan 27 13:36:31 2026 +0000
(chores): reduce cognitive complexity in MimeMultipartDataFormat
---
.../mime/multipart/MimeMultipartDataFormat.java | 346 ++++++++++++---------
1 file changed, 206 insertions(+), 140 deletions(-)
diff --git a/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java b/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java
index f38a3d90600f..4f28bf0d0e5d 100644
--- a/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java
+++ b/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java
@@ -124,80 +124,109 @@ public class MimeMultipartDataFormat extends DefaultDataFormat {
@Override
public void marshal(Exchange exchange, Object graph, OutputStream stream)
throws NoTypeConversionAvailableException, MessagingException, IOException {
- if (multipartWithoutAttachment || headersInline || exchange.getIn(AttachmentMessage.class).hasAttachments()) {
- ContentType contentType = getContentType(exchange);
- // remove the Content-Type header. This will be wrong afterwards...
- exchange.getMessage().removeHeader(Exchange.CONTENT_TYPE);
- byte[] bodyContent = ExchangeHelper.convertToMandatoryType(exchange, byte[].class, graph);
- Session session = Session.getInstance(System.getProperties());
- MimeMessage mm = new MimeMessage(session);
- MimeMultipart mp = new MimeMultipart(multipartSubType);
- BodyPart part = new MimeBodyPart();
- writeBodyPart(bodyContent, part, contentType);
+ if (!shouldMarshalAsMultipart(exchange)) {
+ // keep the original data
+ InputStream is = ExchangeHelper.convertToMandatoryType(exchange, InputStream.class, graph);
+ IOHelper.copyAndCloseInput(is, stream);
+ return;
+ }
+
+ ContentType contentType = getContentType(exchange);
+ // remove the Content-Type header. This will be wrong afterwards...
+ exchange.getMessage().removeHeader(Exchange.CONTENT_TYPE);
+ byte[] bodyContent = ExchangeHelper.convertToMandatoryType(exchange, byte[].class, graph);
+ Session session = Session.getInstance(System.getProperties());
+ MimeMessage mm = new MimeMessage(session);
+ MimeMultipart mp = new MimeMultipart(multipartSubType);
+
+ BodyPart part = new MimeBodyPart();
+ writeBodyPart(bodyContent, part, contentType);
+ mp.addBodyPart(part);
+
+ addAttachmentsToMultipart(exchange, mp);
+
+ mm.setContent(mp);
+ copyInlineHeaders(exchange, mm);
+ mm.saveChanges();
+
+ List<String> headers = extractHeadersToMessage(exchange, mm);
+ mm.writeTo(stream, headers.toArray(new String[0]));
+ }
+
+ private boolean shouldMarshalAsMultipart(Exchange exchange) {
+ return multipartWithoutAttachment || headersInline || exchange.getIn(AttachmentMessage.class).hasAttachments();
+ }
+
+ private void addAttachmentsToMultipart(Exchange exchange, MimeMultipart mp)
+ throws MessagingException, UnsupportedEncodingException, ParseException {
+ if (!exchange.getIn(AttachmentMessage.class).hasAttachments()) {
+ return;
+ }
+ List<String> idsToRemove = new ArrayList<>();
+ for (Map.Entry<String, Attachment> entry : exchange.getIn(AttachmentMessage.class).getAttachmentObjects().entrySet()) {
+ String attachmentFilename = entry.getKey();
+ Attachment attachment = entry.getValue();
+ BodyPart part = createAttachmentBodyPart(attachmentFilename, attachment);
mp.addBodyPart(part);
- if (exchange.getIn(AttachmentMessage.class).hasAttachments()) {
- List<String> idsToRemove = new ArrayList<>();
- for (Map.Entry<String, Attachment> entry : exchange.getIn(AttachmentMessage.class).getAttachmentObjects()
- .entrySet()) {
- String attachmentFilename = entry.getKey();
- Attachment attachment = entry.getValue();
- part = new MimeBodyPart();
- part.setDataHandler(attachment.getDataHandler());
- part.setFileName(MimeUtility.encodeText(attachmentFilename, "UTF-8", null));
- String ct = attachment.getDataHandler().getContentType();
- contentType = new ContentType(ct);
- part.setHeader(CONTENT_TYPE, ct);
- if (!contentType.match("text/*") && binaryContent) {
- part.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
- } else {
- setContentTransferEncoding(part, contentType);
- }
- // Set headers to the attachment
- for (String headerName : attachment.getHeaderNames()) {
- List<String> values = attachment.getHeaderAsList(headerName);
- for (String value : values) {
- part.setHeader(headerName, value);
- }
- }
- mp.addBodyPart(part);
- idsToRemove.add(attachmentFilename);
- }
- for (String id : idsToRemove) {
- exchange.getMessage(AttachmentMessage.class).removeAttachment(id);
- }
+ idsToRemove.add(attachmentFilename);
+ }
+ for (String id : idsToRemove) {
+ exchange.getMessage(AttachmentMessage.class).removeAttachment(id);
+ }
+ }
+
+ private BodyPart createAttachmentBodyPart(String attachmentFilename, Attachment attachment)
+ throws MessagingException, UnsupportedEncodingException, ParseException {
+ BodyPart part = new MimeBodyPart();
+ part.setDataHandler(attachment.getDataHandler());
+ part.setFileName(MimeUtility.encodeText(attachmentFilename, "UTF-8", null));
+ String ct = attachment.getDataHandler().getContentType();
+ ContentType contentType = new ContentType(ct);
+ part.setHeader(CONTENT_TYPE, ct);
+ if (!contentType.match("text/*") && binaryContent) {
+ part.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
+ } else {
+ setContentTransferEncoding(part, contentType);
+ }
+ // Set headers to the attachment
+ for (String headerName : attachment.getHeaderNames()) {
+ List<String> values = attachment.getHeaderAsList(headerName);
+ for (String value : values) {
+ part.setHeader(headerName, value);
}
- mm.setContent(mp);
- // copy headers if required and if the content can be converted into
- // a String
- if (headersInline && includeHeadersPattern != null) {
- for (Map.Entry<String, Object> entry : exchange.getIn().getHeaders().entrySet()) {
- if (includeHeadersPattern.matcher(entry.getKey()).matches()) {
- String headerStr = ExchangeHelper.convertToType(exchange, String.class, entry.getValue());
- if (headerStr != null) {
- mm.setHeader(entry.getKey(), headerStr);
- }
- }
+ }
+ return part;
+ }
+
+ private void copyInlineHeaders(Exchange exchange, MimeMessage mm)
+ throws MessagingException, NoTypeConversionAvailableException {
+ if (!headersInline || includeHeadersPattern == null) {
+ return;
+ }
+ for (Map.Entry<String, Object> entry : exchange.getIn().getHeaders().entrySet()) {
+ if (includeHeadersPattern.matcher(entry.getKey()).matches()) {
+ String headerStr = ExchangeHelper.convertToType(exchange, String.class, entry.getValue());
+ if (headerStr != null) {
+ mm.setHeader(entry.getKey(), headerStr);
}
}
- mm.saveChanges();
- Enumeration<?> hl = mm.getAllHeaders();
- List<String> headers = new ArrayList<>();
- if (!headersInline) {
- while (hl.hasMoreElements()) {
- Object ho = hl.nextElement();
- if (ho instanceof Header) {
- Header h = (Header) ho;
- exchange.getMessage().setHeader(h.getName(), h.getValue());
- headers.add(h.getName());
- }
- }
+ }
+ }
+
+ private List<String> extractHeadersToMessage(Exchange exchange, MimeMessage mm) throws MessagingException {
+ List<String> headers = new ArrayList<>();
+ if (headersInline) {
+ return headers;
+ }
+ Enumeration<?> hl = mm.getAllHeaders();
+ while (hl.hasMoreElements()) {
+ Object ho = hl.nextElement();
+ if (ho instanceof Header h) {
+ exchange.getMessage().setHeader(h.getName(), h.getValue());
+ headers.add(h.getName());
}
- mm.writeTo(stream, headers.toArray(new String[0]));
- } else {
- // keep the original data
- InputStream is = ExchangeHelper.convertToMandatoryType(exchange, InputStream.class, graph);
- IOHelper.copyAndCloseInput(is, stream);
}
+ return headers;
}
private ContentType getContentType(Exchange exchange) throws ParseException {
@@ -233,90 +262,127 @@ public class MimeMultipartDataFormat extends DefaultDataFormat {
@Override
public Object unmarshal(Exchange exchange, InputStream stream) throws IOException, MessagingException {
- MimeBodyPart mimeMessage;
- String contentType;
- Message camelMessage;
- Object content = null;
if (headersInline) {
- mimeMessage = new MimeBodyPart(stream);
- camelMessage = exchange.getMessage();
- MessageHelper.copyHeaders(exchange.getIn(), camelMessage, true);
- // write the MIME headers not generated by javamail as Camel headers
- Enumeration<?> headersEnum = mimeMessage.getNonMatchingHeaders(STANDARD_HEADERS);
- while (headersEnum.hasMoreElements()) {
- Object ho = headersEnum.nextElement();
- if (ho instanceof Header) {
- Header header = (Header) ho;
- camelMessage.setHeader(header.getName(), header.getValue());
- }
- }
- } else {
- // check if this a multipart at all. Otherwise do nothing
- contentType = exchange.getIn().getHeader(CONTENT_TYPE, String.class);
- if (contentType == null) {
- return stream;
- }
- try {
- ContentType ct = new ContentType(contentType);
- if (!ct.match("multipart/*")) {
- return stream;
- }
- } catch (ParseException e) {
- LOG.warn("Invalid Content-Type {} ignored", contentType);
- return stream;
+ return unmarshalWithInlineHeaders(exchange, stream);
+ }
+ return unmarshalWithExternalHeaders(exchange, stream);
+ }
+
+ private Object unmarshalWithInlineHeaders(Exchange exchange, InputStream stream)
+ throws IOException, MessagingException {
+ MimeBodyPart mimeMessage = new MimeBodyPart(stream);
+ Message camelMessage = exchange.getMessage();
+ MessageHelper.copyHeaders(exchange.getIn(), camelMessage, true);
+ copyNonStandardHeaders(mimeMessage, camelMessage);
+ return processContent(mimeMessage, camelMessage);
+ }
+
+ private void copyNonStandardHeaders(MimeBodyPart mimeMessage, Message camelMessage) throws MessagingException {
+ Enumeration<?> headersEnum = mimeMessage.getNonMatchingHeaders(STANDARD_HEADERS);
+ while (headersEnum.hasMoreElements()) {
+ Object ho = headersEnum.nextElement();
+ if (ho instanceof Header header) {
+ camelMessage.setHeader(header.getName(), header.getValue());
}
- camelMessage = exchange.getMessage();
- MessageHelper.copyHeaders(exchange.getIn(), camelMessage, true);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- IOHelper.copyAndCloseInput(stream, bos);
- InternetHeaders headers = new InternetHeaders();
- extractHeader(CONTENT_TYPE, camelMessage, headers);
- extractHeader(MIME_VERSION, camelMessage, headers);
- mimeMessage = new MimeBodyPart(headers, bos.toByteArray());
- bos.close();
}
- DataHandler dh;
+ }
+
+ private Object unmarshalWithExternalHeaders(Exchange exchange, InputStream stream)
+ throws IOException, MessagingException {
+ // check if this a multipart at all. Otherwise do nothing
+ String contentType = exchange.getIn().getHeader(CONTENT_TYPE, String.class);
+ if (contentType == null) {
+ return stream;
+ }
+ if (!isMultipartContentType(contentType)) {
+ return stream;
+ }
+
+ Message camelMessage = exchange.getMessage();
+ MessageHelper.copyHeaders(exchange.getIn(), camelMessage, true);
+ MimeBodyPart mimeMessage = createMimeBodyPart(stream, camelMessage);
+ return processContent(mimeMessage, camelMessage);
+ }
+
+ private boolean isMultipartContentType(String contentType) {
try {
- dh = mimeMessage.getDataHandler();
+ ContentType ct = new ContentType(contentType);
+ return ct.match("multipart/*");
+ } catch (ParseException e) {
+ LOG.warn("Invalid Content-Type {} ignored", contentType);
+ return false;
+ }
+ }
+
+ private MimeBodyPart createMimeBodyPart(InputStream stream, Message camelMessage)
+ throws IOException, MessagingException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ IOHelper.copyAndCloseInput(stream, bos);
+ InternetHeaders headers = new InternetHeaders();
+ extractHeader(CONTENT_TYPE, camelMessage, headers);
+ extractHeader(MIME_VERSION, camelMessage, headers);
+ MimeBodyPart mimeMessage = new MimeBodyPart(headers, bos.toByteArray());
+ bos.close();
+ return mimeMessage;
+ }
+
+ private Object processContent(MimeBodyPart mimeMessage, Message camelMessage)
+ throws MessagingException, IOException {
+ Object content = extractContent(mimeMessage);
+ content = extractAttachments(content, camelMessage);
+ setBodyFromContent(content, camelMessage);
+ return camelMessage;
+ }
+
+ private Object extractContent(MimeBodyPart mimeMessage) {
+ try {
+ DataHandler dh = mimeMessage.getDataHandler();
if (dh != null) {
- content = dh.getContent();
+ return dh.getContent();
}
- } catch (MessagingException e) {
+ } catch (MessagingException | IOException e) {
LOG.warn("cannot parse message, no unmarshalling done");
}
- if (content instanceof MimeMultipart) {
- MimeMultipart mp = (MimeMultipart) content;
- content = mp.getBodyPart(0);
- for (int i = 1; i < mp.getCount(); i++) {
- BodyPart bp = mp.getBodyPart(i);
- DefaultAttachment camelAttachment = new DefaultAttachment(bp.getDataHandler());
- @SuppressWarnings("unchecked")
- Enumeration<Header> headers = bp.getAllHeaders();
- while (headers.hasMoreElements()) {
- Header header = headers.nextElement();
- camelAttachment.addHeader(header.getName(), header.getValue());
- }
- camelMessage.getExchange().getMessage(AttachmentMessage.class).addAttachmentObject(getAttachmentKey(bp),
- camelAttachment);
- }
+ return null;
+ }
+
+ private Object extractAttachments(Object content, Message camelMessage)
+ throws MessagingException, UnsupportedEncodingException {
+ if (!(content instanceof MimeMultipart mp)) {
+ return content;
}
- if (content instanceof BodyPart) {
- BodyPart bp = (BodyPart) content;
- camelMessage.setBody(bp.getInputStream());
- contentType = bp.getContentType();
- if (contentType != null && !DEFAULT_CONTENT_TYPE.equals(contentType)) {
- camelMessage.setHeader(CONTENT_TYPE, contentType);
- ContentType ct = new ContentType(contentType);
- String charset = ct.getParameter("charset");
- if (charset != null) {
- camelMessage.setHeader(Exchange.CONTENT_ENCODING, MimeUtility.javaCharset(charset));
- }
+ Object bodyPart = mp.getBodyPart(0);
+ for (int i = 1; i < mp.getCount(); i++) {
+ BodyPart bp = mp.getBodyPart(i);
+ DefaultAttachment camelAttachment = new DefaultAttachment(bp.getDataHandler());
+ @SuppressWarnings("unchecked")
+ Enumeration<Header> headers = bp.getAllHeaders();
+ while (headers.hasMoreElements()) {
+ Header header = headers.nextElement();
+ camelAttachment.addHeader(header.getName(), header.getValue());
}
- } else {
- // If we find no body part, try to leave the message alone
+ camelMessage.getExchange().getMessage(AttachmentMessage.class).addAttachmentObject(getAttachmentKey(bp),
+ camelAttachment);
+ }
+ return bodyPart;
+ }
+
+ private void setBodyFromContent(Object content, Message camelMessage) throws MessagingException, IOException {
+ if (!(content instanceof BodyPart bp)) {
LOG.info("no MIME part found");
+ return;
+ }
+ camelMessage.setBody(bp.getInputStream());
+ String contentType = bp.getContentType();
+ if (contentType == null || DEFAULT_CONTENT_TYPE.equals(contentType)) {
+ return;
+ }
+ camelMessage.setHeader(CONTENT_TYPE, contentType);
+ ContentType ct = new ContentType(contentType);
+ String charset = ct.getParameter("charset");
+ if (charset != null) {
+ camelMessage.setHeader(Exchange.CONTENT_ENCODING, MimeUtility.javaCharset(charset));
}
- return camelMessage;
}
private void extractHeader(String headerMame, Message camelMessage, InternetHeaders headers) {