You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ro...@apache.org on 2017/01/10 14:18:21 UTC

[06/50] [abbrv] james-project git commit: JAMES-1877 Refactor Delays related class

JAMES-1877 Refactor Delays related class

 - also add support for no unit in TimeConverter


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/61c6309f
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/61c6309f
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/61c6309f

Branch: refs/heads/master
Commit: 61c6309f65d43889f98c1984d3f040603f43d9d0
Parents: 8a8af97
Author: Benoit Tellier <bt...@linagora.com>
Authored: Wed Nov 30 00:44:17 2016 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Tue Jan 10 14:40:34 2017 +0700

----------------------------------------------------------------------
 .../org/apache/james/util/TimeConverter.java    |   3 +-
 .../apache/james/util/TimeConverterTest.java    |  10 ++
 .../james/transport/mailets/RemoteDelivery.java |   7 +-
 .../transport/mailets/remoteDelivery/Delay.java | 137 ++++++-------------
 .../remoteDelivery/DelaysAndMaxRetry.java       | 107 +++++++--------
 .../mailets/remoteDelivery/Repeat.java          |  37 +++++
 .../mailets/remoteDelivery/DelayTest.java       |  37 ++---
 .../remoteDelivery/DelaysAndMaxRetryTest.java   |   4 +-
 .../mailets/remoteDelivery/RepeatTest.java      |  58 ++++++++
 9 files changed, 226 insertions(+), 174 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java
