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

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit e389ab7d4aff45be34f804dbc084e3f2360e0366
Author: Benoit TELLIER <[email protected]>
AuthorDate: Thu Nov 28 15:53:56 2024 +0100

    [ENHANCEMENT] Extract MimeWalk in a separate class
---
 .../transport/matchers/AttachmentFileNameIs.java   | 164 +----------------
 .../james/transport/matchers/utils/MimeWalk.java   | 199 +++++++++++++++++++++
 .../matchers/AttachmentFileNameIsTest.java         |  24 ---
 .../transport/matchers/utils/MimeWalkTest.java     |  51 ++++++
 4 files changed, 255 insertions(+), 183 deletions(-)

diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/AttachmentFileNameIs.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/AttachmentFileNameIs.java
index d5703299fb..7423a2135e 100755
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/AttachmentFileNameIs.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/AttachmentFileNameIs.java
@@ -16,29 +16,22 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-
-
  
 package org.apache.james.transport.matchers;
 
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Locale;
-import java.util.StringTokenizer;
-import java.util.function.Predicate;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
 import jakarta.mail.MessagingException;
-import jakarta.mail.Multipart;
 import jakarta.mail.Part;
-import jakarta.mail.internet.MimeMessage;
 
 import org.apache.james.core.MailAddress;
 import org.apache.james.mime4j.codec.DecodeMonitor;
 import org.apache.james.mime4j.codec.DecoderUtil;
+import org.apache.james.transport.matchers.utils.MimeWalk;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.GenericMatcher;
 import org.slf4j.Logger;
@@ -63,131 +56,6 @@ import com.google.common.annotations.VisibleForTesting;
 public class AttachmentFileNameIs extends GenericMatcher {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(AttachmentFileNameIs.class);
 
-    record MimeWalkConfiguration(Mask[] masks, boolean isDebug, boolean 
unzipIsRequested) {
-        public static MimeWalkConfiguration DEFAULT = new 
MimeWalkConfiguration(null, false, false);
-
-        public static MimeWalkConfiguration parse(String condition) {
-            StringTokenizer st = new StringTokenizer(condition, ", ", false);
-            ArrayList<Mask> theMasks = new ArrayList<>(20);
-            boolean unzipIsRequested = false;
-            boolean isDebug = false;
-            while (st.hasMoreTokens()) {
-                String fileName = st.nextToken();
-
-                // check possible parameters at the beginning of the condition
-                if (theMasks.isEmpty() && 
fileName.equalsIgnoreCase(UNZIP_REQUEST_PARAMETER)) {
-                    unzipIsRequested = true;
-                    LOGGER.info("zip file analysis requested");
-                    continue;
-                }
-                if (theMasks.isEmpty() && 
fileName.equalsIgnoreCase(DEBUG_REQUEST_PARAMETER)) {
-                    isDebug = true;
-                    LOGGER.info("debug requested");
-                    continue;
-                }
-                Mask mask = new Mask();
-                if (fileName.startsWith("*")) {
-                    mask.suffixMatch = true;
-                    mask.matchString = fileName.substring(1);
-                } else {
-                    mask.suffixMatch = false;
-                    mask.matchString = fileName;
-                }
-                mask.matchString = cleanFileName(mask.matchString);
-                theMasks.add(mask);
-            }
-            return new MimeWalkConfiguration(theMasks.toArray(Mask[]::new), 
isDebug, unzipIsRequested);
-        }
-    }
-
-    public static class MimeWalk {
-        @FunctionalInterface
-        interface PartMatch {
-            boolean partMatch(Part part) throws MessagingException, 
IOException;
-        }
-
-        private final MimeWalkConfiguration configuration;
-        private final PartMatch partMatch;
-
-        public MimeWalk(MimeWalkConfiguration configuration, PartMatch 
partMatch) {
-            this.configuration = configuration;
-            this.partMatch = partMatch;
-        }
-
-        private Collection<MailAddress> matchMail(Mail mail) throws 
MessagingException {
-            try {
-                MimeMessage message = mail.getMessage();
-
-                if (matchFound(message)) {
-                    return mail.getRecipients();
-                } else {
-                    return null;
-                }
-
-            } catch (Exception e) {
-                if (configuration.isDebug()) {
-                    LOGGER.debug("Malformed message", e);
-                }
-                throw new MessagingException("Malformed message", e);
-            }
-        }
-
-        /**
-         * Checks if <I>part</I> matches with at least one of the 
<CODE>masks</CODE>.
-         *
-         * @param part
-         */
-        protected boolean matchFound(Part part) throws Exception {
-
-            /*
-             * if there is an attachment and no inline text,
-             * the content type can be anything
-             */
-
-            if (part.getContentType() == null ||
-                part.getContentType().startsWith("multipart/alternative")) {
-                return false;
-            }
-
-            Object content;
-
-            try {
-                content = part.getContent();
-            } catch (UnsupportedEncodingException uee) {
-                // in this case it is not an attachment, so ignore it
-                return false;
-            }
-
-            Exception anException = null;
-
-            if (content instanceof Multipart) {
-                Multipart multipart = (Multipart) content;
-                for (int i = 0; i < multipart.getCount(); i++) {
-                    try {
-                        Part bodyPart = multipart.getBodyPart(i);
-                        if (matchFound(bodyPart)) {
-                            return true; // matching file found
-                        }
-                    } catch (MessagingException e) {
-                        anException = e;
-                    } // remember any messaging exception and process next 
bodypart
-                }
-            } else {
-                if (partMatch.partMatch(part)) {
-                    return true;
-                }
-            }
-
-            // if no matching attachment was found and at least one exception 
was catched rethrow it up
-            if (anException != null) {
-                throw anException;
-            }
-
-            return false;
-        }
-    }
-
-
     /**
      * Transforms <I>fileName<I> in a trimmed lowercase string usable for 
matching agains the masks.
      * Also decode encoded words.
@@ -196,45 +64,23 @@ public class AttachmentFileNameIs extends GenericMatcher {
         return 
DecoderUtil.decodeEncodedWords(fileName.toLowerCase(Locale.US).trim(), 
DecodeMonitor.SILENT);
     }
     
-    /** Unzip request parameter. */
-    protected static final String UNZIP_REQUEST_PARAMETER = "-z";
-    
-    /** Debug request parameter. */
-    protected static final String DEBUG_REQUEST_PARAMETER = "-d";
-    
     /** Match string for zip files. */
     protected static final String ZIP_SUFFIX = ".zip";
     
     /**
      * represents a single parsed file name mask.
      */
-    private static class Mask {
-        /** true if the mask starts with a wildcard asterisk */
-        public boolean suffixMatch;
-        
-        /** file name mask not including the wildcard asterisk */
-        public String matchString;
-
-        public boolean match(String fileName) {
-            //XXX: file names in mail may contain directory - theoretically
-            if (this.suffixMatch) {
-                return fileName.endsWith(this.matchString);
-            } else {
-                return fileName.equals(this.matchString);
-            }
-        }
-    }
     
     /**
      * Controls certain log messages.
      */
     @VisibleForTesting
-    MimeWalkConfiguration configuration = MimeWalkConfiguration.DEFAULT;
+    MimeWalk.Configuration configuration = MimeWalk.Configuration.DEFAULT;
     
 
     @Override
     public void init() throws MessagingException {
-        configuration = MimeWalkConfiguration.parse(getCondition());
+        configuration = MimeWalk.Configuration.parse(getCondition());
     }
 
     /** 
@@ -271,7 +117,7 @@ public class AttachmentFileNameIs extends GenericMatcher {
      * @param fileName
      */
     protected boolean matchFound(String fileName) {
-        for (Mask mask1 : configuration.masks) {
+        for (MimeWalk.Mask mask1 : configuration.masks()) {
             if (mask1.match(fileName)) {
                 return true; // matching file found
             }
@@ -293,7 +139,7 @@ public class AttachmentFileNameIs extends GenericMatcher {
                 }
                 String fileName = zipEntry.getName();
                 if (matchFound(fileName)) {
-                    if (configuration.unzipIsRequested) {
+                    if (configuration.unzipIsRequested()) {
                         LOGGER.debug("matched {}({})", part.getFileName(), 
fileName);
                     }
                     return true;
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/utils/MimeWalk.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/utils/MimeWalk.java
new file mode 100644
index 0000000000..9b2a9a776a
--- /dev/null
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/utils/MimeWalk.java
@@ -0,0 +1,199 @@
+/****************************************************************
+ * 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.james.transport.matchers.utils;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import jakarta.mail.MessagingException;
+import jakarta.mail.Multipart;
+import jakarta.mail.Part;
+import jakarta.mail.internet.MimeMessage;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.codec.DecoderUtil;
+import org.apache.mailet.Mail;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MimeWalk {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(MimeWalk.class);
+    /** Unzip request parameter. */
+    protected static final String UNZIP_REQUEST_PARAMETER = "-z";
+
+    /** Debug request parameter. */
+    protected static final String DEBUG_REQUEST_PARAMETER = "-d";
+
+    @FunctionalInterface
+    public interface PartMatch {
+        boolean partMatch(Part part) throws MessagingException, IOException;
+    }
+
+    public static class Mask {
+        /** true if the mask starts with a wildcard asterisk */
+        private boolean suffixMatch;
+
+        /** file name mask not including the wildcard asterisk */
+        private String matchString;
+
+        public boolean match(String fileName) {
+            //XXX: file names in mail may contain directory - theoretically
+            if (this.suffixMatch) {
+                return fileName.endsWith(this.matchString);
+            } else {
+                return fileName.equals(this.matchString);
+            }
+        }
+
+        public boolean isSuffixMatch() {
+            return suffixMatch;
+        }
+
+        public String getMatchString() {
+            return matchString;
+        }
+    }
+
+    public record Configuration(Mask[] masks, boolean isDebug, boolean 
unzipIsRequested) {
+        public static Configuration DEFAULT = new Configuration(null, false, 
false);
+
+        public static Configuration parse(String condition) {
+            StringTokenizer st = new StringTokenizer(condition, ", ", false);
+            ArrayList<Mask> theMasks = new ArrayList<>(20);
+            boolean unzipIsRequested = false;
+            boolean isDebug = false;
+            while (st.hasMoreTokens()) {
+                String fileName = st.nextToken();
+
+                // check possible parameters at the beginning of the condition
+                if (theMasks.isEmpty() && 
fileName.equalsIgnoreCase(UNZIP_REQUEST_PARAMETER)) {
+                    unzipIsRequested = true;
+                    LOGGER.info("zip file analysis requested");
+                    continue;
+                }
+                if (theMasks.isEmpty() && 
fileName.equalsIgnoreCase(DEBUG_REQUEST_PARAMETER)) {
+                    isDebug = true;
+                    LOGGER.info("debug requested");
+                    continue;
+                }
+                Mask mask = new Mask();
+                if (fileName.startsWith("*")) {
+                    mask.suffixMatch = true;
+                    mask.matchString = fileName.substring(1);
+                } else {
+                    mask.suffixMatch = false;
+                    mask.matchString = fileName;
+                }
+                mask.matchString = cleanString(mask.matchString);
+                theMasks.add(mask);
+            }
+            return new Configuration(theMasks.toArray(Mask[]::new), isDebug, 
unzipIsRequested);
+        }
+    }
+
+    public static String cleanString(String fileName) {
+        return 
DecoderUtil.decodeEncodedWords(fileName.toLowerCase(Locale.US).trim(), 
DecodeMonitor.SILENT);
+    }
+
+    private final Configuration configuration;
+    private final PartMatch partMatch;
+
+    public MimeWalk(Configuration configuration, PartMatch partMatch) {
+        this.configuration = configuration;
+        this.partMatch = partMatch;
+    }
+
+    public Collection<MailAddress> matchMail(Mail mail) throws 
MessagingException {
+        try {
+            MimeMessage message = mail.getMessage();
+
+            if (matchFound(message)) {
+                return mail.getRecipients();
+            } else {
+                return null;
+            }
+
+        } catch (Exception e) {
+            if (configuration.isDebug()) {
+                LOGGER.debug("Malformed message", e);
+            }
+            throw new MessagingException("Malformed message", e);
+        }
+    }
+
+    /**
+     * Checks if <I>part</I> matches with at least one of the 
<CODE>masks</CODE>.
+     *
+     * @param part
+     */
+    protected boolean matchFound(Part part) throws Exception {
+
+        /*
+         * if there is an attachment and no inline text,
+         * the content type can be anything
+         */
+
+        if (part.getContentType() == null ||
+            part.getContentType().startsWith("multipart/alternative")) {
+            return false;
+        }
+
+        Object content;
+
+        try {
+            content = part.getContent();
+        } catch (UnsupportedEncodingException uee) {
+            // in this case it is not an attachment, so ignore it
+            return false;
+        }
+
+        Exception anException = null;
+
+        if (content instanceof Multipart) {
+            Multipart multipart = (Multipart) content;
+            for (int i = 0; i < multipart.getCount(); i++) {
+                try {
+                    Part bodyPart = multipart.getBodyPart(i);
+                    if (matchFound(bodyPart)) {
+                        return true; // matching file found
+                    }
+                } catch (MessagingException e) {
+                    anException = e;
+                } // remember any messaging exception and process next bodypart
+            }
+        } else {
+            if (partMatch.partMatch(part)) {
+                return true;
+            }
+        }
+
+        // if no matching attachment was found and at least one exception was 
catched rethrow it up
+        if (anException != null) {
+            throw anException;
+        }
+
+        return false;
+    }
+}
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/AttachmentFileNameIsTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/AttachmentFileNameIsTest.java
index 5642dbadcd..d0657c1dcf 100644
--- 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/AttachmentFileNameIsTest.java
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/AttachmentFileNameIsTest.java
@@ -27,7 +27,6 @@ import org.apache.james.util.ClassLoaderUtils;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.test.FakeMail;
 import org.apache.mailet.base.test.FakeMatcherConfig;
-import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
 class AttachmentFileNameIsTest {
@@ -535,27 +534,4 @@ class AttachmentFileNameIsTest {
         assertThat(testee.match(mail))
             .isNull();
     }
-
-    @Nested
-    class MimeWalkConfigurationTest {
-        @Test
-        void shouldSupportDebugMode() {
-            assertThat(AttachmentFileNameIs.MimeWalkConfiguration.parse("-d 
test.txt").isDebug()).isTrue();
-        }
-
-        @Test
-        void debugModeShouldBeFalseByDefault() {
-            
assertThat(AttachmentFileNameIs.MimeWalkConfiguration.parse("test.txt").isDebug()).isFalse();
-        }
-
-        @Test
-        void shouldSupportUnzipMode() {
-            assertThat(AttachmentFileNameIs.MimeWalkConfiguration.parse("-z 
test.txt").unzipIsRequested()).isTrue();
-        }
-
-        @Test
-        void unzipModeShouldBeFalseByDefault() {
-            
assertThat(AttachmentFileNameIs.MimeWalkConfiguration.parse("test.txt").unzipIsRequested()).isFalse();
-        }
-    }
 }
\ No newline at end of file
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/utils/MimeWalkTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/utils/MimeWalkTest.java
new file mode 100644
index 0000000000..4860783692
--- /dev/null
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/utils/MimeWalkTest.java
@@ -0,0 +1,51 @@
+/****************************************************************
+ * 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.james.transport.matchers.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+class MimeWalkTest {
+
+    @Nested
+    class ConfigurationTest {
+        @Test
+        void shouldSupportDebugMode() {
+            assertThat(MimeWalk.Configuration.parse("-d 
test.txt").isDebug()).isTrue();
+        }
+
+        @Test
+        void debugModeShouldBeFalseByDefault() {
+            
assertThat(MimeWalk.Configuration.parse("test.txt").isDebug()).isFalse();
+        }
+
+        @Test
+        void shouldSupportUnzipMode() {
+            assertThat(MimeWalk.Configuration.parse("-z 
test.txt").unzipIsRequested()).isTrue();
+        }
+
+        @Test
+        void unzipModeShouldBeFalseByDefault() {
+            
assertThat(MimeWalk.Configuration.parse("test.txt").unzipIsRequested()).isFalse();
+        }
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to