----------------------------------------------------------------------
diff --git a/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java b/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java
index 2a877b7..162fef5 100644
--- a/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java
+++ b/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java
@@ -27,12 +27,13 @@ public class TimeConverter {
 
     private static final HashMap<String, Integer> multipliers = new HashMap<String, Integer>(10);
 
-    private static final String PATTERN_STRING = "\\s*([0-9]+)\\s*([a-z,A-Z]+)\\s*";
+    private static final String PATTERN_STRING = "\\s*([0-9]+)\\s*([a-z,A-Z]*)\\s*";
 
     private static Pattern PATTERN = null;
 
     static {
         // add allowed units and their respective multiplier
+        multipliers.put("", 1);
         multipliers.put("ms", 1);
         multipliers.put("msec", 1);
         multipliers.put("msecs", 1);

http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java
----------------------------------------------------------------------
diff --git a/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java b/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java
index b05a935..fc13f58 100644
--- a/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java
+++ b/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java
@@ -25,6 +25,16 @@ import java.util.concurrent.TimeUnit;
 import org.junit.Test;
 
 public class TimeConverterTest {
+    
+    @Test
+    public void getMilliSecondsShouldConvertValueWhenNoUnitAmountAsString() {
+        //Given
+        long expected = 2;
+        //When
+        long actual = TimeConverter.getMilliSeconds("2");
+        //Then
+        assertThat(actual).isEqualTo(expected);
+    }
 
     @Test 
     public void getMilliSecondsShouldConvertValueWhenMsecUnit() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
index 9ffd164..88f8ea7 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
@@ -33,6 +33,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.Hashtable;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
@@ -166,7 +167,7 @@ public class RemoteDelivery extends GenericMailet implements Runnable {
     /**
      * List of Delay Times. Controls frequency of retry attempts.
      */
-    private long[] delayTimes;
+    private List<Long> delayTimes;
 
     /**
      * Maximum no. of retries (Defaults to 5).
@@ -392,10 +393,10 @@ public class RemoteDelivery extends GenericMailet implements Runnable {
      * @return the next delay time to use, given the retry count
      */
     private long getNextDelay(int retry_count) {
-        if (retry_count > delayTimes.length) {
+        if (retry_count > delayTimes.size()) {
             return Delay.DEFAULT_DELAY_TIME;
         }
-        return delayTimes[retry_count - 1];
+        return delayTimes.get(retry_count - 1);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Delay.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Delay.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Delay.java
index c066a63..3f50ea7 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Delay.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Delay.java
@@ -19,133 +19,82 @@
 
 package org.apache.james.transport.mailets.remoteDelivery;
 
-import java.util.Locale;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import javax.mail.MessagingException;
 
-import org.apache.james.transport.util.Patterns;
 import org.apache.james.util.TimeConverter;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 
-/**
- * This class is used to hold a delay time and its corresponding number of
- * retries.
- */
 public class Delay {
-
-    /**
-     * Default Delay Time (Default is 6*60*60*1000 Milliseconds (6 hours)).
-     */
-    public static final long DEFAULT_DELAY_TIME = 21600000;
-    public static final int DEFAULT_ATTEMPTS = 1;
-    /**
-     * Pattern to match [attempts*]delay[units].
-     */
-    private static final String PATTERN_STRING = "\\s*([0-9]*\\s*[\\*])?\\s*([0-9]+)\\s*([a-z,A-Z]*)\\s*";
-    private static final Pattern PATTERN = Patterns.compilePatternUncheckedException(PATTERN_STRING);
-
-    private int attempts = DEFAULT_ATTEMPTS;
-
-    private long delayTime = DEFAULT_DELAY_TIME;
-
     /**
-     * <p>
-     * This constructor expects Strings of the form
-     * "[attempt\*]delaytime[unit]".
-     * </p>
-     * <p>
-     * The optional attempt is the number of tries this delay should be used
-     * (default = 1). The unit, if present, must be one of
-     * (msec,sec,minute,hour,day). The default value of unit is 'msec'.
-     * </p>
-     * <p>
-     * The constructor multiplies the delaytime by the relevant multiplier
-     * for the unit, so the delayTime instance variable is always in msec.
-     * </p>
+     * <p> The optional attempt is the number of tries this delay should be used (default = 1).
+     * The delayTime is parsed by {@link TimeConverter}</p>
      *
-     * @param initString the string to initialize this Delay object from
+     * @param initString the string to initialize this Delay object from. It has the form "[attempt\*]delaytime[unit]"
      */
-    public Delay(String initString) throws MessagingException {
-        // Default unit value to 'msec'.
-        String unit = "msec";
-
-        Matcher res = PATTERN.matcher(initString);
-        if (res.matches()) {
-            // The capturing groups will now hold:
-            // at 1: attempts * (if present)
-            // at 2: delaytime
-            // at 3: unit (if present)
-            if (res.group(1) != null && !res.group(1).equals("")) {
-                // We have an attempt *
-                String attemptMatch = res.group(1);
-
-                // Strip the * and whitespace.
-                attemptMatch = attemptMatch.substring(0, attemptMatch.length() - 1).trim();
-                attempts = Integer.parseInt(attemptMatch);
-            }
-
-            delayTime = Long.parseLong(res.group(2));
-
-            if (!res.group(3).equals("")) {
-                // We have a value for 'unit'.
-                unit = res.group(3).toLowerCase(Locale.US);
-            }
-        } else {
-            throw new MessagingException(initString + " does not match " + PATTERN_STRING);
+    public static Delay from(String initString) throws MessagingException {
+        if (Strings.isNullOrEmpty(initString)) {
+            throw new NumberFormatException("Null or Empty strings are not permitted");
         }
+        List<String> parts = Splitter.on('*').splitToList(initString);
 
-        // calculate delayTime.
-        try {
-            delayTime = TimeConverter.getMilliSeconds(delayTime, unit);
-        } catch (NumberFormatException e) {
-            throw new MessagingException(e.getMessage());
+        if (parts.size() == 1) {
+            return new Delay(DEFAULT_ATTEMPTS, TimeConverter.getMilliSeconds(parts.get(0)));
+        }
+        if (parts.size() == 2) {
+            int attempts = Integer.parseInt(parts.get(0));
+            if (attempts < 0) {
+                throw new MessagingException("Number of attempts negative in " + initString);
+            }
+            return new Delay(attempts, TimeConverter.getMilliSeconds(parts.get(1)));
         }
+        throw new MessagingException(initString + " contains too much parts");
     }
 
-    /**
-     * This constructor makes a default Delay object with attempts = 1 and
-     * delayTime = DEFAULT_DELAY_TIME.
-     */
+    public static final long DEFAULT_DELAY_TIME = TimeUnit.HOURS.toMillis(6);
+    public static final int DEFAULT_ATTEMPTS = 1;
+
+    private final int attempts;
+    private final long delayTimeInMs;
+
     public Delay() {
+        this(DEFAULT_ATTEMPTS, DEFAULT_DELAY_TIME);
     }
 
     @VisibleForTesting
     Delay(int attempts, long delayTime) {
         this.attempts = attempts;
-        this.delayTime = delayTime;
+        this.delayTimeInMs = delayTime;
     }
 
-    /**
-     * @return the delayTime for this Delay
-     */
-    public long getDelayTime() {
-        return delayTime;
+    public long getDelayTimeInMs() {
+        return delayTimeInMs;
     }
 
-    /**
-     * @return the number attempts this Delay should be used.
-     */
     public int getAttempts() {
         return attempts;
     }
 
-    /**
-     * Set the number attempts this Delay should be used.
-     */
-    public void setAttempts(int value) {
-        attempts = value;
+    public List<Long> getExpendendDelays() {
+        return Repeat.repeat(delayTimeInMs, attempts);
     }
 
-    /**
-     * Pretty prints this Delay
-     */
     @Override
     public String toString() {
-        return getAttempts() + "*" + getDelayTime() + "msecs";
+        return MoreObjects.toStringHelper(this)
+            .add("attempts", attempts)
+            .add("delayTime", delayTimeInMs)
+            .toString();
     }
 
     @Override
@@ -154,13 +103,13 @@ public class Delay {
             Delay that = (Delay) o;
 
             return Objects.equal(this.attempts, that.attempts)
-                && Objects.equal(this.delayTime, that.delayTime);
+                && Objects.equal(this.delayTimeInMs, that.delayTimeInMs);
         }
         return false;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(attempts, delayTime);
+        return Objects.hashCode(attempts, delayTimeInMs);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetry.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetry.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetry.java
index 10b6cca..16ae192 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetry.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetry.java
@@ -19,10 +19,7 @@
 
 package org.apache.james.transport.mailets.remoteDelivery;
 
-import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
-import java.util.StringTokenizer;
 
 import javax.mail.MessagingException;
 
@@ -31,72 +28,75 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Objects;
+import com.google.common.base.Splitter;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 
 public class DelaysAndMaxRetry {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(DelaysAndMaxRetry.class);
 
-    public static DelaysAndMaxRetry from(int intendedMaxRetries, String delaysAsString) throws MessagingException {
-        // Create list of Delay Times.
-        ArrayList<Delay> delayTimesList = createDelayList(delaysAsString);
+    public static DelaysAndMaxRetry defaults() {
+        return new DelaysAndMaxRetry(RemoteDeliveryConfiguration.DEFAULT_MAX_RETRY, Repeat.repeat(new Delay(), RemoteDeliveryConfiguration.DEFAULT_MAX_RETRY));
+    }
 
-        // Check consistency of 'maxRetries' with delayTimesList attempts.
-        int totalAttempts = calcTotalAttempts(delayTimesList);
+    public static DelaysAndMaxRetry from(int intendedMaxRetries, String delaysAsString) throws MessagingException {
+        List<Delay> delayTimesList = createDelayList(delaysAsString);
+        int totalAttempts = computeTotalAttempts(delayTimesList);
+        return getDelaysAndMaxRetry(intendedMaxRetries, totalAttempts, delayTimesList);
+    }
 
-        // If inconsistency found, fix it.
+    private static DelaysAndMaxRetry getDelaysAndMaxRetry(int intendedMaxRetries, int totalAttempts, List<Delay> delayTimesList) throws MessagingException {
         if (totalAttempts > intendedMaxRetries) {
-            LOGGER.warn("Total number of delayTime attempts exceeds maxRetries specified. " + " Increasing maxRetries from " + intendedMaxRetries + " to " + totalAttempts);
+            LOGGER.warn("Total number of delayTime attempts exceeds maxRetries specified. Increasing maxRetries from {} to {}", intendedMaxRetries, totalAttempts);
             return new DelaysAndMaxRetry(totalAttempts, delayTimesList);
         } else {
             int extra = intendedMaxRetries - totalAttempts;
-            if (extra != 0) {
-                LOGGER.warn("maxRetries is larger than total number of attempts specified.  " + "Increasing last delayTime with " + extra + " attempts ");
-
-                // Add extra attempts to the last delayTime.
-                if (delayTimesList.size() != 0) {
-                    // Get the last delayTime.
-                    Delay delay = delayTimesList.get(delayTimesList.size() - 1);
-
-                    // Increase no. of attempts.
-                    delay.setAttempts(delay.getAttempts() + extra);
-                    LOGGER.warn("Delay of " + delay.getDelayTime() + " msecs is now attempted: " + delay.getAttempts() + " times");
-                } else {
-                    throw new MessagingException("No delaytimes, cannot continue");
-                }
+            if (extra > 0) {
+                LOGGER.warn("maxRetries is larger than total number of attempts specified. Increasing last delayTime with {} attempts ", extra);
+                return addExtraAttemptToLastDelay(intendedMaxRetries, extra, delayTimesList);
             }
             return new DelaysAndMaxRetry(intendedMaxRetries, delayTimesList);
         }
     }
 
-    private static ArrayList<Delay> createDelayList(String delaysAsString) {
-        ArrayList<Delay> delayTimesList = new ArrayList<Delay>();
+    private static DelaysAndMaxRetry addExtraAttemptToLastDelay(int intendedMaxRetries, int extra, List<Delay> delayTimesList) throws MessagingException {
+        if (delayTimesList.size() != 0) {
+            Delay lastDelay = delayTimesList.get(delayTimesList.size() - 1);
+            LOGGER.warn("Delay of {} msecs is now attempted: {} times", lastDelay.getDelayTimeInMs(), lastDelay.getAttempts());
+            return new DelaysAndMaxRetry(intendedMaxRetries,
+                ImmutableList.copyOf(
+                    Iterables.concat(
+                        Iterables.limit(delayTimesList, delayTimesList.size() - 1),
+                        ImmutableList.of(new Delay(lastDelay.getAttempts() + extra, lastDelay.getDelayTimeInMs())))));
+        } else {
+            throw new MessagingException("No delaytimes, cannot continue");
+        }
+    }
+
+    private static List<Delay> createDelayList(String delaysAsString) {
+        if (delaysAsString == null) {
+            // Use default delayTime.
+            return ImmutableList.of(new Delay());
+        }
+        ImmutableList<String> delayStrings = FluentIterable.from(Splitter.on(',')
+            .omitEmptyStrings()
+            .split(delaysAsString))
+            .toList();
+        ImmutableList.Builder<Delay> builder = ImmutableList.builder();
         try {
-            if (delaysAsString != null) {
-
-                // Split on commas
-                StringTokenizer st = new StringTokenizer(delaysAsString, ",");
-                while (st.hasMoreTokens()) {
-                    String delayTime = st.nextToken();
-                    delayTimesList.add(new Delay(delayTime));
-                }
-            } else {
-                // Use default delayTime.
-                delayTimesList.add(new Delay());
+            for (String s : delayStrings) {
+                builder.add(Delay.from(s));
             }
+            return builder.build();
         } catch (Exception e) {
-            LOGGER.warn("Invalid delayTime setting: " + delaysAsString);
+            LOGGER.warn("Invalid delayTime setting: {}", delaysAsString);
+            return builder.build();
         }
-        return delayTimesList;
     }
 
-    /**
-     * Calculates Total no. of attempts for the specified delayList.
-     *
-     * @param delayList list of 'Delay' objects
-     * @return total no. of retry attempts
-     */
-    private static int calcTotalAttempts(List<Delay> delayList) {
+    private static int computeTotalAttempts(List<Delay> delayList) {
         int sum = 0;
         for (Delay delay : delayList) {
             sum += delay.getAttempts();
@@ -136,17 +136,12 @@ public class DelaysAndMaxRetry {
      * @param list the list to expand
      * @return the expanded list
      */
-    public long[] getExpendedDelays() {
-        long[] delaysAsLong = new long[calcTotalAttempts(delays)];
-        Iterator<Delay> i = delays.iterator();
-        int idx = 0;
-        while (i.hasNext()) {
-            Delay delay = i.next();
-            for (int j = 0; j < delay.getAttempts(); j++) {
-                delaysAsLong[idx++] = delay.getDelayTime();
-            }
+    public List<Long> getExpendedDelays() {
+        ImmutableList.Builder<Long> builder = ImmutableList.builder();
+        for (Delay delay: delays) {
+            builder.addAll(delay.getExpendendDelays());
         }
-        return delaysAsLong;
+        return builder.build();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Repeat.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Repeat.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Repeat.java
new file mode 100644
index 0000000..0252214
--- /dev/null
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/Repeat.java
@@ -0,0 +1,37 @@
+/****************************************************************
+ * 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.mailets.remoteDelivery;
+
+import java.util.List;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class Repeat {
+
+    public static <T> List<T> repeat(T element, int times) {
+        Preconditions.checkArgument(times > 0, "Times argument should be strictly positive");
+        return ImmutableList.copyOf(
+            Iterables.limit(
+                Iterables.cycle(element), times));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelayTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelayTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelayTest.java
index f23c918..b940c3e 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelayTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelayTest.java
@@ -40,78 +40,79 @@ public class DelayTest {
 
     @Test
     public void stringConstructorShouldWorkForNumbers() throws Exception {
-        assertThat(new Delay("36")).isEqualTo(new Delay(Delay.DEFAULT_ATTEMPTS, 36));
+        assertThat(Delay.from("36")).isEqualTo(new Delay(Delay.DEFAULT_ATTEMPTS, 36));
     }
 
     @Test
     public void stringConstructorShouldWorkForZero() throws Exception {
-        assertThat(new Delay("0")).isEqualTo(new Delay(Delay.DEFAULT_ATTEMPTS, 0));
+        assertThat(Delay.from("0")).isEqualTo(new Delay(Delay.DEFAULT_ATTEMPTS, 0));
     }
 
     @Test
-    public void stringConstructorShouldDefaultToZeroForNegatives() throws Exception {
-        assertThat(new Delay("0")).isEqualTo(new Delay(Delay.DEFAULT_ATTEMPTS, 0));
+    public void stringConstructorShouldThrowOnNegativeNumbers() throws Exception {
+        expectedException.expect(NumberFormatException.class);
+        assertThat(Delay.from("-1s")).isEqualTo(new Delay(Delay.DEFAULT_ATTEMPTS, 0));
     }
 
     @Test
     public void stringConstructorShouldWorkForNumberAndSecond() throws Exception {
-        assertThat(new Delay("1s")).isEqualTo(new Delay(Delay.DEFAULT_ATTEMPTS, 1000));
+        assertThat(Delay.from("1s")).isEqualTo(new Delay(Delay.DEFAULT_ATTEMPTS, 1000));
     }
 
     @Test
     public void stringConstructorShouldWorkForNumberAndAttempts() throws Exception {
-        assertThat(new Delay("2*36")).isEqualTo(new Delay(2, 36));
+        assertThat(Delay.from("2*36")).isEqualTo(new Delay(2, 36));
     }
 
     @Test
     public void stringConstructorShouldWorkForNumberAndZeroAttempts() throws Exception {
-        assertThat(new Delay("0*36")).isEqualTo(new Delay(0, 36));
+        assertThat(Delay.from("0*36")).isEqualTo(new Delay(0, 36));
     }
 
     @Test
     public void stringConstructorShouldThrowOnNegativeAttempts() throws Exception {
         expectedException.expect(MessagingException.class);
 
-        new Delay("-1*36");
+        Delay.from("-1*36");
     }
 
     @Test
     public void stringConstructorShouldThrowWhenAttemptsOmitted() throws Exception {
         expectedException.expect(NumberFormatException.class);
 
-        new Delay("*36");
+        Delay.from("*36");
     }
 
     @Test
     public void stringConstructorShouldThrowWhenDelayOmitted() throws Exception {
-        expectedException.expect(MessagingException.class);
+        expectedException.expect(NumberFormatException.class);
 
-        new Delay("2*");
+        Delay.from("2*");
     }
 
     @Test
     public void stringConstructorShouldWorkForNumberAttemptsAndUnit() throws Exception {
-        assertThat(new Delay("2*36s")).isEqualTo(new Delay(2, 36000));
+        assertThat(Delay.from("2*36s")).isEqualTo(new Delay(2, 36000));
     }
 
     @Test
     public void stringConstructorShouldThrowOnInvalidInput() throws Exception {
-        expectedException.expect(MessagingException.class);
+        expectedException.expect(NumberFormatException.class);
 
-        new Delay("invalid");
+        Delay.from("invalid");
     }
 
     @Test
     public void stringConstructorShouldThrowOnInvalidUnit() throws Exception {
-        expectedException.expect(MessagingException.class);
+        expectedException.expect(NumberFormatException.class);
 
-        new Delay("36invalid");
+        Delay.from("36invalid");
     }
 
     @Test
     public void stringConstructorShouldThrowOnEmptyString() throws Exception {
-        expectedException.expect(MessagingException.class);
+        expectedException.expect(NumberFormatException.class);
 
-        new Delay("");
+        Delay.from("");
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetryTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetryTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetryTest.java
index da4ecda..dbab3c4 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetryTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DelaysAndMaxRetryTest.java
@@ -124,13 +124,13 @@ public class DelaysAndMaxRetryTest {
     public void getExpendedDelaysShouldExpandSingleDelays() throws Exception {
         DelaysAndMaxRetry testee = DelaysAndMaxRetry.from(3, "1*1S,1*2S,1*5S");
 
-        assertThat(testee.getExpendedDelays()).containsExactly(1000, 2000, 5000);
+        assertThat(testee.getExpendedDelays()).containsExactly(1000L, 2000L, 5000L);
     }
 
     @Test
     public void getExpendedDelaysShouldExpandMultipleDelays() throws Exception {
         DelaysAndMaxRetry testee = DelaysAndMaxRetry.from(3, "1*1S,2*2S,2*5S");
 
-        assertThat(testee.getExpendedDelays()).containsExactly(1000, 2000, 2000, 5000, 5000);
+        assertThat(testee.getExpendedDelays()).containsExactly(1000L, 2000L, 2000L, 5000L, 5000L);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/61c6309f/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/RepeatTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/RepeatTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/RepeatTest.java
new file mode 100644
index 0000000..13b9968
--- /dev/null
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/RepeatTest.java
@@ -0,0 +1,58 @@
+/****************************************************************
+ * 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.mailets.remoteDelivery;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class RepeatTest {
+
+    public static final String ELEMENT = "a";
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void repeatShouldThrowOnNegativeTimes() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        Repeat.repeat(new Object(), -1);
+    }
+
+    @Test
+    public void repeatShouldThrowOnZeroTimes() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        Repeat.repeat(new Object(), 0);
+    }
+
+    @Test
+    public void repeatShouldWorkWithOneElement() {
+        assertThat(Repeat.repeat(ELEMENT, 1)).containsExactly(ELEMENT);
+    }
+
+    @Test
+    public void repeatShouldWorkWithTwoElements() {
+        assertThat(Repeat.repeat(ELEMENT, 2)).containsExactly(ELEMENT, ELEMENT);
+    }
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org