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 bt...@apache.org on 2018/11/01 04:07:36 UTC

[01/17] james-project git commit: JAMES-2557 MailHook should use a MaybeSender

Repository: james-project
Updated Branches:
  refs/heads/master 096c6c763 -> 38b3d7a59


JAMES-2557 MailHook should use a MaybeSender


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

Branch: refs/heads/master
Commit: 215f99d0ebcb4c65fa81d9f0fdf43cdd75457cdb
Parents: 096c6c7
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 10:49:01 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 10:55:43 2018 +0700

----------------------------------------------------------------------
 .../james/protocols/smtp/hook/MailHook.java     | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/215f99d0/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/MailHook.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/MailHook.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/MailHook.java
index ec1649f..a1c48a8 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/MailHook.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/MailHook.java
@@ -20,6 +20,7 @@
 package org.apache.james.protocols.smtp.hook;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPSession;
 
 /**
@@ -30,10 +31,27 @@ public interface MailHook extends Hook {
 
     /**
      * Return the HookResult after run the hook
+     *
+     * @Deprecated use {@link #doMail(SMTPSession, MaybeSender)} instead
      * 
      * @param session the SMTPSession
      * @param sender the sender MailAddress
      * @return HockResult
      */
-    HookResult doMail(SMTPSession session, MailAddress sender);
+    @Deprecated
+    default HookResult doMail(SMTPSession session, MailAddress sender) {
+        return doMail(session, MaybeSender.of(sender));
+    }
+
+    /**
+     * Return the HookResult after run the hook
+     *
+     * This strongly typed version of do mail is safer to use.
+     *
+     * @since James 3.2.0
+     */
+    @SuppressWarnings("deprecated")
+    default HookResult doMail(SMTPSession session, MaybeSender sender) {
+        return doMail(session, sender.asOptional().orElse(MailAddress.nullSender()));
+    }
 }


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


[11/17] james-project git commit: JAMES-2578 Add an Optional serializer

Posted by bt...@apache.org.
JAMES-2578 Add an Optional serializer


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

Branch: refs/heads/master
Commit: d66fa22b9af271d0d56e326a8c4f6c31bc399650
Parents: c1f4ba5
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 09:08:02 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:03:27 2018 +0700

----------------------------------------------------------------------
 .../java/org/apache/mailet/AttributeValue.java  |  9 ++++
 .../main/java/org/apache/mailet/Serializer.java | 34 ++++++++++++-
 .../org/apache/mailet/AttributeValueTest.java   | 52 ++++++++++++++++++++
 3 files changed, 94 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/d66fa22b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
index 6bf3a6e..4ae6952 100644
--- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -87,6 +87,12 @@ public class AttributeValue<T> {
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static <T> AttributeValue<Optional<AttributeValue<T>>> of(Optional<AttributeValue<T>> value) {
+        Preconditions.checkNotNull(value, "value should not be null");
+        return new AttributeValue<>(value, new Serializer.OptionalSerializer<>());
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     public static AttributeValue<Collection<AttributeValue<?>>> of(Collection<AttributeValue<?>> value) {
         Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, new Serializer.CollectionSerializer());
@@ -135,6 +141,9 @@ public class AttributeValue<T> {
         if (value instanceof URL) {
             return of((URL) value);
         }
+        if (value instanceof Optional) {
+            return of((Optional) value);
+        }
         if (value instanceof Serializable) {
             return ofSerializable((Serializable) value);
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/d66fa22b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
index 514b464..e3eb47a 100644
--- a/mailet/api/src/main/java/org/apache/mailet/Serializer.java
+++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
@@ -47,6 +47,7 @@ import com.fasterxml.jackson.databind.node.FloatNode;
 import com.fasterxml.jackson.databind.node.IntNode;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.LongNode;
+import com.fasterxml.jackson.databind.node.NullNode;
 import com.fasterxml.jackson.databind.node.NumericNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.node.TextNode;
@@ -82,7 +83,8 @@ public interface Serializer<T> {
                     URL_SERIALIZER,
                     new CollectionSerializer<>(),
                     new MapSerializer<>(),
-                    new FSTSerializer())
+                    new FSTSerializer(),
+                    new OptionalSerializer<>())
                 .collect(ImmutableMap.toImmutableMap(Serializer::getName, Function.identity()));
         }
 
@@ -405,6 +407,36 @@ public interface Serializer<T> {
         }
     }
 
+    class OptionalSerializer<U> implements Serializer<Optional<AttributeValue<U>>> {
+        @Override
+        public JsonNode serialize(Optional<AttributeValue<U>> object) {
+            return object.map(AttributeValue::toJson)
+                .orElse(NullNode.getInstance());
+        }
+
+        @Override
+        public Optional<Optional<AttributeValue<U>>> deserialize(JsonNode json) {
+            if (json instanceof ObjectNode) {
+                AttributeValue<U> value = (AttributeValue<U>) AttributeValue.fromJson(json);
+                return Optional.of(Optional.of(value));
+            } else if (json instanceof NullNode) {
+                return Optional.of(Optional.empty());
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "OptionalSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
     class FSTSerializer implements Serializer<Serializable> {
         static final FSTConfiguration CONFIGURATION = FSTConfiguration.createJsonConfiguration();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/d66fa22b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
index dd3f43f..95cb0c2 100644
--- a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
@@ -446,6 +446,58 @@ class AttributeValueTest {
         }
     }
 
+    @Nested
+    class OptionalSerialization {
+        @Test
+        void nullMapShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((Optional) null));
+        }
+
+        @Test
+        void emptyOptionalShouldBeSerializedAndBack() {
+            AttributeValue<?> expected = AttributeValue.of(Optional.empty());
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void optionalShouldBeSerializedAndBack() {
+            AttributeValue<?> expected = AttributeValue.of(Optional.of(AttributeValue.of(42)));
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnEmptyOptionalWhenEmptyOptional() throws Exception {
+            AttributeValue<?> expected = AttributeValue.of(Optional.empty());
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"OptionalSerializer\",\"value\":null}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnOptional() throws Exception {
+            AttributeValue<Optional<AttributeValue<Integer>>> expected = AttributeValue.of(
+                Optional.of(AttributeValue.of(1)));
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"OptionalSerializer\",\"value\":{\"serializer\":\"IntSerializer\",\"value\":1}}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"OptionalSerializer\",\"value\": []}"));
+        }
+    }
+
     @Test
     void fromJsonStringShouldThrowOnUnknownSerializer() {
         assertThatIllegalStateException()


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


[09/17] james-project git commit: JAMES-2578 Introduce Attribute abstraction

Posted by bt...@apache.org.
JAMES-2578 Introduce Attribute abstraction


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

Branch: refs/heads/master
Commit: c97bc757dcd79b8cc01cf1eac06100ae19155ca9
Parents: 9a96bd5
Author: Raphael Ouazana <ra...@linagora.com>
Authored: Fri Oct 26 09:11:06 2018 +0200
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:02:43 2018 +0700

----------------------------------------------------------------------
 mailet/api/pom.xml                              | 37 ++++++++-
 .../main/java/org/apache/mailet/Attribute.java  | 81 ++++++++++++++++++++
 .../java/org/apache/mailet/AttributeName.java   | 72 +++++++++++++++++
 .../java/org/apache/mailet/AttributeValue.java  | 73 ++++++++++++++++++
 .../org/apache/mailet/AttributeNameTest.java    | 53 +++++++++++++
 .../java/org/apache/mailet/AttributeTest.java   | 46 +++++++++++
 6 files changed, 359 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c97bc757/mailet/api/pom.xml
----------------------------------------------------------------------
diff --git a/mailet/api/pom.xml b/mailet/api/pom.xml
index 18ee831..5b5d599 100644
--- a/mailet/api/pom.xml
+++ b/mailet/api/pom.xml
@@ -41,6 +41,22 @@
             <artifactId>james-core</artifactId>
         </dependency>
         <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jdk8</artifactId>
+        </dependency>
+        <dependency>
             <groupId>com.github.steveash.guavate</groupId>
             <artifactId>guavate</artifactId>
         </dependency>
@@ -53,9 +69,9 @@
             <artifactId>javax.mail</artifactId>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
+            <groupId>de.ruedigermoeller</groupId>
+            <artifactId>fst</artifactId>
+            <version>2.56</version>
         </dependency>
         <dependency>
             <groupId>nl.jqno.equalsverifier</groupId>
@@ -68,6 +84,21 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.vintage</groupId>
+            <artifactId>junit-vintage-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/c97bc757/mailet/api/src/main/java/org/apache/mailet/Attribute.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/Attribute.java b/mailet/api/src/main/java/org/apache/mailet/Attribute.java
new file mode 100644
index 0000000..a4d5d7c
--- /dev/null
+++ b/mailet/api/src/main/java/org/apache/mailet/Attribute.java
@@ -0,0 +1,81 @@
+/****************************************************************
+ * 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.mailet;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+
+/** 
+ * Attribute attached to an email
+ *
+ * Attributes hold information to be shared during Mail processing, across mailets.
+ * 
+ * @since Mailet API v3.2
+ */
+public class Attribute {
+    private final AttributeName name;
+    private final AttributeValue<?> value;
+
+    public Attribute(AttributeName name, AttributeValue<?> value) {
+        Preconditions.checkNotNull(name, "`name` should not be null");
+        Preconditions.checkNotNull(value, "`value` should not be null");
+
+        this.name = name;
+        this.value = value;
+    }
+
+    public AttributeName getName() {
+        return name;
+    }
+
+    public AttributeValue<?> getValue() {
+        return value;
+    }
+
+    public Attribute duplicate() {
+        return new Attribute(name, value.duplicate());
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof Attribute) {
+            Attribute that = (Attribute) o;
+
+            return Objects.equals(this.name, that.name)
+                && Objects.equals(this.value, that.value);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("name", name)
+            .add("value", value)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c97bc757/mailet/api/src/main/java/org/apache/mailet/AttributeName.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeName.java b/mailet/api/src/main/java/org/apache/mailet/AttributeName.java
new file mode 100644
index 0000000..5322d7e
--- /dev/null
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeName.java
@@ -0,0 +1,72 @@
+/****************************************************************
+ * 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.mailet;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+/** 
+ * Strong typing for attribute name, which represents the name of an attribute stored in a mail.
+ * 
+ * @since Mailet API v3.2
+ */
+public class AttributeName {
+    private final String name;
+
+    public static AttributeName of(String name) {
+        Preconditions.checkNotNull(name, "`name` is compulsory");
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "`name` should not be empty");
+
+        return new AttributeName(name);
+    }
+
+    private AttributeName(String name) {
+        this.name = name;
+    }
+
+    public String asString() {
+        return name;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof AttributeName) {
+            AttributeName that = (AttributeName) o;
+
+            return Objects.equals(this.name, that.name);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(name);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("name", name)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c97bc757/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
new file mode 100644
index 0000000..82e520d
--- /dev/null
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -0,0 +1,73 @@
+/****************************************************************
+ * 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.mailet;
+
+import java.util.Objects;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/** 
+ * Strong typing for attribute value, which represents the value of an attribute stored in a mail.
+ * 
+ * @since Mailet API v3.2
+ */
+public class AttributeValue<T> {
+
+    private final T value;
+    private final Serializer<T> serializer;
+
+    private AttributeValue(T value, Serializer<T> serializer) {
+        this.value = value;
+        this.serializer = serializer;
+    }
+
+    public T value() {
+        return value;
+    }
+
+    public JsonNode toJson() {
+        ObjectNode serialized = JsonNodeFactory.instance.objectNode();
+        serialized.put("serializer", serializer.getName());
+        serialized.replace("value", serializer.serialize(value));
+        return serialized;
+    }
+
+    public T getValue() {
+        return value;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof AttributeValue) {
+            AttributeValue<?> that = (AttributeValue<?>) o;
+
+            return Objects.equals(this.value, that.value)
+                && Objects.equals(this.serializer, that.serializer);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(value, serializer);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c97bc757/mailet/api/src/test/java/org/apache/mailet/AttributeNameTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeNameTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeNameTest.java
new file mode 100644
index 0000000..24a9394
--- /dev/null
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeNameTest.java
@@ -0,0 +1,53 @@
+/****************************************************************
+ * 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.mailet;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+class AttributeNameTest {
+
+    @Test
+    void shouldRespectBeanContract() {
+        EqualsVerifier.forClass(AttributeName.class).verify();
+    }
+
+    @Test
+    void ofShouldRejectNullValue() {
+        assertThatThrownBy(() -> AttributeName.of(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    void ofShouldRejectEmptyString() {
+        assertThatThrownBy(() -> AttributeName.of(""))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void asStringShouldReturnWrappedValue() {
+        String name = "name";
+        assertThat(AttributeName.of(name).asString()).isEqualTo(name);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c97bc757/mailet/api/src/test/java/org/apache/mailet/AttributeTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeTest.java
new file mode 100644
index 0000000..053f745
--- /dev/null
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeTest.java
@@ -0,0 +1,46 @@
+/****************************************************************
+ * 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.mailet;
+
+import static org.assertj.core.api.Assertions.assertThatNullPointerException;
+
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+class AttributeTest {
+
+    @Test
+    void shouldRespectBeanContract() {
+        EqualsVerifier.forClass(Attribute.class).verify();
+    }
+
+    @Test
+    void constructorShouldThrowOnNullName() {
+        assertThatNullPointerException()
+            .isThrownBy(() -> new Attribute(null, AttributeValue.of(1)));
+    }
+
+    @Test
+    void constructorShouldThrowOnNullValue() {
+        assertThatNullPointerException()
+            .isThrownBy(() -> new Attribute(AttributeName.of("name"), null));
+    }
+
+}


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


[05/17] james-project git commit: JAMES-2257 All MailKooks should use Optional sender

Posted by bt...@apache.org.
JAMES-2257 All MailKooks should use Optional sender


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

Branch: refs/heads/master
Commit: 93be34c312e63d71d7b0bab0c6d3083ff642ae44
Parents: 215f99d
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 10:56:16 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 10:56:32 2018 +0700

----------------------------------------------------------------------
 .../protocols/smtp/core/MailCmdHandler.java     |  6 ++--
 .../core/fastfail/ValidSenderDomainHandler.java |  6 ++--
 .../james/protocols/smtp/hook/SimpleHook.java   |  3 +-
 .../protocols/smtp/AbstractSMTPServerTest.java  |  5 +--
 .../fastfail/ValidSenderDomainHandlerTest.java  |  6 ++--
 .../james/smtpserver/fastfail/SPFHandler.java   | 11 ++++---
 .../apache/james/smtpserver/SPFHandlerTest.java | 33 ++++++++++----------
 7 files changed, 37 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/93be34c3/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java
index 806d730..5a18476 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java
@@ -31,6 +31,7 @@ import javax.inject.Inject;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.api.Request;
@@ -257,10 +258,7 @@ public class MailCmdHandler extends AbstractHookableCmdHandler<MailHook> {
     @Override
     protected HookResult callHook(MailHook rawHook, SMTPSession session, String parameters) {
         MailAddress sender = (MailAddress) session.getAttachment(SMTPSession.SENDER, State.Transaction);
-        if (sender.isNullSender()) {
-            sender = null;
-        }
-        return rawHook.doMail(session, sender);
+        return rawHook.doMail(session, MaybeSender.of(sender));
     }
 
     

http://git-wip-us.apache.org/repos/asf/james-project/blob/93be34c3/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandler.java
index db70aa5..efb0384 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandler.java
@@ -18,7 +18,7 @@
  ****************************************************************/
 package org.apache.james.protocols.smtp.core.fastfail;
 
-import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPRetCode;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.dsn.DSNStatus;
@@ -34,8 +34,8 @@ public abstract class ValidSenderDomainHandler implements MailHook {
 
 
     @Override
-    public HookResult doMail(SMTPSession session, MailAddress sender) {
-        if (sender != null  && !hasMXRecord(session,sender.getDomain().name())) {
+    public HookResult doMail(SMTPSession session, MaybeSender sender) {
+        if (!sender.isNullSender()  && !hasMXRecord(session,sender.get().getDomain().name())) {
             return HookResult.builder()
                 .hookReturnCode(HookReturnCode.deny())
                 .smtpReturnCode(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS)

http://git-wip-us.apache.org/repos/asf/james-project/blob/93be34c3/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java
index 2364253..f226e17 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java
@@ -22,6 +22,7 @@ package org.apache.james.protocols.smtp.hook;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.MailEnvelope;
 import org.apache.james.protocols.smtp.SMTPSession;
 
@@ -65,7 +66,7 @@ public class SimpleHook implements HeloHook, MailHook, RcptHook, MessageHook {
      * Return {@link HookResult} with {@link HookReturnCode#DECLINED}
      */
     @Override
-    public HookResult doMail(SMTPSession session, MailAddress sender) {
+    public HookResult doMail(SMTPSession session, MaybeSender sender) {
         return HookResult.DECLINED;
 
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/93be34c3/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
index faeca83..7bcb07f 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
@@ -37,6 +37,7 @@ import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.net.smtp.SMTPClient;
 import org.apache.commons.net.smtp.SMTPReply;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.protocols.api.Protocol;
 import org.apache.james.protocols.api.ProtocolServer;
@@ -593,7 +594,7 @@ public abstract class AbstractSMTPServerTest {
             }
 
             @Override
-            public HookResult doMail(SMTPSession session, MailAddress sender) {
+            public HookResult doMail(SMTPSession session, MaybeSender sender) {
                 return HookResult.DENY;
             }
         };
@@ -643,7 +644,7 @@ public abstract class AbstractSMTPServerTest {
             }
 
             @Override
-            public HookResult doMail(SMTPSession session, MailAddress sender) {
+            public HookResult doMail(SMTPSession session, MaybeSender sender) {
                 return HookResult.DENYSOFT;
             }
         };

http://git-wip-us.apache.org/repos/asf/james-project/blob/93be34c3/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java
index 82d8d4b..3d5da19 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookReturnCode;
@@ -106,7 +107,7 @@ public class ValidSenderDomainHandlerTest {
     @Test
     public void testNullSenderNotReject() {
         ValidSenderDomainHandler handler = createHandler();
-        HookReturnCode response = handler.doMail(setupMockedSession(null),null).getResult();
+        HookReturnCode response = handler.doMail(setupMockedSession(null), MaybeSender.nullSender()).getResult();
         
         assertThat(HookReturnCode.declined()).describedAs("Not blocked cause its a nullsender").isEqualTo(response);
     }
@@ -115,7 +116,8 @@ public class ValidSenderDomainHandlerTest {
     public void testInvalidSenderDomainReject() throws Exception {
         ValidSenderDomainHandler handler = createHandler();
         SMTPSession session = setupMockedSession(new MailAddress("invalid@invalid"));
-        HookReturnCode response = handler.doMail(session,(MailAddress) session.getAttachment(SMTPSession.SENDER, State.Transaction)).getResult();
+        MailAddress sender = (MailAddress) session.getAttachment(SMTPSession.SENDER, State.Transaction);
+        HookReturnCode response = handler.doMail(session, MaybeSender.of(sender)).getResult();
         
         assertThat(HookReturnCode.deny()).describedAs("Blocked cause we use reject action").isEqualTo(response);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/93be34c3/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
index 7a6e2b2..2c86b5f 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
@@ -23,6 +23,7 @@ import javax.inject.Inject;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.jspf.core.DNSService;
 import org.apache.james.jspf.core.exceptions.SPFErrorConstants;
 import org.apache.james.jspf.executor.SPFResult;
@@ -109,17 +110,17 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
      * @param session
      *            SMTP session object
      */
-    private void doSPFCheck(SMTPSession session, MailAddress sender) {
+    private void doSPFCheck(SMTPSession session, MaybeSender sender) {
         String heloEhlo = (String) session.getAttachment(SMTPSession.CURRENT_HELO_NAME, State.Transaction);
 
         // We have no Sender or HELO/EHLO yet return false
-        if (sender == null || heloEhlo == null) {
+        if (sender.isNullSender() || heloEhlo == null) {
             LOGGER.info("No Sender or HELO/EHLO present");
         } else {
 
             String ip = session.getRemoteAddress().getAddress().getHostAddress();
 
-            SPFResult result = spf.checkSPF(ip, sender.toString(), heloEhlo);
+            SPFResult result = spf.checkSPF(ip, sender.asString(), heloEhlo);
 
             String spfResult = result.getResult();
 
@@ -128,7 +129,7 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
             // Store the header
             session.setAttachment(SPF_HEADER, result.getHeaderText(), State.Transaction);
 
-            LOGGER.info("Result for {} - {} - {} = {}", ip, sender, heloEhlo, spfResult);
+            LOGGER.info("Result for {} - {} - {} = {}", ip, sender.asString(), heloEhlo, spfResult);
 
             // Check if we should block!
             if ((spfResult.equals(SPFErrorConstants.FAIL_CONV)) || (spfResult.equals(SPFErrorConstants.SOFTFAIL_CONV) && blockSoftFail) || (spfResult.equals(SPFErrorConstants.PERM_ERROR_CONV) && blockPermError)) {
@@ -169,7 +170,7 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
     }
 
     @Override
-    public HookResult doMail(SMTPSession session, MailAddress sender) {
+    public HookResult doMail(SMTPSession session, MaybeSender sender) {
         doSPFCheck(session, sender);
         return HookResult.DECLINED;
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/93be34c3/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
index 04481cd..d7221ff 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.List;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.jspf.core.DNSRequest;
 import org.apache.james.jspf.core.DNSService;
 import org.apache.james.jspf.core.exceptions.TimeoutException;
@@ -169,7 +170,7 @@ public class SPFHandlerTest {
 
     @Test
     public void testSPFpass() throws Exception {
-        MailAddress sender = new MailAddress("test@spf1.james.apache.org");
+        MaybeSender sender = MaybeSender.of(new MailAddress("test@spf1.james.apache.org"));
         MailAddress rcpt = new MailAddress("test@localhost");
         setupMockedSMTPSession("192.168.100.1", "spf1.james.apache.org");
         SPFHandler spf = new SPFHandler();
@@ -177,12 +178,12 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
     }
 
     @Test
     public void testSPFfail() throws Exception {
-        MailAddress sender = new MailAddress("test@spf2.james.apache.org");
+        MaybeSender sender = MaybeSender.of(new MailAddress("test@spf2.james.apache.org"));
         MailAddress rcpt = new MailAddress("test@localhost");
         setupMockedSMTPSession("192.168.100.1", "spf2.james.apache.org");
         SPFHandler spf = new SPFHandler();
@@ -190,12 +191,12 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("fail").isEqualTo(HookReturnCode.deny());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("fail").isEqualTo(HookReturnCode.deny());
     }
 
     @Test
     public void testSPFsoftFail() throws Exception {
-        MailAddress sender = new MailAddress("test@spf3.james.apache.org");
+        MaybeSender sender = MaybeSender.of(new MailAddress("test@spf3.james.apache.org"));
         MailAddress rcpt = new MailAddress("test@localhost");
         setupMockedSMTPSession("192.168.100.1", "spf3.james.apache.org");
         SPFHandler spf = new SPFHandler();
@@ -203,12 +204,12 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("softfail declined").isEqualTo(HookReturnCode.declined());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("softfail declined").isEqualTo(HookReturnCode.declined());
     }
 
     @Test
     public void testSPFsoftFailRejectEnabled() throws Exception {
-        MailAddress sender = new MailAddress("test@spf3.james.apache.org");
+        MaybeSender sender = MaybeSender.of(new MailAddress("test@spf3.james.apache.org"));
         MailAddress rcpt = new MailAddress("test@localhost");
 
         setupMockedSMTPSession("192.168.100.1", "spf3.james.apache.org");
@@ -219,12 +220,12 @@ public class SPFHandlerTest {
         spf.setBlockSoftFail(true);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("softfail reject").isEqualTo(HookReturnCode.deny());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("softfail reject").isEqualTo(HookReturnCode.deny());
     }
 
     @Test
     public void testSPFpermError() throws Exception {
-        MailAddress sender = new MailAddress("test@spf4.james.apache.org");
+        MaybeSender sender = MaybeSender.of(new MailAddress("test@spf4.james.apache.org"));
         MailAddress rcpt = new MailAddress("test@localhost");
 
         setupMockedSMTPSession("192.168.100.1", "spf4.james.apache.org");
@@ -235,12 +236,12 @@ public class SPFHandlerTest {
         spf.setBlockSoftFail(true);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("permerror reject").isEqualTo(HookReturnCode.deny());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("permerror reject").isEqualTo(HookReturnCode.deny());
     }
 
     @Test
     public void testSPFtempError() throws Exception {
-        MailAddress sender = new MailAddress("test@spf5.james.apache.org");
+        MaybeSender sender = MaybeSender.of(new MailAddress("test@spf5.james.apache.org"));
         MailAddress rcpt = new MailAddress("test@localhost");
 
         setupMockedSMTPSession("192.168.100.1", "spf5.james.apache.org");
@@ -250,12 +251,12 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("temperror denysoft").isEqualTo(HookReturnCode.denySoft());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("temperror denysoft").isEqualTo(HookReturnCode.denySoft());
     }
 
     @Test
     public void testSPFNoRecord() throws Exception {
-        MailAddress sender = new MailAddress("test@spf6.james.apache.org");
+        MaybeSender sender = MaybeSender.of(new MailAddress("test@spf6.james.apache.org"));
         MailAddress rcpt = new MailAddress("test@localhost");
 
         setupMockedSMTPSession("192.168.100.1", "spf6.james.apache.org");
@@ -264,12 +265,12 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
     }
 
     @Test
     public void testSPFpermErrorRejectDisabled() throws Exception {
-        MailAddress sender = new MailAddress("test@spf4.james.apache.org");
+        MaybeSender sender = MaybeSender.of(new MailAddress("test@spf4.james.apache.org"));
         MailAddress rcpt = new MailAddress("test@localhost");
         setupMockedSMTPSession("192.168.100.1", "spf4.james.apache.org");
         SPFHandler spf = new SPFHandler();
@@ -279,6 +280,6 @@ public class SPFHandlerTest {
         spf.setBlockPermError(false);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
     }
 }


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


[12/17] james-project git commit: JAMES-2578 Reuse FST Json configuration

Posted by bt...@apache.org.
JAMES-2578 Reuse FST Json configuration


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

Branch: refs/heads/master
Commit: 94df1ac4536a5004637c49a6e3038082e7f2489e
Parents: d66fa22
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 09:08:55 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:03:32 2018 +0700

----------------------------------------------------------------------
 mailet/api/src/main/java/org/apache/mailet/Serializer.java | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/94df1ac4/mailet/api/src/main/java/org/apache/mailet/Serializer.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
index e3eb47a..ffa0069 100644
--- a/mailet/api/src/main/java/org/apache/mailet/Serializer.java
+++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
@@ -442,8 +442,7 @@ public interface Serializer<T> {
 
         @Override
         public JsonNode serialize(Serializable object) {
-            FSTConfiguration conf = CONFIGURATION;
-            String json = conf.asJsonString(object);
+            String json = CONFIGURATION.asJsonString(object);
             try {
                 return new ObjectMapper().reader().readTree(json);
             } catch (IOException e) {
@@ -453,9 +452,8 @@ public interface Serializer<T> {
 
         @Override
         public Optional<Serializable> deserialize(JsonNode json) {
-            FSTConfiguration conf = FSTConfiguration.createJsonConfiguration();
             try {
-                return Optional.of((Serializable) conf.asObject(new ObjectMapper().writer().writeValueAsBytes(json)));
+                return Optional.of((Serializable) CONFIGURATION.asObject(new ObjectMapper().writer().writeValueAsBytes(json)));
             } catch (JsonProcessingException e) {
                 throw new UncheckedIOException(e);
             }


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


[10/17] james-project git commit: JAMES-2578 Strengthen ArbitrarySerializable types

Posted by bt...@apache.org.
JAMES-2578 Strengthen ArbitrarySerializable types


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

Branch: refs/heads/master
Commit: dbee6f7e8a8487918a0f37ae08147180aed8c23c
Parents: 46ba928
Author: Gautier DI FOLCO <gd...@linagora.com>
Authored: Mon Oct 29 14:18:15 2018 +0100
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:02:43 2018 +0700

----------------------------------------------------------------------
 .../apache/mailet/ArbitrarySerializable.java    | 16 +++++++-------
 .../java/org/apache/mailet/AttributeValue.java  |  4 ++--
 .../main/java/org/apache/mailet/Serializer.java | 22 +++++++++-----------
 .../org/apache/mailet/AttributeValueTest.java   | 14 ++++++-------
 4 files changed, 27 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/dbee6f7e/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java b/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
index 2bab770..d4ab5ad 100644
--- a/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
+++ b/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
@@ -21,17 +21,17 @@ package org.apache.mailet;
 
 import java.util.Optional;
 
-public interface ArbitrarySerializable {
-    public class Serializable {
+public interface ArbitrarySerializable<T> {
+    public class Serializable<U> {
         private final AttributeValue<?> value;
-        private final Class<? extends Factory> factory;
+        private final Class<? extends Factory<U>> factory;
 
-        public Serializable(AttributeValue<?> value, Class<? extends Factory> factory) {
+        public Serializable(AttributeValue<?> value, Class<? extends Factory<U>> factory) {
             this.value = value;
             this.factory = factory;
         }
 
-        public Class<? extends Factory> getFactory() {
+        public Class<? extends Factory<U>> getFactory() {
             return factory;
         }
 
@@ -40,9 +40,9 @@ public interface ArbitrarySerializable {
         }
     }
 
-    public interface Factory {
-        Optional<ArbitrarySerializable> deserialize(Serializable serializable);
+    public interface Factory<U> {
+        Optional<U> deserialize(Serializable<U> serializable);
     }
     
-    Serializable serialize();
+    Serializable<T> serialize();
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/dbee6f7e/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
index fd997c4..4a548b3 100644
--- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -69,8 +69,8 @@ public class AttributeValue<T> {
         return new AttributeValue<>(value, Serializer.DOUBLE_SERIALIZER);
     }
 
-    public static AttributeValue<ArbitrarySerializable> of(ArbitrarySerializable value) {
-        return new AttributeValue<>(value, Serializer.ARIBITRARY_SERIALIZABLE_SERIALIZER);
+    public static <T extends ArbitrarySerializable<T>> AttributeValue<T> of(T value) {
+        return new AttributeValue<>(value, new Serializer.ArbitrarySerializableSerializer<>());
     }
 
     public static AttributeValue<URL> of(URL value) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/dbee6f7e/mailet/api/src/main/java/org/apache/mailet/Serializer.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
index d71a01c..514b464 100644
--- a/mailet/api/src/main/java/org/apache/mailet/Serializer.java
+++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
@@ -78,7 +78,7 @@ public interface Serializer<T> {
                     LONG_SERIALIZER,
                     FLOAT_SERIALIZER,
                     DOUBLE_SERIALIZER,
-                    ARIBITRARY_SERIALIZABLE_SERIALIZER,
+                    new Serializer.ArbitrarySerializableSerializer(),
                     URL_SERIALIZER,
                     new CollectionSerializer<>(),
                     new MapSerializer<>(),
@@ -259,12 +259,12 @@ public interface Serializer<T> {
 
     Serializer<Double> DOUBLE_SERIALIZER = new DoubleSerializer();
 
-    class ArbitrarySerializableSerializer implements Serializer<ArbitrarySerializable> {
+    class ArbitrarySerializableSerializer<T extends ArbitrarySerializable<T>> implements Serializer<T> {
         private static final Logger LOGGER = LoggerFactory.getLogger(ArbitrarySerializableSerializer.class);
 
         @Override
-        public JsonNode serialize(ArbitrarySerializable serializable) {
-            ArbitrarySerializable.Serializable serialized = serializable.serialize();
+        public JsonNode serialize(T serializable) {
+            ArbitrarySerializable.Serializable<T> serialized = serializable.serialize();
             ObjectNode serializedJson = JsonNodeFactory.instance.objectNode();
             serializedJson.put("factory", serialized.getFactory().getName());
             serializedJson.replace("value", serialized.getValue().toJson());
@@ -272,14 +272,14 @@ public interface Serializer<T> {
         }
 
         @Override
-        public Optional<ArbitrarySerializable> deserialize(JsonNode json) {
+        public Optional<T> deserialize(JsonNode json) {
             return Optional.of(json)
                     .filter(ObjectNode.class::isInstance)
                     .map(ObjectNode.class::cast)
                     .flatMap(this::instantiate);
         }
 
-        public Optional<ArbitrarySerializable> instantiate(ObjectNode fields) {
+        public Optional<T> instantiate(ObjectNode fields) {
             return Optional.ofNullable(fields.get("factory"))
                 .flatMap(serializer ->
                     Optional.ofNullable(fields.get("value"))
@@ -287,15 +287,15 @@ public interface Serializer<T> {
         }
 
         @SuppressWarnings("unchecked")
-        private Optional<ArbitrarySerializable> deserialize(String serializer, AttributeValue<?> value) {
+        private Optional<T> deserialize(String serializer, AttributeValue<?> value) {
             try {
                 Class<?> factoryClass = Class.forName(serializer);
                 if (ArbitrarySerializable.Factory.class.isAssignableFrom(factoryClass)) {
-                    ArbitrarySerializable.Factory factory = (ArbitrarySerializable.Factory) factoryClass.newInstance();
-                    return factory.deserialize(new ArbitrarySerializable.Serializable(value, (Class<ArbitrarySerializable.Factory>) factoryClass));
+                    ArbitrarySerializable.Factory<T> factory = (ArbitrarySerializable.Factory<T>) factoryClass.newInstance();
+                    return factory.deserialize(new ArbitrarySerializable.Serializable<>(value, (Class<ArbitrarySerializable.Factory<T>>) factoryClass));
                 }
             } catch (Exception e) {
-                LOGGER.error("Error while deserializing", e);
+                LOGGER.error("Error while deserializing using serializer {} and value {}", serializer, value, e);
             }
 
             return Optional.empty();
@@ -312,8 +312,6 @@ public interface Serializer<T> {
         }
     }
 
-    Serializer<ArbitrarySerializable> ARIBITRARY_SERIALIZABLE_SERIALIZER = new ArbitrarySerializableSerializer();
-
     class UrlSerializer implements Serializer<URL> {
         @Override
         public JsonNode serialize(URL object) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/dbee6f7e/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
index f741d05..45cfede 100644
--- a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
@@ -311,7 +311,7 @@ class AttributeValueTest {
     class QueueSerializableTest {
         @Test
         void queueSerializableShouldBeSerializedAndBack() {
-            AttributeValue<ArbitrarySerializable> expected = AttributeValue.of(new TestArbitrarySerializable(42));
+            AttributeValue<TestArbitrarySerializable> expected = AttributeValue.of(new TestArbitrarySerializable(42));
 
             JsonNode json = expected.toJson();
             AttributeValue<?> actual = AttributeValue.fromJson(json);
@@ -322,7 +322,7 @@ class AttributeValueTest {
 
         @Test
         void fromJsonStringShouldReturnQueueSerializableAttributeValueWhenQueueSerializable() throws Exception {
-            AttributeValue<ArbitrarySerializable> expected = AttributeValue.of(new TestArbitrarySerializable(42));
+            AttributeValue<TestArbitrarySerializable> expected = AttributeValue.of(new TestArbitrarySerializable(42));
 
             AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"ArbitrarySerializableSerializer\",\"value\":{\"factory\":\"org.apache.mailet.AttributeValueTest$TestArbitrarySerializable$Factory\",\"value\":{\"serializer\":\"IntSerializer\",\"value\":42}}}");
 
@@ -515,10 +515,10 @@ class AttributeValueTest {
             .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"MapSerializer\"}"));
     }
 
-    private static class TestArbitrarySerializable implements ArbitrarySerializable {
-        public static class Factory implements ArbitrarySerializable.Factory {
+    private static class TestArbitrarySerializable implements ArbitrarySerializable<TestArbitrarySerializable> {
+        public static class Factory implements ArbitrarySerializable.Factory<TestArbitrarySerializable> {
             @Override
-            public Optional<ArbitrarySerializable> deserialize(Serializable serializable) {
+            public Optional<TestArbitrarySerializable> deserialize(Serializable<TestArbitrarySerializable> serializable) {
                 return Optional.of(serializable.getValue().value())
                         .filter(Integer.class::isInstance)
                         .map(Integer.class::cast)
@@ -533,8 +533,8 @@ class AttributeValueTest {
         }
 
         @Override
-        public Serializable serialize() {
-            return new Serializable(AttributeValue.of(value), Factory.class);
+        public Serializable<TestArbitrarySerializable> serialize() {
+            return new Serializable<>(AttributeValue.of(value), Factory.class);
         }
 
         @Override


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


[17/17] james-project git commit: JAMES-2578 Add MessageId serialization

Posted by bt...@apache.org.
JAMES-2578 Add MessageId serialization


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

Branch: refs/heads/master
Commit: 38b3d7a598cb684e8090e24d3542cda612463d92
Parents: ccd8226
Author: Gautier DI FOLCO <gd...@linagora.com>
Authored: Tue Oct 30 17:03:53 2018 +0100
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:04:22 2018 +0700

----------------------------------------------------------------------
 .../james/mailbox/model/MessageIdDto.java       | 66 ++++++++++++++++++
 .../james/mailbox/model/MessageIdDtoTest.java   | 70 ++++++++++++++++++++
 mailet/api/pom.xml                              | 10 +++
 .../java/org/apache/mailet/AttributeValue.java  | 10 +++
 .../main/java/org/apache/mailet/Serializer.java | 30 +++++++++
 .../org/apache/mailet/AttributeValueTest.java   | 37 +++++++++++
 6 files changed, 223 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/38b3d7a5/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageIdDto.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageIdDto.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageIdDto.java
new file mode 100644
index 0000000..275a52e
--- /dev/null
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageIdDto.java
@@ -0,0 +1,66 @@
+/****************************************************************
+ * 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.mailbox.model;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+public class MessageIdDto {
+    private final String messageId;
+
+    public MessageIdDto(String messageId) {
+        this.messageId = messageId;
+    }
+
+    public MessageIdDto(MessageId messageId) {
+        this.messageId = messageId.serialize();
+    }
+
+    public MessageId instantiate(MessageId.Factory factory) {
+        return factory.fromString(messageId);
+    }
+
+    public String asString() {
+        return messageId;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof MessageIdDto) {
+            MessageIdDto that = (MessageIdDto) o;
+
+            return Objects.equals(this.messageId, that.messageId);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(messageId);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("messageId", messageId)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/38b3d7a5/mailbox/api/src/test/java/org/apache/james/mailbox/model/MessageIdDtoTest.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MessageIdDtoTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MessageIdDtoTest.java
new file mode 100644
index 0000000..0c7e74d
--- /dev/null
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MessageIdDtoTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.mailbox.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class MessageIdDtoTest {
+
+    private static final TestMessageId.Factory factory = new TestMessageId.Factory();
+    private static final Long SAMPLE_ID_VALUE = 42L;
+    private static final String SAMPLE_ID_STRING = SAMPLE_ID_VALUE.toString();
+    private static final TestMessageId SAMPLE_ID = TestMessageId.of(SAMPLE_ID_VALUE);
+
+    @Test
+    public void shouldRespectJavaBeanContract() {
+        EqualsVerifier.forClass(MessageIdDto.class).verify();
+    }
+
+    @Test
+    public void shouldAcceptStringAndGiveItBack() {
+        assertThat(new MessageIdDto(SAMPLE_ID_STRING).asString())
+            .isEqualTo(SAMPLE_ID_STRING);
+    }
+
+    @Test
+    public void shouldAcceptMessageIdAndGiveTheRightString() {
+        assertThat(new MessageIdDto(SAMPLE_ID).asString())
+            .isEqualTo(SAMPLE_ID_STRING);
+    }
+
+    @Test
+    public void shouldAcceptMessageIdAndGiveItBack() {
+        assertThat(new MessageIdDto(SAMPLE_ID).instantiate(factory))
+            .isEqualTo(SAMPLE_ID);
+    }
+
+    @Test
+    public void shouldAcceptStringAndGiveAnInstantiatedMessageId() {
+        assertThat(new MessageIdDto(SAMPLE_ID_STRING).instantiate(factory))
+            .isEqualTo(SAMPLE_ID);
+    }
+
+    @Test
+    public void shouldThrowAnExceptionOnWronglyFormattedString() {
+        MessageIdDto messageIdDto = new MessageIdDto("Definitively not a number");
+        assertThatThrownBy(() -> messageIdDto.instantiate(factory))
+            .isInstanceOf(Exception.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/38b3d7a5/mailet/api/pom.xml
----------------------------------------------------------------------
diff --git a/mailet/api/pom.xml b/mailet/api/pom.xml
index 5b5d599..75be1f1 100644
--- a/mailet/api/pom.xml
+++ b/mailet/api/pom.xml
@@ -38,6 +38,16 @@
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-core</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/38b3d7a5/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
index 6933bf8..d550d84 100644
--- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -27,6 +27,8 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
+import org.apache.james.mailbox.model.MessageIdDto;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -76,6 +78,11 @@ public class AttributeValue<T> {
         return new AttributeValue<>(value, Serializer.DOUBLE_SERIALIZER);
     }
 
+    public static AttributeValue<MessageIdDto> of(MessageIdDto value) {
+        Preconditions.checkNotNull(value, "value should not be null");
+        return new AttributeValue<>(value, Serializer.MESSAGE_ID_DTO_SERIALIZER);
+    }
+
     public static <T extends ArbitrarySerializable<T>> AttributeValue<T> of(T value) {
         Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, new Serializer.ArbitrarySerializableSerializer<>());
@@ -136,6 +143,9 @@ public class AttributeValue<T> {
         if (value instanceof Map<?,?>) {
             return of(((Map<String, AttributeValue<?>>) value));
         }
+        if (value instanceof MessageIdDto) {
+            return of((MessageIdDto) value);
+        }
         if (value instanceof ArbitrarySerializable) {
             return of((ArbitrarySerializable) value);
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/38b3d7a5/mailet/api/src/main/java/org/apache/mailet/Serializer.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
index 016472a..ba73395 100644
--- a/mailet/api/src/main/java/org/apache/mailet/Serializer.java
+++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
@@ -32,6 +32,7 @@ import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
+import org.apache.james.mailbox.model.MessageIdDto;
 import org.apache.james.util.streams.Iterators;
 import org.nustaq.serialization.FSTConfiguration;
 import org.slf4j.Logger;
@@ -78,6 +79,7 @@ public interface Serializer<T> {
                     LONG_SERIALIZER,
                     FLOAT_SERIALIZER,
                     DOUBLE_SERIALIZER,
+                    MESSAGE_ID_DTO_SERIALIZER,
                     new Serializer.ArbitrarySerializableSerializer(),
                     URL_SERIALIZER,
                     new CollectionSerializer<>(),
@@ -264,6 +266,34 @@ public interface Serializer<T> {
 
     Serializer<Double> DOUBLE_SERIALIZER = new DoubleSerializer();
 
+    class MessageIdDtoSerializer implements Serializer<MessageIdDto> {
+
+        @Override
+        public JsonNode serialize(MessageIdDto serializable) {
+            return STRING_SERIALIZER
+                    .serialize(serializable.asString());
+        }
+
+        @Override
+        public Optional<MessageIdDto> deserialize(JsonNode json) {
+            return STRING_SERIALIZER
+                    .deserialize(json)
+                    .map(MessageIdDto::new);
+        }
+
+        @Override
+        public String getName() {
+            return "MessageIdDtoSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<MessageIdDto> MESSAGE_ID_DTO_SERIALIZER = new MessageIdDtoSerializer();
+
     class ArbitrarySerializableSerializer<T extends ArbitrarySerializable<T>> implements Serializer<T> {
         private static final Logger LOGGER = LoggerFactory.getLogger(ArbitrarySerializableSerializer.class);
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/38b3d7a5/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
index 3ce1d3f..c8bbc86 100644
--- a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
@@ -30,6 +30,9 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
+import org.apache.james.mailbox.model.MessageIdDto;
+import org.apache.james.mailbox.model.TestMessageId;
+
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
@@ -389,6 +392,40 @@ class AttributeValueTest {
     }
 
     @Nested
+    class MessageIdDtoSerialization {
+        @Test
+        void messageIdShouldBeSerializedAndBack() {
+            AttributeValue<MessageIdDto> expected = AttributeValue.of(new MessageIdDto(TestMessageId.of(42)));
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void nullMessageIdDtoShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((MessageIdDto) null));
+        }
+
+        @Test
+        void fromJsonStringShouldReturnMessageIdAttributeValue() throws Exception {
+            AttributeValue<MessageIdDto> expected = AttributeValue.of(new MessageIdDto(TestMessageId.of(42)));
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"MessageIdDtoSerializer\",\"value\":\"42\"}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"MessageIdDtoSerializer\",\"value\": {}}"));
+        }
+    }
+
+    @Nested
     class ListSerialization {
         @Test
         void nullStringListShouldThrowAnException() {


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


[04/17] james-project git commit: JAMES-2557 Review mail envelope API

Posted by bt...@apache.org.
JAMES-2557 Review mail envelope API


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

Branch: refs/heads/master
Commit: 3d83c3dd1676545a47d661d88721c5dc7133807c
Parents: 3f68078
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 11:17:22 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 10:56:32 2018 +0700

----------------------------------------------------------------------
 .../james/protocols/smtp/MailEnvelope.java      | 27 ++++++++++++++++++--
 .../james/protocols/smtp/MailEnvelopeImpl.java  |  7 ++---
 .../protocols/smtp/core/DataCmdHandler.java     |  6 +++--
 .../protocols/smtp/AbstractSMTPServerTest.java  |  2 +-
 .../DataLineJamesMessageHookHandler.java        |  6 ++---
 5 files changed, 37 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/3d83c3dd/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelope.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelope.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelope.java
index f85d861..3cba413 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelope.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelope.java
@@ -25,6 +25,7 @@ import java.io.OutputStream;
 import java.util.List;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 
 /**
  * The MailEnvelope of a SMTP-Transaction
@@ -51,10 +52,32 @@ public interface MailEnvelope {
     /**
      * Return the sender of the mail which was supplied int the MAIL FROM:
      * command. If its a "null" sender, null will get returned
-     * 
+     *
+     * @deprecated @see {@link #getMaybeSender()}
+     *
+     * Note that SMTP null sender ( "&lt;&gt;" ) needs to be implicitly handled by the caller under the form of 'null' or
+     * {@link MailAddress#nullSender()}. Replacement method adds type safety on this operation.
+     *
      * @return sender
      */
-    MailAddress getSender();
+    @Deprecated
+    default MailAddress getSender() {
+        return getMaybeSender().asOptional().orElse(MailAddress.nullSender());
+    }
+
+    /**
+     * Returns the sender of the message, as specified by the SMTP "MAIL FROM" command,
+     * or internally defined.
+     *
+     * 'null' or {@link MailAddress#nullSender()} are handled with {@link MaybeSender}.
+     *
+     * @since Mailet API v3.2.0
+     * @return the sender of this message wrapped in an optional
+     */
+    @SuppressWarnings("deprecated")
+    default MaybeSender getMaybeSender() {
+        return MaybeSender.of(getSender());
+    }
 
     /**
      * Return the OutputStream of the message

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d83c3dd/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelopeImpl.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelopeImpl.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelopeImpl.java
index 59dbe97..2f51d58 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelopeImpl.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/MailEnvelopeImpl.java
@@ -27,6 +27,7 @@ import java.io.OutputStream;
 import java.util.List;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 
 /**
  * MailEnvelope implementation which stores everything in memory
@@ -37,7 +38,7 @@ public class MailEnvelopeImpl implements MailEnvelope {
 
     private List<MailAddress> recipients;
 
-    private MailAddress sender;
+    private MaybeSender sender;
 
     private ByteArrayOutputStream outputStream;
 
@@ -55,7 +56,7 @@ public class MailEnvelopeImpl implements MailEnvelope {
     }
 
     @Override
-    public MailAddress getSender() {
+    public MaybeSender getMaybeSender() {
         return sender;
     }
 
@@ -73,7 +74,7 @@ public class MailEnvelopeImpl implements MailEnvelope {
      * 
      * @param sender
      */
-    public void setSender(MailAddress sender) {
+    public void setSender(MaybeSender sender) {
         this.sender = sender;
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d83c3dd/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
index 0a0e594..906da01 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
@@ -31,6 +31,7 @@ import javax.inject.Inject;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.metrics.api.TimeMetric;
 import org.apache.james.protocols.api.ProtocolSession;
@@ -171,14 +172,15 @@ public class DataCmdHandler implements CommandHandler<SMTPSession>, ExtensibleHa
      */
     @SuppressWarnings("unchecked")
     protected Response doDATA(SMTPSession session, String argument) {
-        MailEnvelope env = createEnvelope(session, (MailAddress) session.getAttachment(SMTPSession.SENDER,ProtocolSession.State.Transaction), new ArrayList<>((Collection<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, ProtocolSession.State.Transaction)));
+        MailAddress sender = (MailAddress) session.getAttachment(SMTPSession.SENDER, ProtocolSession.State.Transaction);
+        MailEnvelope env = createEnvelope(session, MaybeSender.of(sender), new ArrayList<>((Collection<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, ProtocolSession.State.Transaction)));
         session.setAttachment(MAILENV, env,ProtocolSession.State.Transaction);
         session.pushLineHandler(lineHandler);
         
         return DATA_READY;
     }
     
-    protected MailEnvelope createEnvelope(SMTPSession session, MailAddress sender, List<MailAddress> recipients) {
+    protected MailEnvelope createEnvelope(SMTPSession session, MaybeSender sender, List<MailAddress> recipients) {
         MailEnvelopeImpl env = new MailEnvelopeImpl();
         env.setRecipients(recipients);
         env.setSender(sender);

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d83c3dd/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
index bf3f756..74aa841 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
@@ -1115,7 +1115,7 @@ public abstract class AbstractSMTPServerTest {
     }
     
     protected static void checkEnvelope(MailEnvelope env, String sender, List<String> recipients, String msg) throws IOException {
-        assertThat(env.getSender().toString()).isEqualTo(sender);
+        assertThat(env.getMaybeSender().asString()).isEqualTo(sender);
 
         List<MailAddress> envRecipients = env.getRecipients();
         assertThat(envRecipients.size()).isEqualTo(recipients.size());

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d83c3dd/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java
index a051e7e..b90d603 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java
@@ -31,6 +31,7 @@ import javax.mail.MessagingException;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.lifecycle.api.LifecycleUtil;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.api.Response;
@@ -259,10 +260,9 @@ public class DataLineJamesMessageHookHandler implements DataLineFilter, Extensib
             return ImmutableList.copyOf(mail.getRecipients());
         }
 
-        @SuppressWarnings("deprecated") // This will be handled in a followup pull request See JAMES-2557
         @Override
-        public MailAddress getSender() {
-            return mail.getSender();
+        public MaybeSender getMaybeSender() {
+            return mail.getMaybeSender();
         }
 
         @Override


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


[13/17] james-project git commit: JAMES-2578 Require JSON object node never to be null

Posted by bt...@apache.org.
JAMES-2578 Require JSON object node never to be null


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

Branch: refs/heads/master
Commit: 1ccae9018a115ccec46a3dc0d2d000450d7ef6c6
Parents: 77f4ecb
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 14:25:58 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:03:38 2018 +0700

----------------------------------------------------------------------
 .../api/src/main/java/org/apache/mailet/AttributeValue.java | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/1ccae901/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
index 4ae6952..638dd34 100644
--- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -176,9 +176,12 @@ public class AttributeValue<T> {
     }
 
     public static Optional<?> deserialize(ObjectNode fields) {
-        return Optional.ofNullable(fields.get("serializer"))
-                .flatMap(serializer ->  Optional.ofNullable(fields.get("value"))
-                        .flatMap(value -> findSerializerAndDeserialize(serializer, value)));
+        Preconditions.checkNotNull(fields);
+        Optional<JsonNode> maybeSerializer = Optional.ofNullable(fields.get("serializer"));
+        Optional<JsonNode> maybeValue = Optional.ofNullable(fields.get("value"));
+
+        return maybeSerializer.flatMap(serializer -> maybeValue
+            .flatMap(value -> findSerializerAndDeserialize(serializer, value)));
     }
 
     public static Optional<?> findSerializerAndDeserialize(JsonNode serializer, JsonNode value) {


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


[08/17] james-project git commit: JAMES-2578 Add Serializers

Posted by bt...@apache.org.
JAMES-2578 Add Serializers


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

Branch: refs/heads/master
Commit: 46ba928f398e69c14fd5a6980ba80f6ac8de9e2b
Parents: c97bc75
Author: Gautier DI FOLCO <gd...@linagora.com>
Authored: Fri Oct 26 11:53:08 2018 +0200
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:02:43 2018 +0700

----------------------------------------------------------------------
 .../apache/mailet/ArbitrarySerializable.java    |  48 ++
 .../java/org/apache/mailet/AttributeValue.java  | 146 +++++
 .../main/java/org/apache/mailet/Serializer.java | 445 +++++++++++++++
 .../org/apache/mailet/AttributeValueTest.java   | 555 +++++++++++++++++++
 4 files changed, 1194 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/46ba928f/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java b/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
new file mode 100644
index 0000000..2bab770
--- /dev/null
+++ b/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
@@ -0,0 +1,48 @@
+/****************************************************************
+ * 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.mailet;
+
+import java.util.Optional;
+
+public interface ArbitrarySerializable {
+    public class Serializable {
+        private final AttributeValue<?> value;
+        private final Class<? extends Factory> factory;
+
+        public Serializable(AttributeValue<?> value, Class<? extends Factory> factory) {
+            this.value = value;
+            this.factory = factory;
+        }
+
+        public Class<? extends Factory> getFactory() {
+            return factory;
+        }
+
+        public AttributeValue<?> getValue() {
+            return value;
+        }
+    }
+
+    public interface Factory {
+        Optional<ArbitrarySerializable> deserialize(Serializable serializable);
+    }
+    
+    Serializable serialize();
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/46ba928f/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
index 82e520d..fd997c4 100644
--- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -19,11 +19,23 @@
 
 package org.apache.mailet;
 
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
 
 /** 
  * Strong typing for attribute value, which represents the value of an attribute stored in a mail.
@@ -31,6 +43,127 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
  * @since Mailet API v3.2
  */
 public class AttributeValue<T> {
+    private static final Logger LOGGER = LoggerFactory.getLogger(AttributeValue.class);
+
+    public static AttributeValue<Boolean> of(Boolean value) {
+        return new AttributeValue<>(value, Serializer.BOOLEAN_SERIALIZER);
+    }
+
+    public static AttributeValue<String> of(String value) {
+        return new AttributeValue<>(value, Serializer.STRING_SERIALIZER);
+    }
+
+    public static AttributeValue<Integer> of(Integer value) {
+        return new AttributeValue<>(value, Serializer.INT_SERIALIZER);
+    }
+
+    public static AttributeValue<Long> of(Long value) {
+        return new AttributeValue<>(value, Serializer.LONG_SERIALIZER);
+    }
+
+    public static AttributeValue<Float> of(Float value) {
+        return new AttributeValue<>(value, Serializer.FLOAT_SERIALIZER);
+    }
+
+    public static AttributeValue<Double> of(Double value) {
+        return new AttributeValue<>(value, Serializer.DOUBLE_SERIALIZER);
+    }
+
+    public static AttributeValue<ArbitrarySerializable> of(ArbitrarySerializable value) {
+        return new AttributeValue<>(value, Serializer.ARIBITRARY_SERIALIZABLE_SERIALIZER);
+    }
+
+    public static AttributeValue<URL> of(URL value) {
+        return new AttributeValue<>(value, Serializer.URL_SERIALIZER);
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static AttributeValue<Collection<AttributeValue<?>>> of(Collection<AttributeValue<?>> value) {
+        return new AttributeValue<>(value, new Serializer.CollectionSerializer());
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static AttributeValue<Map<String, AttributeValue<?>>> of(Map<String, AttributeValue<?>> value) {
+        return new AttributeValue<>(value, new Serializer.MapSerializer());
+    }
+
+    public static AttributeValue<Serializable> ofSerializable(Serializable value) {
+        return new AttributeValue<>(value, new Serializer.FSTSerializer());
+    }
+
+    @SuppressWarnings("unchecked")
+    public static AttributeValue<?> ofAny(Object value) {
+        if (value instanceof Boolean) {
+            return of((Boolean) value);
+        }
+        if (value instanceof String) {
+            return of((String) value);
+        }
+        if (value instanceof Integer) {
+            return of((Integer) value);
+        }
+        if (value instanceof Long) {
+            return of((Long) value);
+        }
+        if (value instanceof Float) {
+            return of((Float) value);
+        }
+        if (value instanceof Double) {
+            return of((Double) value);
+        }
+        if (value instanceof Collection<?>) {
+            return of(((Collection<AttributeValue<?>>) value));
+        }
+        if (value instanceof Map<?,?>) {
+            return of(((Map<String, AttributeValue<?>>) value));
+        }
+        if (value instanceof ArbitrarySerializable) {
+            return of((ArbitrarySerializable) value);
+        }
+        if (value instanceof URL) {
+            return of((URL) value);
+        }
+        if (value instanceof Serializable) {
+            return ofSerializable((Serializable) value);
+        }
+        throw new IllegalArgumentException(value.getClass().toString() + " should at least be Serializable");
+    }
+
+    public static AttributeValue<?> fromJsonString(String json) throws IOException {
+        ObjectMapper objectMapper = new ObjectMapper();
+        JsonNode tree = objectMapper.readTree(json);
+        return fromJson(tree);
+    }
+
+    public static Optional<AttributeValue<?>> optionalFromJsonString(String json) {
+        try {
+            return Optional.of(fromJsonString(json));
+        } catch (IOException e) {
+            LOGGER.error("Error while deserializing '" + json + "'", e);
+            return Optional.empty();
+        }
+    }
+
+    @VisibleForTesting
+    static AttributeValue<?> fromJson(JsonNode input) {
+        return Optional.ofNullable(input)
+                .filter(ObjectNode.class::isInstance)
+                .map(ObjectNode.class::cast)
+                .flatMap(AttributeValue::deserialize)
+                .map(AttributeValue::ofAny)
+                .orElseThrow(() -> new IllegalStateException("unable to deserialize " + input.toString()));
+    }
+
+    public static Optional<?> deserialize(ObjectNode fields) {
+        return Optional.ofNullable(fields.get("serializer"))
+                .flatMap(serializer ->  Optional.ofNullable(fields.get("value"))
+                        .flatMap(value -> findSerializerAndDeserialize(serializer, value)));
+    }
+
+    public static Optional<?> findSerializerAndDeserialize(JsonNode serializer, JsonNode value) {
+        return Serializer.Registry.find(serializer.asText())
+                .flatMap(s -> s.deserialize(value));
+    }
 
     private final T value;
     private final Serializer<T> serializer;
@@ -44,6 +177,11 @@ public class AttributeValue<T> {
         return value;
     }
 
+    //FIXME : poor performance
+    public AttributeValue<T> duplicate() {
+        return (AttributeValue<T>) fromJson(toJson());
+    }
+
     public JsonNode toJson() {
         ObjectNode serialized = JsonNodeFactory.instance.objectNode();
         serialized.put("serializer", serializer.getName());
@@ -70,4 +208,12 @@ public class AttributeValue<T> {
     public final int hashCode() {
         return Objects.hash(value, serializer);
     }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("value", value)
+            .add("serializer", serializer.getName())
+            .toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/46ba928f/mailet/api/src/main/java/org/apache/mailet/Serializer.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
new file mode 100644
index 0000000..d71a01c
--- /dev/null
+++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
@@ -0,0 +1,445 @@
+/****************************************************************
+ * 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.mailet;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.UncheckedIOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.apache.james.util.streams.Iterators;
+import org.nustaq.serialization.FSTConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.BooleanNode;
+import com.fasterxml.jackson.databind.node.DoubleNode;
+import com.fasterxml.jackson.databind.node.FloatNode;
+import com.fasterxml.jackson.databind.node.IntNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.LongNode;
+import com.fasterxml.jackson.databind.node.NumericNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/** 
+ * Controlled Json serialization/deserialization
+ * 
+ * @since Mailet API v3.2
+ */
+public interface Serializer<T> {
+    JsonNode serialize(T object);
+
+    Optional<T> deserialize(JsonNode json);
+
+    String getName();
+
+    class Registry {
+
+        private static ImmutableMap<String, Serializer<?>> serializers;
+
+        static {
+            serializers = Stream
+                .<Serializer<?>>of(
+                    BOOLEAN_SERIALIZER,
+                    STRING_SERIALIZER,
+                    INT_SERIALIZER,
+                    LONG_SERIALIZER,
+                    FLOAT_SERIALIZER,
+                    DOUBLE_SERIALIZER,
+                    ARIBITRARY_SERIALIZABLE_SERIALIZER,
+                    URL_SERIALIZER,
+                    new CollectionSerializer<>(),
+                    new MapSerializer<>(),
+                    new FSTSerializer())
+                .collect(ImmutableMap.toImmutableMap(Serializer::getName, Function.identity()));
+        }
+
+        static Optional<Serializer<?>> find(String name) {
+            return Optional.ofNullable(serializers.get(name));
+        }
+    }
+
+    class BooleanSerializer implements Serializer<Boolean> {
+        @Override
+        public JsonNode serialize(Boolean object) {
+            return BooleanNode.valueOf(object);
+        }
+
+        @Override
+        public Optional<Boolean> deserialize(JsonNode json) {
+            if (json instanceof BooleanNode) {
+                return Optional.of(json.asBoolean());
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "BooleanSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<Boolean> BOOLEAN_SERIALIZER = new BooleanSerializer();
+
+    class StringSerializer implements Serializer<String> {
+        @Override
+        public JsonNode serialize(String object) {
+            return TextNode.valueOf(object);
+        }
+
+        @Override
+        public Optional<String> deserialize(JsonNode json) {
+            if (json instanceof TextNode) {
+                return Optional.of(json.asText());
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "StringSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<String> STRING_SERIALIZER = new StringSerializer();
+
+    class IntSerializer implements Serializer<Integer> {
+        @Override
+        public JsonNode serialize(Integer object) {
+            return IntNode.valueOf(object);
+        }
+
+        @Override
+        public Optional<Integer> deserialize(JsonNode json) {
+            if (json instanceof NumericNode) {
+                return Optional.of(json.asInt());
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "IntSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<Integer> INT_SERIALIZER = new IntSerializer();
+
+    class LongSerializer implements Serializer<Long> {
+        @Override
+        public JsonNode serialize(Long object) {
+            return LongNode.valueOf(object);
+        }
+
+        @Override
+        public Optional<Long> deserialize(JsonNode json) {
+            if (json instanceof NumericNode) {
+                return Optional.of(json.asLong());
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "LongSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<Long> LONG_SERIALIZER = new LongSerializer();
+
+    class FloatSerializer implements Serializer<Float> {
+        @Override
+        public JsonNode serialize(Float object) {
+            return FloatNode.valueOf(object);
+        }
+
+        @Override
+        public Optional<Float> deserialize(JsonNode json) {
+            if (json instanceof NumericNode) {
+                return Optional.of(json.floatValue());
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "FloatSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<Float> FLOAT_SERIALIZER = new FloatSerializer();
+
+    class DoubleSerializer implements Serializer<Double> {
+        @Override
+        public JsonNode serialize(Double object) {
+            return DoubleNode.valueOf(object);
+        }
+
+        @Override
+        public Optional<Double> deserialize(JsonNode json) {
+            if (json instanceof NumericNode) {
+                return Optional.of(json.asDouble());
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "DoubleSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<Double> DOUBLE_SERIALIZER = new DoubleSerializer();
+
+    class ArbitrarySerializableSerializer implements Serializer<ArbitrarySerializable> {
+        private static final Logger LOGGER = LoggerFactory.getLogger(ArbitrarySerializableSerializer.class);
+
+        @Override
+        public JsonNode serialize(ArbitrarySerializable serializable) {
+            ArbitrarySerializable.Serializable serialized = serializable.serialize();
+            ObjectNode serializedJson = JsonNodeFactory.instance.objectNode();
+            serializedJson.put("factory", serialized.getFactory().getName());
+            serializedJson.replace("value", serialized.getValue().toJson());
+            return serializedJson;
+        }
+
+        @Override
+        public Optional<ArbitrarySerializable> deserialize(JsonNode json) {
+            return Optional.of(json)
+                    .filter(ObjectNode.class::isInstance)
+                    .map(ObjectNode.class::cast)
+                    .flatMap(this::instantiate);
+        }
+
+        public Optional<ArbitrarySerializable> instantiate(ObjectNode fields) {
+            return Optional.ofNullable(fields.get("factory"))
+                .flatMap(serializer ->
+                    Optional.ofNullable(fields.get("value"))
+                        .flatMap(value -> deserialize(serializer.asText(), AttributeValue.fromJson(value))));
+        }
+
+        @SuppressWarnings("unchecked")
+        private Optional<ArbitrarySerializable> deserialize(String serializer, AttributeValue<?> value) {
+            try {
+                Class<?> factoryClass = Class.forName(serializer);
+                if (ArbitrarySerializable.Factory.class.isAssignableFrom(factoryClass)) {
+                    ArbitrarySerializable.Factory factory = (ArbitrarySerializable.Factory) factoryClass.newInstance();
+                    return factory.deserialize(new ArbitrarySerializable.Serializable(value, (Class<ArbitrarySerializable.Factory>) factoryClass));
+                }
+            } catch (Exception e) {
+                LOGGER.error("Error while deserializing", e);
+            }
+
+            return Optional.empty();
+        }
+
+        @Override
+        public String getName() {
+            return "ArbitrarySerializableSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<ArbitrarySerializable> ARIBITRARY_SERIALIZABLE_SERIALIZER = new ArbitrarySerializableSerializer();
+
+    class UrlSerializer implements Serializer<URL> {
+        @Override
+        public JsonNode serialize(URL object) {
+            return STRING_SERIALIZER.serialize(object.toString());
+        }
+
+        @Override
+        public Optional<URL> deserialize(JsonNode json) {
+            return STRING_SERIALIZER.deserialize(json).flatMap(url -> {
+                try {
+                    return Optional.of(new URL(url));
+                } catch (MalformedURLException e) {
+                    return Optional.empty();
+                }
+            });
+        }
+
+        @Override
+        public String getName() {
+            return "UrlSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    Serializer<URL> URL_SERIALIZER = new UrlSerializer();
+
+    class CollectionSerializer<U> implements Serializer<Collection<AttributeValue<U>>> {
+        @Override
+        public JsonNode serialize(Collection<AttributeValue<U>> object) {
+            List<JsonNode> jsons = object.stream()
+                .map(AttributeValue::toJson)
+                .collect(ImmutableList.toImmutableList());
+            return new ArrayNode(JsonNodeFactory.instance, jsons);
+        }
+
+        @Override
+        public Optional<Collection<AttributeValue<U>>> deserialize(JsonNode json) {
+            if (json instanceof ArrayNode) {
+                return Optional.of(Iterators.toStream(json.elements())
+                        .map(value -> (AttributeValue<U>) AttributeValue.fromJson(value))
+                        .collect(ImmutableList.toImmutableList()));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "CollectionSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    class MapSerializer<U> implements Serializer<Map<String, AttributeValue<U>>> {
+        @Override
+        public JsonNode serialize(Map<String, AttributeValue<U>> object) {
+            Map<String, JsonNode> jsonMap = object.entrySet().stream()
+                .collect(ImmutableMap.toImmutableMap(Entry::getKey, entry -> entry.getValue().toJson()));
+            return new ObjectNode(JsonNodeFactory.instance, jsonMap);
+        }
+
+        @Override
+        public Optional<Map<String, AttributeValue<U>>> deserialize(JsonNode json) {
+            if (json instanceof ObjectNode) {
+                return Optional.of(Iterators.toStream(json.fields())
+                        .collect(ImmutableMap.toImmutableMap(
+                            Map.Entry::getKey,
+                            entry -> (AttributeValue<U>) AttributeValue.fromJson(entry.getValue())
+                        )));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "MapSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+    class FSTSerializer implements Serializer<Serializable> {
+        static final FSTConfiguration CONFIGURATION = FSTConfiguration.createJsonConfiguration();
+
+        @Override
+        public JsonNode serialize(Serializable object) {
+            FSTConfiguration conf = CONFIGURATION;
+            String json = conf.asJsonString(object);
+            try {
+                return new ObjectMapper().reader().readTree(json);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+
+        @Override
+        public Optional<Serializable> deserialize(JsonNode json) {
+            FSTConfiguration conf = FSTConfiguration.createJsonConfiguration();
+            try {
+                return Optional.of((Serializable) conf.asObject(new ObjectMapper().writer().writeValueAsBytes(json)));
+            } catch (JsonProcessingException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "FSTSerializer";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/46ba928f/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
new file mode 100644
index 0000000..f741d05
--- /dev/null
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
@@ -0,0 +1,555 @@
+/****************************************************************
+ * 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.mailet;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.core.io.JsonEOFException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+class AttributeValueTest {
+    @Test
+    void shouldRespectBeanContract() {
+        EqualsVerifier.forClass(AttributeValue.class).verify();
+    }
+
+    @Test
+    void ofShouldAcceptNullValue() {
+        AttributeValue<String> attributeValue = AttributeValue.of((String) null);
+
+        assertThat(attributeValue.getValue()).isNull();
+    }
+
+    @Nested
+    class StringSerialization {
+        @Test
+        void stringShouldBeSerializedAndBack() {
+            AttributeValue<String> expected = AttributeValue.of("value");
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void emptyStringShouldBeSerializedAndBack() {
+            AttributeValue<String> expected = AttributeValue.of("");
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Disabled("Failing!")
+        @Test
+        void nullStringShouldBeSerializedAndBack() {
+            AttributeValue<String> expected = AttributeValue.of((String) null);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnStringAttributeValueWhenString() throws Exception {
+            AttributeValue<String> expected = AttributeValue.of("value");
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"StringSerializer\",\"value\": \"value\"}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"StringSerializer\",\"value\": []}"));
+        }
+    }
+
+    @Nested
+    class BooleanSerialization {
+        @Test
+        void trueShouldBeSerializedAndBack() {
+            AttributeValue<Boolean> expected = AttributeValue.of(true);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void falseShouldBeSerializedAndBack() {
+            AttributeValue<Boolean> expected = AttributeValue.of(true);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Disabled("Failing")
+        @Test
+        void nullBooleanShouldBeSerializedAndBack() {
+            AttributeValue<Boolean> expected = AttributeValue.of((Boolean) null);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnBooleanAttributeValueWhenBoolean() throws Exception {
+            AttributeValue<Boolean> expected = AttributeValue.of(true);
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"BooleanSerializer\",\"value\": true}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"BooleanSerializer\",\"value\": []}"));
+        }
+    }
+
+    @Nested
+    class IntegerSerialization {
+        @Test
+        void intShouldBeSerializedAndBack() {
+            AttributeValue<Integer> expected = AttributeValue.of(42);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Disabled("Failing")
+        @Test
+        void nullIntShouldBeSerializedAndBack() {
+            AttributeValue<Integer> expected = AttributeValue.of((Integer) null);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnIntAttributeValueWhenInt() throws Exception {
+            AttributeValue<Integer> expected = AttributeValue.of(42);
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"IntSerializer\",\"value\": 42}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"IntSerializer\",\"value\": []}"));
+        }
+    }
+
+    @Nested
+    class LongSerialization {
+        @Test
+        void longShouldBeSerializedAndBack() {
+            AttributeValue<Long> expected = AttributeValue.of(42L);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Disabled("Failing")
+        @Test
+        void nullLongShouldBeSerializedAndBack() {
+            AttributeValue<Long> expected = AttributeValue.of((Long) null);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnLongAttributeValueWhenLong() throws Exception {
+            AttributeValue<Long> expected = AttributeValue.of(42L);
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"LongSerializer\",\"value\":42}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"LongSerializer\",\"value\": []}"));
+        }
+    }
+
+    @Nested
+    class FloatSerialization {
+        @Test
+        void floatShouldBeSerializedAndBack() {
+            AttributeValue<Float> expected = AttributeValue.of(1.0f);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Disabled("Failing")
+        @Test
+        void nullFloatShouldBeSerializedAndBack() {
+            AttributeValue<Float> expected = AttributeValue.of((Float) null);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnFloatAttributeValueWhenFloat() throws Exception {
+            AttributeValue<Float> expected = AttributeValue.of(1.0f);
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"FloatSerializer\",\"value\":1.0}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"FloatSerializer\",\"value\": []}"));
+        }
+    }
+
+    @Nested
+    class DoubleSerialization {
+        @Test
+        void doubleShouldBeSerializedAndBack() {
+            AttributeValue<Double> expected = AttributeValue.of(1.0d);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Disabled("Failing")
+        @Test
+        void nullDoubleShouldBeSerializedAndBack() {
+            AttributeValue<Double> expected = AttributeValue.of((Double) null);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnDoubleAttributeValueWhenDouble() throws Exception {
+            AttributeValue<Double> expected = AttributeValue.of(1.0);
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"DoubleSerializer\",\"value\":1.0}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"DoubleSerializer\",\"value\": []}"));
+        }
+    }
+
+    @Nested
+    class QueueSerializableTest {
+        @Test
+        void queueSerializableShouldBeSerializedAndBack() {
+            AttributeValue<ArbitrarySerializable> expected = AttributeValue.of(new TestArbitrarySerializable(42));
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+
+        @Test
+        void fromJsonStringShouldReturnQueueSerializableAttributeValueWhenQueueSerializable() throws Exception {
+            AttributeValue<ArbitrarySerializable> expected = AttributeValue.of(new TestArbitrarySerializable(42));
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"ArbitrarySerializableSerializer\",\"value\":{\"factory\":\"org.apache.mailet.AttributeValueTest$TestArbitrarySerializable$Factory\",\"value\":{\"serializer\":\"IntSerializer\",\"value\":42}}}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+    }
+
+    @Nested
+    class UrlSerialization {
+        @Test
+        void urlShouldBeSerializedAndBack() throws MalformedURLException {
+            AttributeValue<URL> expected = AttributeValue.of(new URL("https://james.apache.org/"));
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Disabled("Failing!")
+        @Test
+        void nullURLShouldBeSerializedAndBack() {
+            AttributeValue<URL> expected = AttributeValue.of((URL) null);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnUrlAttributeValueWhenUrl() throws Exception {
+            AttributeValue<URL> expected = AttributeValue.of(new URL("https://james.apache.org/"));
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"UrlSerializer\",\"value\": \"https://james.apache.org/\"}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedUrl() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"UrlSerializer\",\"value\": \"htps://bad/\"}"));
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"UrlSerializer\",\"value\": {}}"));
+        }
+    }
+
+    @Nested
+    class ListSerialization {
+        @Disabled("Failing!")
+        @Test
+        void nullStringListShouldBeSerializedAndBack() {
+            AttributeValue<?> expected = AttributeValue.ofAny((List<String>) null);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void emptyStringListShouldBeSerializedAndBack() {
+            AttributeValue<?> expected = AttributeValue.ofAny(ImmutableList.<String>of());
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void listShouldBeSerializedAndBack() {
+            AttributeValue<?> expected = AttributeValue.of(ImmutableList.of(AttributeValue.of("first"), AttributeValue.of("second")));
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnEmptyListAttributeValueWhenEmptyArray() throws Exception {
+            AttributeValue<?> expected = AttributeValue.of(ImmutableList.of());
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"CollectionSerializer\",\"value\": []}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnListAttributeValueWhenArray() throws Exception {
+            AttributeValue<?> expected = AttributeValue.of(ImmutableList.of(AttributeValue.of("first"), AttributeValue.of("second")));
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"CollectionSerializer\",\"value\":[{\"serializer\":\"StringSerializer\",\"value\":\"first\"},{\"serializer\":\"StringSerializer\",\"value\":\"second\"}]}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"CollectionSerializer\",\"value\": {}}"));
+        }
+    }
+
+    @Nested
+    class MapSerialization {
+        @Disabled("Failing!")
+        @Test
+        void nullMapShouldBeSerializedAndBack() {
+            AttributeValue<?> expected = AttributeValue.of((Map) null);
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void emptyMapShouldBeSerializedAndBack() {
+            AttributeValue<?> expected = AttributeValue.of(ImmutableMap.of());
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void mapWithPrimitiveTypesShouldBeSerializedAndBack() {
+            AttributeValue<?> expected = AttributeValue.of(ImmutableMap.of("a", AttributeValue.of("value"), "b", AttributeValue.of(12)));
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnEmptyMapWhenEmptyMap() throws Exception {
+            AttributeValue<Map<String, AttributeValue<?>>> expected = AttributeValue.of(ImmutableMap.of());
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"MapSerializer\",\"value\":{}}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldReturnMapWhenMap() throws Exception {
+            AttributeValue<Map<String, AttributeValue<?>>> expected = AttributeValue.of(
+                ImmutableMap.of(
+                    "a", AttributeValue.of(1),
+                    "b", AttributeValue.of(2)));
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"MapSerializer\",\"value\":{\"a\":{\"serializer\":\"IntSerializer\",\"value\":1},\"b\":{\"serializer\":\"IntSerializer\",\"value\":2}}}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnMalformedFormattedJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"MapSerializer\",\"value\": []}"));
+        }
+    }
+
+    @Test
+    void fromJsonStringShouldThrowOnUnknownSerializer() {
+        assertThatIllegalStateException()
+            .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"unknown\",\"value\": \"value\"}"));
+    }
+
+    @Test
+    void fromJsonStringShouldThrowOnBrokenJson() {
+        assertThatThrownBy(() ->AttributeValue.fromJsonString("{\"serializer\":\"StringSerializer\",\"value\": \"Missing closing bracket\""))
+            .isInstanceOf(JsonEOFException.class);
+    }
+
+    @Test
+    void fromJsonStringShouldThrowOnMissingSerializerField() {
+        assertThatIllegalStateException()
+            .isThrownBy(() -> AttributeValue.fromJsonString("{\"value\": \"value\"}"));
+    }
+
+    @Test
+    void fromJsonStringShouldThrowOnMissingValueField() {
+        assertThatIllegalStateException()
+            .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"MapSerializer\"}"));
+    }
+
+    private static class TestArbitrarySerializable implements ArbitrarySerializable {
+        public static class Factory implements ArbitrarySerializable.Factory {
+            @Override
+            public Optional<ArbitrarySerializable> deserialize(Serializable serializable) {
+                return Optional.of(serializable.getValue().value())
+                        .filter(Integer.class::isInstance)
+                        .map(Integer.class::cast)
+                        .map(TestArbitrarySerializable::new);
+            }
+        }
+
+        private final Integer value;
+
+        public TestArbitrarySerializable(Integer value) {
+            this.value = value;
+        }
+
+        @Override
+        public Serializable serialize() {
+            return new Serializable(AttributeValue.of(value), Factory.class);
+        }
+
+        @Override
+        public final boolean equals(Object o) {
+            if (o instanceof TestArbitrarySerializable) {
+                TestArbitrarySerializable that = (TestArbitrarySerializable) o;
+
+                return Objects.equals(this.value, that.value);
+            }
+            return false;
+        }
+
+        @Override
+        public final int hashCode() {
+            return Objects.hash(value);
+        }
+    }
+}


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


[02/17] james-project git commit: JAMES-2557 All Rcpt hooks should use new API

Posted by bt...@apache.org.
JAMES-2557 All Rcpt hooks should use new API


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

Branch: refs/heads/master
Commit: 3f68078d4e4cd81a492c157740998cd5ac65c7bd
Parents: 585c172
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 11:07:27 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 10:56:32 2018 +0700

----------------------------------------------------------------------
 .../AbstractAuthRequiredToRelayRcptHook.java    |  4 ++--
 ...tSenderAuthIdentifyVerificationRcptHook.java |  6 +++---
 .../AcceptRecipientIfRelayingIsAllowed.java     |  4 ++--
 .../smtp/core/PostmasterAbuseRcptHook.java      |  3 ++-
 .../protocols/smtp/core/RcptCmdHandler.java     |  7 ++++---
 .../core/fastfail/AbstractGreylistHandler.java  | 10 ++++------
 .../core/fastfail/AbstractValidRcptHandler.java |  3 ++-
 .../smtp/core/fastfail/DNSRBLHandler.java       |  3 ++-
 .../smtp/core/fastfail/MaxRcptHandler.java      |  3 ++-
 .../fastfail/ResolvableEhloHeloHandler.java     |  3 ++-
 .../smtp/core/fastfail/SpamTrapHandler.java     |  3 ++-
 .../fastfail/SupressDuplicateRcptHandler.java   |  3 ++-
 .../james/protocols/smtp/hook/SimpleHook.java   |  2 +-
 .../protocols/smtp/AbstractSMTPServerTest.java  |  4 ++--
 .../smtp/core/fastfail/DNSRBLHandlerTest.java   | 13 +++++++------
 .../smtp/core/fastfail/MaxRcptHandlerTest.java  |  4 ++--
 .../fastfail/ResolvableEhloHeloHandlerTest.java |  9 +++++----
 .../smtp/core/fastfail/SpamTrapHandlerTest.java |  9 +++++----
 .../SenderAuthIdentifyVerificationRcptHook.java |  3 ++-
 .../fastfail/JDBCGreylistHandler.java           |  3 ++-
 .../james/smtpserver/fastfail/SPFHandler.java   |  2 +-
 .../james/smtpserver/fastfail/ValidRcptMX.java  |  3 ++-
 .../apache/james/smtpserver/SPFHandlerTest.java | 16 ++++++++--------
 .../james/smtpserver/ValidRcptHandlerTest.java  | 20 +++++++++++---------
 .../james/smtpserver/ValidRcptMXTest.java       |  3 ++-
 25 files changed, 79 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAuthRequiredToRelayRcptHook.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAuthRequiredToRelayRcptHook.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAuthRequiredToRelayRcptHook.java
index e432003..43fc8c8 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAuthRequiredToRelayRcptHook.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAuthRequiredToRelayRcptHook.java
@@ -20,6 +20,7 @@ package org.apache.james.protocols.smtp.core;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPRetCode;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.dsn.DSNStatus;
@@ -48,8 +49,7 @@ public abstract class AbstractAuthRequiredToRelayRcptHook implements RcptHook {
         .build();
     
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender,
-                             MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if (!session.isRelayingAllowed()) {
             Domain toDomain = rcpt.getDomain();
             if (!isLocalDomain(toDomain)) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java
index d568b14..dea7d52 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java
@@ -22,6 +22,7 @@ import java.util.Locale;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.api.ProtocolSession;
 import org.apache.james.protocols.smtp.SMTPRetCode;
 import org.apache.james.protocols.smtp.SMTPSession;
@@ -42,8 +43,7 @@ public abstract class AbstractSenderAuthIdentifyVerificationRcptHook implements
         .build();
     
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender,
-                             MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if (session.getUser() != null) {
             String authUser = (session.getUser()).toLowerCase(Locale.US);
             MailAddress senderAddress = (MailAddress) session.getAttachment(
@@ -62,7 +62,7 @@ public abstract class AbstractSenderAuthIdentifyVerificationRcptHook implements
         return HookResult.DECLINED;
     }
 
-    public String retrieveSender(MailAddress sender, MailAddress senderAddress) {
+    public String retrieveSender(MaybeSender sender, MailAddress senderAddress) {
         if (senderAddress != null && !sender.isNullSender()) {
             return getUser(senderAddress);
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AcceptRecipientIfRelayingIsAllowed.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AcceptRecipientIfRelayingIsAllowed.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AcceptRecipientIfRelayingIsAllowed.java
index 2391572..7ab45a7 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AcceptRecipientIfRelayingIsAllowed.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AcceptRecipientIfRelayingIsAllowed.java
@@ -21,6 +21,7 @@ package org.apache.james.protocols.smtp.core;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookResult;
 import org.apache.james.protocols.smtp.hook.RcptHook;
@@ -31,8 +32,7 @@ import org.apache.james.protocols.smtp.hook.RcptHook;
 public class AcceptRecipientIfRelayingIsAllowed implements RcptHook {
 
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender,
-                             MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if (session.isRelayingAllowed()) {
             return HookResult.OK;
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/PostmasterAbuseRcptHook.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/PostmasterAbuseRcptHook.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/PostmasterAbuseRcptHook.java
index 540568e..35d0506 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/PostmasterAbuseRcptHook.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/PostmasterAbuseRcptHook.java
@@ -21,6 +21,7 @@ package org.apache.james.protocols.smtp.core;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookResult;
 import org.apache.james.protocols.smtp.hook.RcptHook;
@@ -34,7 +35,7 @@ public class PostmasterAbuseRcptHook implements RcptHook {
     private static final Logger LOGGER = LoggerFactory.getLogger(PostmasterAbuseRcptHook.class);
     
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if (rcpt.getLocalPart().equalsIgnoreCase("postmaster") || rcpt.getLocalPart().equalsIgnoreCase("abuse")) {
             LOGGER.debug("Sender allowed");
             return HookResult.OK;

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java
index c7b17ca..2640564 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java
@@ -29,6 +29,7 @@ import javax.inject.Inject;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.api.Response;
@@ -228,10 +229,10 @@ public class RcptCmdHandler extends AbstractHookableCmdHandler<RcptHook> impleme
     }
 
     @Override
-    protected HookResult callHook(RcptHook rawHook, SMTPSession session,
-                                  String parameters) {
+    protected HookResult callHook(RcptHook rawHook, SMTPSession session, String parameters) {
+        MailAddress sender = (MailAddress) session.getAttachment(SMTPSession.SENDER, State.Transaction);
         return rawHook.doRcpt(session,
-                (MailAddress) session.getAttachment(SMTPSession.SENDER, State.Transaction),
+                MaybeSender.of(sender),
                 (MailAddress) session.getAttachment(CURRENT_RECIPIENT, State.Transaction));
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractGreylistHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractGreylistHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractGreylistHandler.java
index bdacc2c..9ccff46 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractGreylistHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractGreylistHandler.java
@@ -22,6 +22,7 @@ package org.apache.james.protocols.smtp.core.fastfail;
 import java.util.Iterator;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPRetCode;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.dsn.DSNStatus;
@@ -76,16 +77,13 @@ public abstract class AbstractGreylistHandler implements RcptHook {
     }
 
 
-    private HookResult doGreyListCheck(SMTPSession session, MailAddress senderAddress, MailAddress recipAddress) {
+    private HookResult doGreyListCheck(SMTPSession session, MaybeSender senderAddress, MailAddress recipAddress) {
         String recip = "";
-        String sender = "";
+        String sender = senderAddress.asString("");
 
         if (recipAddress != null) {
             recip = recipAddress.toString();
         }
-        if (senderAddress != null) {
-            sender = senderAddress.toString();
-        }
     
         long time = System.currentTimeMillis();
         String ipAddress = session.getRemoteAddress().getAddress().getHostAddress();
@@ -219,7 +217,7 @@ public abstract class AbstractGreylistHandler implements RcptHook {
   
 
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if (!session.isRelayingAllowed()) {
             return doGreyListCheck(session, sender,rcpt);
         } else {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractValidRcptHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractValidRcptHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractValidRcptHandler.java
index 374a164..23eb4fb 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractValidRcptHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/AbstractValidRcptHandler.java
@@ -21,6 +21,7 @@ package org.apache.james.protocols.smtp.core.fastfail;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPRetCode;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.dsn.DSNStatus;
@@ -37,7 +38,7 @@ public abstract class AbstractValidRcptHandler implements RcptHook {
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractValidRcptHandler.class);
 
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if (!isLocalDomain(session, rcpt.getDomain())) {
             return HookResult.DECLINED;
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java
index b3822ba..b79dddc 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java
@@ -27,6 +27,7 @@ import java.util.StringTokenizer;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.dsn.DSNStatus;
@@ -178,7 +179,7 @@ public class DNSRBLHandler implements RcptHook {
     }
     
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         checkDNSRBL(session, session.getRemoteAddress().getAddress().getHostAddress());
     
         if (!session.isRelayingAllowed()) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java
index 47c7b1d..2b1e915 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java
@@ -24,6 +24,7 @@ package org.apache.james.protocols.smtp.core.fastfail;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPRetCode;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.dsn.DSNStatus;
@@ -56,7 +57,7 @@ public class MaxRcptHandler implements RcptHook {
     }
    
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if ((session.getRcptCount() + 1) > maxRcpt) {
             LOGGER.info("Maximum recipients of {} reached", maxRcpt);
             

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java
index 65c95e5..5dd741c 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java
@@ -25,6 +25,7 @@ import java.net.UnknownHostException;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.smtp.SMTPRetCode;
 import org.apache.james.protocols.smtp.SMTPSession;
@@ -93,7 +94,7 @@ public class ResolvableEhloHeloHandler implements RcptHook, HeloHook {
     }
 
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if (check(session,rcpt)) {
             return HookResult.builder()
                 .hookReturnCode(HookReturnCode.deny())

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandler.java
index 77324ce..7591928 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandler.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookResult;
 import org.apache.james.protocols.smtp.hook.RcptHook;
@@ -69,7 +70,7 @@ public class SpamTrapHandler implements RcptHook {
     }
     
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         String address = session.getRemoteAddress().getAddress().getHostAddress();
         if (isBlocked(address, session)) {
             return HookResult.DENY;

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java
index 7c5e293..0a1b997 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java
@@ -24,6 +24,7 @@ import java.util.Collection;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.smtp.SMTPRetCode;
 import org.apache.james.protocols.smtp.SMTPSession;
@@ -52,7 +53,7 @@ public class SupressDuplicateRcptHandler implements RcptHook {
 
     @Override
     @SuppressWarnings("unchecked")
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         Collection<MailAddress> rcptList = (Collection<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction);
     
         // Check if the recipient is already in the rcpt list

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java
index f226e17..69d1b0f 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/SimpleHook.java
@@ -57,7 +57,7 @@ public class SimpleHook implements HeloHook, MailHook, RcptHook, MessageHook {
      * Return {@link HookResult} with {@link HookReturnCode#DECLINED}
      */
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         return HookResult.DECLINED;
 
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
index 7bcb07f..bf3f756 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
@@ -695,7 +695,7 @@ public abstract class AbstractSMTPServerTest {
             }
 
             @Override
-            public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+            public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
                 if (RCPT1.equals(rcpt.toString())) {
                     return HookResult.DENY;
                 } else {
@@ -759,7 +759,7 @@ public abstract class AbstractSMTPServerTest {
             }
 
             @Override
-            public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+            public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
                 if (RCPT1.equals(rcpt.toString())) {
                     return HookResult.DENYSOFT;
                 } else {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java
index 1b96bdb..87c30c4 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java
@@ -31,6 +31,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
@@ -183,7 +184,7 @@ public class DNSRBLHandlerTest {
 
         rbl.setBlacklist(new String[] { "bl.spamcop.net." });
         rbl.setGetDetail(true);
-        rbl.doRcpt(mockedSMTPSession, null, new MailAddress("test@localhost"));
+        rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
         assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, State.Connection)).describedAs("Details").isEqualTo("Blocked - see http://www.spamcop.net/bl.shtml?127.0.0.2");
         assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isNotNull();
     }
@@ -196,7 +197,7 @@ public class DNSRBLHandlerTest {
 
         rbl.setBlacklist(new String[] { "bl.spamcop.net." });
         rbl.setGetDetail(false);
-        rbl.doRcpt(mockedSMTPSession, null, new MailAddress("test@localhost"));
+        rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
         assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isNull();
         assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isNotNull();
     }
@@ -210,7 +211,7 @@ public class DNSRBLHandlerTest {
 
         rbl.setBlacklist(new String[] { "bl.spamcop.net." });
         rbl.setGetDetail(true);
-        rbl.doRcpt(mockedSMTPSession, null, new MailAddress("test@localhost"));
+        rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
         assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isNull();
         assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isNull();
     }
@@ -225,7 +226,7 @@ public class DNSRBLHandlerTest {
 
         rbl.setBlacklist(new String[] { "bl.spamcop.net." });
         rbl.setGetDetail(true);
-        rbl.doRcpt(mockedSMTPSession, null, new MailAddress("test@localhost"));
+        rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
         assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isNull();
         assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isNull();
     }
@@ -240,7 +241,7 @@ public class DNSRBLHandlerTest {
 
         rbl.setBlacklist(new String[] { "bl.spamcop.net." });
         rbl.setGetDetail(true);
-        rbl.doRcpt(mockedSMTPSession, null, new MailAddress("test@localhost"));
+        rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
         assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).isNull();
         assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isNotNull();
     }
@@ -255,7 +256,7 @@ public class DNSRBLHandlerTest {
 
         rbl.setWhitelist(new String[] { "bl.spamcop.net." });
         rbl.setGetDetail(true);
-        rbl.doRcpt(mockedSMTPSession, null, new MailAddress("test@localhost"));
+        rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
         assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).isNull();
         assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isNull();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java
index 0466456..0164520 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java
@@ -60,7 +60,7 @@ public class MaxRcptHandlerTest {
         MaxRcptHandler handler = new MaxRcptHandler();
         
         handler.setMaxRcpt(2);
-        HookReturnCode resp = handler.doRcpt(session,null,new MailAddress("test@test")).getResult();
+        HookReturnCode resp = handler.doRcpt(session, MailAddress.nullSender(), new MailAddress("test@test")).getResult();
     
         assertThat(HookReturnCode.deny()).describedAs("Rejected.. To many recipients").isEqualTo(resp);
     }
@@ -72,7 +72,7 @@ public class MaxRcptHandlerTest {
         MaxRcptHandler handler = new MaxRcptHandler();    
 
         handler.setMaxRcpt(4);
-        HookReturnCode resp = handler.doRcpt(session,null,new MailAddress("test@test")).getResult();
+        HookReturnCode resp = handler.doRcpt(session, MailAddress.nullSender(), new MailAddress("test@test")).getResult();
         
         assertThat(HookReturnCode.declined()).describedAs("Not Rejected..").isEqualTo(resp);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java
index 468e0d3..df2d274 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java
@@ -29,6 +29,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookReturnCode;
 import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
@@ -126,7 +127,7 @@ public class ResolvableEhloHeloHandlerTest {
         handler.doHelo(session, INVALID_HOST);
         assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Invalid HELO").isNotNull();
 
-        HookReturnCode result = handler.doRcpt(session,null, mailAddress).getResult();
+        HookReturnCode result = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
         assertThat(HookReturnCode.deny()).describedAs("Reject").isEqualTo(result);
     }
     
@@ -140,7 +141,7 @@ public class ResolvableEhloHeloHandlerTest {
         handler.doHelo(session, VALID_HOST);
         assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Valid HELO").isNull();
 
-        HookReturnCode result = handler.doRcpt(session,null, mailAddress).getResult();
+        HookReturnCode result = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
         assertThat(HookReturnCode.declined()).describedAs("Not reject").isEqualTo(result);
     }
    
@@ -155,7 +156,7 @@ public class ResolvableEhloHeloHandlerTest {
         assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Value stored").isNotNull();
 
 
-        HookReturnCode result = handler.doRcpt(session,null, mailAddress).getResult();
+        HookReturnCode result = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
         assertThat(HookReturnCode.deny()).describedAs("Reject").isEqualTo(result);
     }
     
@@ -171,7 +172,7 @@ public class ResolvableEhloHeloHandlerTest {
         assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Value stored").isNotNull();
 
 
-        HookReturnCode result = handler.doRcpt(session,null, mailAddress).getResult();
+        HookReturnCode result = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
         assertThat(HookReturnCode.deny()).describedAs("Reject").isEqualTo(result);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandlerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandlerTest.java
index ead4197..3e7a528 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/SpamTrapHandlerTest.java
@@ -26,6 +26,7 @@ import java.net.InetSocketAddress;
 import java.util.ArrayList;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookReturnCode;
 import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
@@ -63,17 +64,17 @@ public class SpamTrapHandlerTest {
         handler.setBlockTime(blockTime);
         handler.setSpamTrapRecipients(rcpts);
 
-        HookReturnCode result = handler.doRcpt(setUpSMTPSession(ip),null,new MailAddress(SPAM_TRAP_RECIP1)).getResult();
+        HookReturnCode result = handler.doRcpt(setUpSMTPSession(ip), MaybeSender.nullSender(), new MailAddress(SPAM_TRAP_RECIP1)).getResult();
     
         assertThat(result).describedAs("Blocked on first connect").isEqualTo(HookReturnCode.deny());
     
 
-        result = handler.doRcpt(setUpSMTPSession(ip),null,new MailAddress(RECIP1)).getResult();
+        result = handler.doRcpt(setUpSMTPSession(ip), MaybeSender.nullSender(), new MailAddress(RECIP1)).getResult();
     
         assertThat(result).describedAs("Blocked on second connect").isEqualTo(HookReturnCode.deny());
     
         
-        result = handler.doRcpt(setUpSMTPSession(ip2),null,new MailAddress(RECIP1)).getResult();
+        result = handler.doRcpt(setUpSMTPSession(ip2), MaybeSender.nullSender(), new MailAddress(RECIP1)).getResult();
     
         assertThat(result).describedAs("Not Blocked").isEqualTo(HookReturnCode.declined());
     
@@ -84,7 +85,7 @@ public class SpamTrapHandlerTest {
             fail("Failed to sleep for " + blockTime + " ms");
         }
     
-        result = handler.doRcpt(setUpSMTPSession(ip),null,new MailAddress(RECIP1)).getResult();
+        result = handler.doRcpt(setUpSMTPSession(ip), MaybeSender.nullSender(), new MailAddress(RECIP1)).getResult();
     
         assertThat(result).describedAs("Not blocked. BlockTime exceeded").isEqualTo(HookReturnCode.declined());
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java
index d496c4d..578d50a 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java
@@ -24,6 +24,7 @@ import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.api.DomainListException;
 import org.apache.james.protocols.smtp.SMTPSession;
@@ -61,7 +62,7 @@ public class SenderAuthIdentifyVerificationRcptHook extends AbstractSenderAuthId
     }
 
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         ExtendedSMTPSession nSession = (ExtendedSMTPSession) session;
         if (nSession.verifyIdentity()) {
             return super.doRcpt(session, sender, rcpt);

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/JDBCGreylistHandler.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/JDBCGreylistHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/JDBCGreylistHandler.java
index 37c8252..a1587e8 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/JDBCGreylistHandler.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/JDBCGreylistHandler.java
@@ -38,6 +38,7 @@ import javax.sql.DataSource;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.dnsservice.library.netmatcher.NetMatcher;
 import org.apache.james.filesystem.api.FileSystem;
@@ -353,7 +354,7 @@ public class JDBCGreylistHandler extends AbstractGreylistHandler implements Prot
     }
 
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if ((wNetworks == null) || (!wNetworks.matchInetNetwork(session.getRemoteAddress().getAddress().getHostAddress()))) {
             return super.doRcpt(session, sender, rcpt);
         } else {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
index 2c86b5f..1d136ab 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
@@ -149,7 +149,7 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
     }
 
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
         if (!session.isRelayingAllowed()) {
             // Check if session is blocklisted
             if (session.getAttachment(SPF_BLOCKLISTED, State.Transaction) != null) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptMX.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptMX.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptMX.java
index 13c234b..5165f12 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptMX.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptMX.java
@@ -29,6 +29,7 @@ import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.dnsservice.api.TemporaryResolutionException;
 import org.apache.james.dnsservice.library.netmatcher.NetMatcher;
@@ -87,7 +88,7 @@ public class ValidRcptMX implements RcptHook, ProtocolHandler {
     }
 
     @Override
-    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
 
         Domain domain = rcpt.getDomain();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
index d7221ff..2183816 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
@@ -178,7 +178,7 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
     }
 
     @Test
@@ -191,7 +191,7 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("fail").isEqualTo(HookReturnCode.deny());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("fail").isEqualTo(HookReturnCode.deny());
     }
 
     @Test
@@ -204,7 +204,7 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("softfail declined").isEqualTo(HookReturnCode.declined());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("softfail declined").isEqualTo(HookReturnCode.declined());
     }
 
     @Test
@@ -220,7 +220,7 @@ public class SPFHandlerTest {
         spf.setBlockSoftFail(true);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("softfail reject").isEqualTo(HookReturnCode.deny());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("softfail reject").isEqualTo(HookReturnCode.deny());
     }
 
     @Test
@@ -236,7 +236,7 @@ public class SPFHandlerTest {
         spf.setBlockSoftFail(true);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("permerror reject").isEqualTo(HookReturnCode.deny());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("permerror reject").isEqualTo(HookReturnCode.deny());
     }
 
     @Test
@@ -251,7 +251,7 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("temperror denysoft").isEqualTo(HookReturnCode.denySoft());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("temperror denysoft").isEqualTo(HookReturnCode.denySoft());
     }
 
     @Test
@@ -265,7 +265,7 @@ public class SPFHandlerTest {
         spf.setDNSService(mockedDnsService);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
     }
 
     @Test
@@ -280,6 +280,6 @@ public class SPFHandlerTest {
         spf.setBlockPermError(false);
 
         assertThat(spf.doMail(mockedSMTPSession, sender).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
-        assertThat(spf.doRcpt(mockedSMTPSession, sender.get(), rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
+        assertThat(spf.doRcpt(mockedSMTPSession, sender, rcpt).getResult()).describedAs("declined").isEqualTo(HookReturnCode.declined());
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
index a6eed9a..03d68f8 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
@@ -26,6 +26,7 @@ import java.util.HashMap;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.domainlist.lib.DomainListConfiguration;
 import org.apache.james.domainlist.memory.MemoryDomainList;
@@ -47,6 +48,7 @@ public class ValidRcptHandlerTest {
     private static final String USER2 = "user2";
     private static final String PASSWORD = "xxx";
     private static final boolean RELAYING_ALLOWED = true;
+    private static final MaybeSender MAYBE_SENDER = MaybeSender.of(SENDER);
 
     private ValidRcptHandler handler;
     private MemoryRecipientRewriteTable memoryRecipientRewriteTable;
@@ -115,7 +117,7 @@ public class ValidRcptHandlerTest {
     public void doRcptShouldRejectNotExistingLocalUsersWhenNoRelay() {
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, invalidUserEmail).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, invalidUserEmail).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.deny());
     }
@@ -124,7 +126,7 @@ public class ValidRcptHandlerTest {
     public void doRcptShouldDenyNotExistingLocalUsersWhenRelay() {
         SMTPSession session = setupMockedSMTPSession(RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, invalidUserEmail).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, invalidUserEmail).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.deny());
     }
@@ -134,7 +136,7 @@ public class ValidRcptHandlerTest {
         MailAddress mailAddress = new MailAddress(INVALID_USER + "@otherdomain");
         SMTPSession session = setupMockedSMTPSession(RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, mailAddress).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, mailAddress).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.declined());
     }
@@ -144,7 +146,7 @@ public class ValidRcptHandlerTest {
         MailAddress mailAddress = new MailAddress(INVALID_USER + "@otherdomain");
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, mailAddress).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, mailAddress).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.declined());
     }
@@ -153,7 +155,7 @@ public class ValidRcptHandlerTest {
     public void doRcptShouldDeclineValidUsersWhenNoRelay() throws Exception {
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, validUserEmail).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, validUserEmail).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.declined());
     }
@@ -162,7 +164,7 @@ public class ValidRcptHandlerTest {
     public void doRcptShouldDeclineValidUsersWhenRelay() throws Exception {
         SMTPSession session = setupMockedSMTPSession(RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, validUserEmail).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, validUserEmail).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.declined());
     }
@@ -173,7 +175,7 @@ public class ValidRcptHandlerTest {
 
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, validUserEmail).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, validUserEmail).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.declined());
     }
@@ -185,7 +187,7 @@ public class ValidRcptHandlerTest {
 
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, user1mail).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, user1mail).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.declined());
     }
@@ -196,7 +198,7 @@ public class ValidRcptHandlerTest {
 
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
-        HookReturnCode rCode = handler.doRcpt(session, SENDER, user1mail).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, user1mail).getResult();
 
         assertThat(rCode).isEqualTo(HookReturnCode.declined());
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f68078d/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
index 730460f..c7db08d 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
@@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.util.HashMap;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.dnsservice.api.InMemoryDNSService;
 import org.apache.james.protocols.smtp.SMTPSession;
@@ -83,7 +84,7 @@ public class ValidRcptMXTest {
         ValidRcptMX handler = new ValidRcptMX();
         handler.setDNSService(dns);
         handler.setBannedNetworks(ImmutableList.of(bannedAddress), dns);
-        HookReturnCode rCode = handler.doRcpt(session, null, mailAddress).getResult();
+        HookReturnCode rCode = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
 
         assertThat(HookReturnCode.deny()).describedAs("Reject").isEqualTo(rCode);
     }


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


[03/17] james-project git commit: JAMES-2557 RCPT SMTP hooks API should explicitly handle optional sender

Posted by bt...@apache.org.
JAMES-2557 RCPT SMTP hooks API should explicitly handle optional sender

Note that thanks to interface defaults, API compatibility is not broken


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

Branch: refs/heads/master
Commit: 585c1729536e900dff5fe82745199ab1a2713d85
Parents: 93be34c
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 10:59:08 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 10:56:32 2018 +0700

----------------------------------------------------------------------
 .../james/protocols/smtp/hook/RcptHook.java       | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/585c1729/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/RcptHook.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/RcptHook.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/RcptHook.java
index 0c09663..49d0efa 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/RcptHook.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/hook/RcptHook.java
@@ -19,6 +19,7 @@
 package org.apache.james.protocols.smtp.hook;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.protocols.smtp.SMTPSession;
 
 /**
@@ -28,12 +29,27 @@ public interface RcptHook extends Hook {
     
     /**
      * Return the HookResult after run the hook
+     *
+     * @deprecated Use {@link #doRcpt(SMTPSession, MaybeSender, MailAddress)} instead
      * 
      * @param session the SMTPSession
      * @param sender the sender MailAddress
      * @param rcpt the recipient MailAddress
      * @return HookResult
      */
-    HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt);
+    @Deprecated
+    default HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+        return doRcpt(session, MaybeSender.of(sender), rcpt);
+    }
+
+    /**
+     * Return the HookResult after run the hook
+     *
+     * this strongly typed version smoothly handle null sender and should be prefered.
+     */
+    @SuppressWarnings("deprecated")
+    default HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
+        return doRcpt(session, sender.asOptional().orElse(null), rcpt);
+    }
 
 }


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


[06/17] james-project git commit: JAMES-2153 Added docker file for Guice JPA-SMTP

Posted by bt...@apache.org.
JAMES-2153 Added docker file for Guice JPA-SMTP


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

Branch: refs/heads/master
Commit: 9a96bd51527bdc8baab8a4f00891483c642406d6
Parents: 3d83c3d
Author: matzepan <ma...@gmail.com>
Authored: Sat Oct 20 19:28:53 2018 +0200
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 10:57:34 2018 +0700

----------------------------------------------------------------------
 dockerfiles/compilation/java-8/compile.sh       |  11 +-
 dockerfiles/run/guice/jpa-smtp/Dockerfile       |  28 +++++
 .../jpa-smtp/destination/conf/dnsservice.xml    |  29 +++++
 .../jpa-smtp/destination/conf/domainlist.xml    |  28 +++++
 .../destination/conf/james-database.properties  |  46 ++++++++
 .../jpa-smtp/destination/conf/jmx.properties    |  29 +++++
 .../guice/jpa-smtp/destination/conf/logback.xml |  28 +++++
 .../destination/conf/mailetcontainer.xml        | 108 +++++++++++++++++++
 .../destination/conf/mailrepositorystore.xml    |  34 ++++++
 .../destination/conf/recipientrewritetable.xml  |  27 +++++
 .../jpa-smtp/destination/conf/smtpserver.xml    | 105 ++++++++++++++++++
 .../destination/conf/usersrepository.xml        |  27 +++++
 .../destination/extensions-jars/README.md       |   5 +
 13 files changed, 504 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/compilation/java-8/compile.sh
----------------------------------------------------------------------
diff --git a/dockerfiles/compilation/java-8/compile.sh b/dockerfiles/compilation/java-8/compile.sh
index 954e78a..d3d86ad 100755
--- a/dockerfiles/compilation/java-8/compile.sh
+++ b/dockerfiles/compilation/java-8/compile.sh
@@ -15,6 +15,7 @@ printUsage() {
 ORIGIN=/origin
 CASSANDRA_DESTINATION=/cassandra/destination
 JPA_DESTINATION=/jpa/destination
+JPA_SMTP_DESTINATION=/jpa-smpt/destination
 SPRING_DESTINATION=/spring/destination
 SWAGGER_DESTINATION=/swagger
 
@@ -77,6 +78,14 @@ if [ $? -eq 0 ]; then
       cp -r server/container/cli/target/james-server-cli.lib $JPA_DESTINATION || true
    fi
 
+   if [ -d "$JPA_SMTP_DESTINATION" ]; then
+      echo "Copying JPA-SMTP jars"
+      cp server/container/guice/jpa-smpt/target/james-server-jpa-smtp-guice.jar $JPA_SMTP_DESTINATION || true
+      cp -r server/container/guice/jpa-smpt/target/james-server-jpa-smtp-guice.lib $JPA_SMTP_DESTINATION || true
+      cp server/container/cli/target/james-server-cli.jar $JPA_SMTP_DESTINATION || true
+      cp -r server/container/cli/target/james-server-cli.lib $JPA_SMTP_DESTINATION || true
+   fi
+
    if [ -d "$SPRING_DESTINATION" ]; then
       echo "Copying SPRING jars"
       cp server/app/target/james-server-app-*-app.zip $SPRING_DESTINATION
@@ -87,4 +96,4 @@ if [ $? -eq 0 ]; then
       cp server/protocols/webadmin/webadmin-mailbox/target/webadmin-mailbox.json $SWAGGER_DESTINATION || true
       cp server/protocols/webadmin/webadmin-swagger/target/webadmin-swagger.json $SWAGGER_DESTINATION || true
    fi
-fi
+fi
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/Dockerfile
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/Dockerfile b/dockerfiles/run/guice/jpa-smtp/Dockerfile
new file mode 100644
index 0000000..7e57dda
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/Dockerfile
@@ -0,0 +1,28 @@
+# Run James
+#
+# VERSION	1.0
+
+FROM openjdk:8u171-jdk
+
+# Ports that are used
+#
+# 25   SMTP without authentication
+# 143  IMAP with startTLS enabled
+# 465  SMTP with authentication and socketTLS enabled
+# 587  SMTP with authentication and startTLS enabled
+# 8000 Web Admin interface (unsecured: expose at your own risks)
+
+EXPOSE 25 143 465 587 8000
+
+WORKDIR /root
+
+# Get data we need to run James : build results and configuration
+ADD destination/james-server-jpa-smtp-guice.jar /root/james-server-jpa-smtp-guice.jar
+ADD destination/james-server-jpa-smtp-guice.lib /root/james-server-jpa-smtp-guice.lib
+ADD destination/james-server-cli.jar /root/james-cli.jar
+ADD destination/james-server-cli.lib /root/james-server-cli.lib
+ADD destination/conf /root/conf
+
+VOLUME /logs
+
+ENTRYPOINT java -classpath '/root/james-server-jpa-smtp-guice.jar:/root/james-server-jpa-smtp-guice.lib/*' -javaagent:/root/james-server-jpa-smtp-guice.lib/openjpa-3.0.0.jar -Dlogback.configurationFile=/root/conf/logback.xml -Dworking.directory=/root/ org.apache.james.JPAJamesServerMain

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/dnsservice.xml
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/dnsservice.xml b/dockerfiles/run/guice/jpa-smtp/destination/conf/dnsservice.xml
new file mode 100644
index 0000000..0978a00
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/dnsservice.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+  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.                                           
+ -->
+
+<dnsservice>
+  <servers>
+    <server>8.8.8.8</server>
+    <server>62.210.16.6</server>
+  </servers>
+  <autodiscover>false</autodiscover>
+  <authoritative>false</authoritative>
+  <maxcachesize>50000</maxcachesize>
+</dnsservice>

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/domainlist.xml
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/domainlist.xml b/dockerfiles/run/guice/jpa-smtp/destination/conf/domainlist.xml
new file mode 100644
index 0000000..fc64fd2
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/domainlist.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!--
+  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.                                           
+ -->
+
+<domainlist class="org.apache.james.domainlist.jpa.JPADomainList">
+    <domainnames>
+        <domainname>james.linagora.com</domainname>
+    </domainnames>
+    <autodetect>true</autodetect>
+    <autodetectIP>true</autodetectIP>
+    <defaultDomain>localhost</defaultDomain>
+</domainlist>

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/james-database.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/james-database.properties b/dockerfiles/run/guice/jpa-smtp/destination/conf/james-database.properties
new file mode 100644
index 0000000..22770d0
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/james-database.properties
@@ -0,0 +1,46 @@
+#  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.
+
+#  This template file can be used as example for James Server configuration
+#  DO NOT USE IT AS SUCH AND ADAPT IT TO YOUR NEEDS
+
+# See http://james.apache.org/server/3/config.html for usage
+
+# Use derby as default
+database.driverClassName=org.apache.derby.jdbc.EmbeddedDriver
+database.url=jdbc:derby:../var/store/derby;create=true
+database.username=app
+database.password=app
+
+# Supported adapters are:
+# DB2, DERBY, H2, HSQL, INFORMIX, MYSQL, ORACLE, POSTGRESQL, SQL_SERVER, SYBASE 
+vendorAdapter.database=DERBY
+
+# Use streaming for Blobs
+# This is only supported on a limited set of databases atm. You should check if its supported by your DB before enable
+# it. 
+# 
+# See:
+# http://openjpa.apache.org/builds/latest/docs/manual/ref_guide_mapping_jpa.html  #7.11.  LOB Streaming 
+# 
+openjpa.streaming=false
+
+# Validate the data source before using it
+# datasource.testOnBorrow=true
+# datasource.validationQueryTimeoutSec=2
+# This is different per database. See https://stackoverflow.com/questions/10684244/dbcp-validationquery-for-different-databases#10684260
+# datasource.validationQuery=select 1

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/jmx.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/jmx.properties b/dockerfiles/run/guice/jpa-smtp/destination/conf/jmx.properties
new file mode 100644
index 0000000..1c39a17
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/jmx.properties
@@ -0,0 +1,29 @@
+#  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.
+#
+
+#  This template file can be used as example for James Server configuration
+#  DO NOT USE IT AS SUCH AND ADAPT IT TO YOUR NEEDS
+
+#  This template file can be used as example for James Server configuration
+#  DO NOT USE IT AS SUCH AND ADAPT IT TO YOUR NEEDS
+
+# See http://james.apache.org/server/3/config.html for usage
+
+jmx.enabled=true
+jmx.address=127.0.0.1
+jmx.port=9999

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/logback.xml
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/logback.xml b/dockerfiles/run/guice/jpa-smtp/destination/conf/logback.xml
new file mode 100644
index 0000000..1f91099
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/logback.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+        <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
+                <resetJUL>true</resetJUL>
+        </contextListener>
+
+        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+                <encoder>
+                        <pattern>%d{HH:mm:ss.SSS} %highlight([%-5level]) %logger{15} - %msg%n%rEx</pattern>
+                        <immediateFlush>false</immediateFlush>
+                </encoder>
+        </appender>
+
+        <appender name="LOG_FILE" class="ch.qos.logback.core.FileAppender">
+                <file>/logs/james.log</file>
+                <encoder>
+                        <pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
+                        <immediateFlush>false</immediateFlush>
+                </encoder>
+        </appender>
+
+        <root level="INFO">
+                <appender-ref ref="CONSOLE" />
+                <appender-ref ref="LOG_FILE" />
+        </root>
+
+</configuration>

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/mailetcontainer.xml
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/mailetcontainer.xml b/dockerfiles/run/guice/jpa-smtp/destination/conf/mailetcontainer.xml
new file mode 100644
index 0000000..c1e2dd5
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/mailetcontainer.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0"?>
+
+<!--
+  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.
+ -->
+
+<mailetcontainer enableJmx="true">
+
+    <context>
+        <postmaster>postmaster@james.minet.net</postmaster>
+    </context>
+
+    <spooler>
+        <threads>20</threads>
+    </spooler>
+
+    <processors>
+        <processor state="root" enableJmx="true">
+            <mailet match="All" class="PostmasterAlias"/>
+            <mailet match="RelayLimit=30" class="Null"/>
+            <mailet match="All" class="ToProcessor">
+                <processor>transport</processor>
+            </mailet>
+        </processor>
+
+        <processor state="error" enableJmx="true">
+            <mailet match="All" class="Bounce"/>
+            <mailet match="All" class="ToRepository">
+                <repositoryPath>file://var/mail/error/</repositoryPath>
+            </mailet>
+        </processor>
+
+
+        <processor state="transport" enableJmx="true">
+            <matcher name="relay-allowed" match="org.apache.james.mailetcontainer.impl.matchers.Or">
+                <matcher match="SMTPAuthSuccessful"/>
+                <matcher match="SMTPIsAuthNetwork"/>
+                <matcher match="SentByMailet"/>
+            </matcher>
+
+            <mailet match="All" class="RemoveMimeHeader">
+                <name>bcc</name>
+                <onMailetException>ignore</onMailetException>
+            </mailet>
+            <mailet match="All" class="RecipientRewriteTable" />
+            <mailet match="HostIsLocal" class="ToProcessor">
+                <processor>local-address-error</processor>
+                <notice>550 - Requested action not taken: no such user here</notice>
+            </mailet>
+
+            <mailet match="relay-allowed" class="RemoteDelivery">
+                <outgoingQueue>outgoing</outgoingQueue>
+                <delayTime>5000, 100000, 500000</delayTime>
+                <maxRetries>25</maxRetries>
+                <maxDnsProblemRetries>0</maxDnsProblemRetries>
+                <deliveryThreads>10</deliveryThreads>
+                <sendpartial>true</sendpartial>
+                <bounceProcessor>bounces</bounceProcessor>
+            </mailet>
+            <mailet match="All" class="ToProcessor">
+                <processor>relay-denied</processor>
+            </mailet>
+        </processor>
+
+        <processor state="local-address-error" enableJmx="true">
+            <mailet match="All" class="Bounce">
+                <attachment>none</attachment>
+            </mailet>
+            <mailet match="All" class="ToRepository">
+                <repositoryPath>file://var/mail/address-error/</repositoryPath>
+            </mailet>
+        </processor>
+
+        <processor state="relay-denied" enableJmx="true">
+            <mailet match="All" class="Bounce">
+                <attachment>none</attachment>
+            </mailet>
+            <mailet match="All" class="ToRepository">
+                <repositoryPath>file://var/mail/relay-denied/</repositoryPath>
+                <notice>Warning: You are sending an e-mail to a remote server. You must be authentified to perform such an operation</notice>
+            </mailet>
+        </processor>
+
+        <processor state="bounces" enableJmx="true">
+            <mailet match="All" class="DSNBounce">
+                <passThrough>false</passThrough>
+            </mailet>
+        </processor>
+    </processors>
+
+</mailetcontainer>
+
+

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/mailrepositorystore.xml
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/mailrepositorystore.xml b/dockerfiles/run/guice/jpa-smtp/destination/conf/mailrepositorystore.xml
new file mode 100644
index 0000000..acca810
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/mailrepositorystore.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+
+<!--
+  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.
+ -->
+
+<mailrepositorystore>
+    <mailrepositories>
+        <!-- File based repositories.  These repositories store all message data -->
+        <!-- in the file system. -->
+        <mailrepository class="org.apache.james.mailrepository.file.FileMailRepository">
+            <protocols>
+                <protocol>file</protocol>
+            </protocols>
+            <!-- Set if the messages should be listed sorted. False by default -->
+            <config FIFO="false" CACHEKEYS="true"/>
+        </mailrepository>
+    </mailrepositories>
+</mailrepositorystore>

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/recipientrewritetable.xml
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/recipientrewritetable.xml b/dockerfiles/run/guice/jpa-smtp/destination/conf/recipientrewritetable.xml
new file mode 100644
index 0000000..7e7f586
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/recipientrewritetable.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+  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.                                           
+ -->
+
+<!-- The default table for storing James' RecipientRewriteTable mappings. -->
+<recipientrewritetable class="org.apache.james.rrt.jpa.JPARecipientRewriteTable">
+  <recursiveMapping>true</recursiveMapping>
+  <mappingLimit>10</mappingLimit>
+  <mapping>some@domain=some</mapping>
+</recipientrewritetable>
+

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/smtpserver.xml
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/smtpserver.xml b/dockerfiles/run/guice/jpa-smtp/destination/conf/smtpserver.xml
new file mode 100644
index 0000000..e464ca6
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/smtpserver.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+
+<!--
+  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.
+ -->
+
+<smtpservers>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-global</jmxName>
+        <bind>0.0.0.0:25</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <authRequired>false</authRequired>
+        <authorizedAddresses>127.0.0.0/8</authorizedAddresses>
+        <verifyIdentity>true</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>JAMES Linagora's SMTP awesome Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-TLS</jmxName>
+        <bind>0.0.0.0:465</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="true" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <!--
+           Authorize only local users
+        -->
+        <authRequired>true</authRequired>
+        <authorizedAddresses>127.0.0.0/8</authorizedAddresses>
+        <!-- Trust authenticated users -->
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>JAMES Linagora's SMTP awesome Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-authenticated</jmxName>
+        <bind>0.0.0.0:587</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="true">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <!--
+           Authorize only local users
+        -->
+        <authRequired>true</authRequired>
+        <authorizedAddresses>127.0.0.0/8</authorizedAddresses>
+        <!-- Trust authenticated users -->
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>JAMES Linagora's SMTP awesome Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+    </smtpserver>
+</smtpservers>
+
+

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/conf/usersrepository.xml
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/conf/usersrepository.xml b/dockerfiles/run/guice/jpa-smtp/destination/conf/usersrepository.xml
new file mode 100644
index 0000000..e1f1b08
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/conf/usersrepository.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+  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.                                           
+ -->
+
+<usersrepository name="LocalUsers" class="org.apache.james.user.jpa.JPAUsersRepository">
+    <destination URL="file://users/"/>
+    <algorithm>SHA-512</algorithm>
+    <enableVirtualHosting>true</enableVirtualHosting>
+    <enableForwarding>true</enableForwarding>
+</usersrepository>
+

http://git-wip-us.apache.org/repos/asf/james-project/blob/9a96bd51/dockerfiles/run/guice/jpa-smtp/destination/extensions-jars/README.md
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/extensions-jars/README.md b/dockerfiles/run/guice/jpa-smtp/destination/extensions-jars/README.md
new file mode 100644
index 0000000..00f9d15
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/extensions-jars/README.md
@@ -0,0 +1,5 @@
+# Adding Jars to JAMES
+
+The jar in this folder will be added to JAMES classpath when mounted under /root/extensions-jars inside the running container.
+
+You can use it to add your customs Mailets/Matchers.


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


[15/17] james-project git commit: JAMES-2578 Rename ArbitrarySerializable.Factory to Deserializer

Posted by bt...@apache.org.
JAMES-2578 Rename ArbitrarySerializable.Factory to Deserializer


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

Branch: refs/heads/master
Commit: cb91f992ee1a22607b6fcfbbf99846d4c4566f22
Parents: 1ccae90
Author: Gautier DI FOLCO <gd...@linagora.com>
Authored: Tue Oct 30 17:55:10 2018 +0100
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:03:43 2018 +0700

----------------------------------------------------------------------
 .../java/org/apache/mailet/ArbitrarySerializable.java   |  8 ++++----
 .../api/src/main/java/org/apache/mailet/Serializer.java | 12 ++++++------
 .../test/java/org/apache/mailet/AttributeValueTest.java |  4 ++--
 3 files changed, 12 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/cb91f992/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java b/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
index d4ab5ad..2462f32 100644
--- a/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
+++ b/mailet/api/src/main/java/org/apache/mailet/ArbitrarySerializable.java
@@ -24,14 +24,14 @@ import java.util.Optional;
 public interface ArbitrarySerializable<T> {
     public class Serializable<U> {
         private final AttributeValue<?> value;
-        private final Class<? extends Factory<U>> factory;
+        private final Class<? extends Deserializer<U>> factory;
 
-        public Serializable(AttributeValue<?> value, Class<? extends Factory<U>> factory) {
+        public Serializable(AttributeValue<?> value, Class<? extends Deserializer<U>> factory) {
             this.value = value;
             this.factory = factory;
         }
 
-        public Class<? extends Factory<U>> getFactory() {
+        public Class<? extends Deserializer<U>> getDeserializer() {
             return factory;
         }
 
@@ -40,7 +40,7 @@ public interface ArbitrarySerializable<T> {
         }
     }
 
-    public interface Factory<U> {
+    public interface Deserializer<U> {
         Optional<U> deserialize(Serializable<U> serializable);
     }
     

http://git-wip-us.apache.org/repos/asf/james-project/blob/cb91f992/mailet/api/src/main/java/org/apache/mailet/Serializer.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
index 192d132..016472a 100644
--- a/mailet/api/src/main/java/org/apache/mailet/Serializer.java
+++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
@@ -271,7 +271,7 @@ public interface Serializer<T> {
         public JsonNode serialize(T serializable) {
             ArbitrarySerializable.Serializable<T> serialized = serializable.serialize();
             ObjectNode serializedJson = JsonNodeFactory.instance.objectNode();
-            serializedJson.put("factory", serialized.getFactory().getName());
+            serializedJson.put("deserializer", serialized.getDeserializer().getName());
             serializedJson.replace("value", serialized.getValue().toJson());
             return serializedJson;
         }
@@ -285,7 +285,7 @@ public interface Serializer<T> {
         }
 
         public Optional<T> instantiate(ObjectNode fields) {
-            return Optional.ofNullable(fields.get("factory"))
+            return Optional.ofNullable(fields.get("deserializer"))
                 .flatMap(serializer ->
                     Optional.ofNullable(fields.get("value"))
                         .flatMap(value -> deserialize(serializer.asText(), AttributeValue.fromJson(value))));
@@ -294,10 +294,10 @@ public interface Serializer<T> {
         @SuppressWarnings("unchecked")
         private Optional<T> deserialize(String serializer, AttributeValue<?> value) {
             try {
-                Class<?> factoryClass = Class.forName(serializer);
-                if (ArbitrarySerializable.Factory.class.isAssignableFrom(factoryClass)) {
-                    ArbitrarySerializable.Factory<T> factory = (ArbitrarySerializable.Factory<T>) factoryClass.newInstance();
-                    return factory.deserialize(new ArbitrarySerializable.Serializable<>(value, (Class<ArbitrarySerializable.Factory<T>>) factoryClass));
+                Class<?> deserializerClass = Class.forName(serializer);
+                if (ArbitrarySerializable.Deserializer.class.isAssignableFrom(deserializerClass)) {
+                    ArbitrarySerializable.Deserializer<T> deserializer = (ArbitrarySerializable.Deserializer<T>) deserializerClass.newInstance();
+                    return deserializer.deserialize(new ArbitrarySerializable.Serializable<>(value, (Class<ArbitrarySerializable.Deserializer<T>>) deserializerClass));
                 }
             } catch (Exception e) {
                 LOGGER.error("Error while deserializing using serializer {} and value {}", serializer, value, e);

http://git-wip-us.apache.org/repos/asf/james-project/blob/cb91f992/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
index d1189d1..ef92c6b 100644
--- a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
@@ -342,7 +342,7 @@ class AttributeValueTest {
         void fromJsonStringShouldReturnQueueSerializableAttributeValueWhenQueueSerializable() throws Exception {
             AttributeValue<TestArbitrarySerializable> expected = AttributeValue.of(new TestArbitrarySerializable(42));
 
-            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"ArbitrarySerializableSerializer\",\"value\":{\"factory\":\"org.apache.mailet.AttributeValueTest$TestArbitrarySerializable$Factory\",\"value\":{\"serializer\":\"IntSerializer\",\"value\":42}}}");
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"ArbitrarySerializableSerializer\",\"value\":{\"deserializer\":\"org.apache.mailet.AttributeValueTest$TestArbitrarySerializable$Factory\",\"value\":{\"serializer\":\"IntSerializer\",\"value\":42}}}");
 
             assertThat(actual).isEqualTo(expected);
         }
@@ -572,7 +572,7 @@ class AttributeValueTest {
     }
 
     private static class TestArbitrarySerializable implements ArbitrarySerializable<TestArbitrarySerializable> {
-        public static class Factory implements ArbitrarySerializable.Factory<TestArbitrarySerializable> {
+        public static class Factory implements ArbitrarySerializable.Deserializer<TestArbitrarySerializable> {
             @Override
             public Optional<TestArbitrarySerializable> deserialize(Serializable<TestArbitrarySerializable> serializable) {
                 return Optional.of(serializable.getValue().value())


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


[14/17] james-project git commit: JAMES-2578 NumericNode is too vague

Posted by bt...@apache.org.
JAMES-2578 NumericNode is too vague

Our integer/long AttributeSerializer should reject float values.


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

Branch: refs/heads/master
Commit: 77f4ecb87a9928f8941ec8a80f535367324897b9
Parents: 94df1ac
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 30 14:17:17 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:03:38 2018 +0700

----------------------------------------------------------------------
 .../main/java/org/apache/mailet/Serializer.java | 13 ++++--
 .../org/apache/mailet/AttributeValueTest.java   | 49 ++++++++++++++++++++
 2 files changed, 57 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/77f4ecb8/mailet/api/src/main/java/org/apache/mailet/Serializer.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
index ffa0069..192d132 100644
--- a/mailet/api/src/main/java/org/apache/mailet/Serializer.java
+++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
@@ -48,7 +48,6 @@ import com.fasterxml.jackson.databind.node.IntNode;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.LongNode;
 import com.fasterxml.jackson.databind.node.NullNode;
-import com.fasterxml.jackson.databind.node.NumericNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.node.TextNode;
 import com.google.common.collect.ImmutableList;
@@ -157,7 +156,7 @@ public interface Serializer<T> {
 
         @Override
         public Optional<Integer> deserialize(JsonNode json) {
-            if (json instanceof NumericNode) {
+            if (json instanceof IntNode) {
                 return Optional.of(json.asInt());
             } else {
                 return Optional.empty();
@@ -185,8 +184,10 @@ public interface Serializer<T> {
 
         @Override
         public Optional<Long> deserialize(JsonNode json) {
-            if (json instanceof NumericNode) {
+            if (json instanceof LongNode) {
                 return Optional.of(json.asLong());
+            } else if (json instanceof IntNode) {
+                return Optional.of(Long.valueOf(json.asInt()));
             } else {
                 return Optional.empty();
             }
@@ -213,7 +214,9 @@ public interface Serializer<T> {
 
         @Override
         public Optional<Float> deserialize(JsonNode json) {
-            if (json instanceof NumericNode) {
+            if (json instanceof FloatNode) {
+                return Optional.of(json.floatValue());
+            } else if (json instanceof DoubleNode) {
                 return Optional.of(json.floatValue());
             } else {
                 return Optional.empty();
@@ -241,7 +244,7 @@ public interface Serializer<T> {
 
         @Override
         public Optional<Double> deserialize(JsonNode json) {
-            if (json instanceof NumericNode) {
+            if (json instanceof DoubleNode || json instanceof FloatNode) {
                 return Optional.of(json.asDouble());
             } else {
                 return Optional.empty();

http://git-wip-us.apache.org/repos/asf/james-project/blob/77f4ecb8/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
index 95cb0c2..d1189d1 100644
--- a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
@@ -172,6 +172,19 @@ class AttributeValueTest {
             assertThatIllegalStateException()
                 .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"IntSerializer\",\"value\": []}"));
         }
+
+        @Test
+        void fromJsonStringShouldThrowOnFloatJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"IntSerializer\",\"value\": 42.0}"));
+        }
+
+        @Test
+        void fromJsonStringShouldThrowOnLongJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"IntSerializer\",\"value\": 2147483648}"));
+            // Int.MAX_VALUE + 1
+        }
     }
 
     @Nested
@@ -185,6 +198,15 @@ class AttributeValueTest {
 
             assertThat(actual).isEqualTo(expected);
         }
+        @Test
+        void longShouldBeSerializedAndBackForLongMaxValue() {
+            AttributeValue<Long> expected = AttributeValue.of(Long.MAX_VALUE);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
 
         @Test
         void nullLongShouldThrowAnException() {
@@ -206,6 +228,12 @@ class AttributeValueTest {
             assertThatIllegalStateException()
                 .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"LongSerializer\",\"value\": []}"));
         }
+
+        @Test
+        void fromJsonStringShouldThrowOnFloatJson() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"LongSerializer\",\"value\": 42.0}"));
+        }
     }
 
     @Nested
@@ -240,6 +268,12 @@ class AttributeValueTest {
             assertThatIllegalStateException()
                 .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"FloatSerializer\",\"value\": []}"));
         }
+
+        @Test
+        void fromJsonStringShouldThrowOnIntNode() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"FloatSerializer\",\"value\": 1}"));
+        }
     }
 
     @Nested
@@ -253,6 +287,15 @@ class AttributeValueTest {
 
             assertThat(actual).isEqualTo(expected);
         }
+        @Test
+        void doubleShouldBeSerializedAndBackForMaxValue() {
+            AttributeValue<Double> expected = AttributeValue.of(Double.MAX_VALUE);
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
 
         @Test
         void nullDoubleShouldThrowAnException() {
@@ -274,6 +317,12 @@ class AttributeValueTest {
             assertThatIllegalStateException()
                 .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"DoubleSerializer\",\"value\": []}"));
         }
+
+        @Test
+        void fromJsonStringShouldThrowOnIntNode() {
+            assertThatIllegalStateException()
+                .isThrownBy(() -> AttributeValue.fromJsonString("{\"serializer\":\"DoubleSerializer\",\"value\": 1}"));
+        }
     }
 
     @Nested


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


[16/17] james-project git commit: JAMES-2578 Add tests for AttributeValue.ofSerializable

Posted by bt...@apache.org.
JAMES-2578 Add tests for AttributeValue.ofSerializable


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

Branch: refs/heads/master
Commit: ccd822676a0dda5d286f98d98d2fe6a41e1fe445
Parents: cb91f99
Author: Gautier DI FOLCO <gd...@linagora.com>
Authored: Tue Oct 30 17:57:34 2018 +0100
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:03:43 2018 +0700

----------------------------------------------------------------------
 .../java/org/apache/mailet/AttributeValue.java  |  1 +
 .../org/apache/mailet/AttributeValueTest.java   | 51 ++++++++++++++++++++
 2 files changed, 52 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ccd82267/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
index 638dd34..6933bf8 100644
--- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -105,6 +105,7 @@ public class AttributeValue<T> {
     }
 
     public static AttributeValue<Serializable> ofSerializable(Serializable value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, new Serializer.FSTSerializer());
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ccd82267/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
index ef92c6b..3ce1d3f 100644
--- a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
@@ -547,6 +547,34 @@ class AttributeValueTest {
         }
     }
 
+    @Nested
+    class SerializableSerialization {
+        @Test
+        void filledSerializabletrueShouldBeSerializedAndBack() {
+            AttributeValue<java.io.Serializable> expected = AttributeValue.ofSerializable(new TestSerializable("me"));
+
+            JsonNode json = expected.toJson();
+            AttributeValue<?> actual = AttributeValue.fromJson(json);
+
+            assertThat(actual).isEqualTo(expected);
+        }
+
+        @Test
+        void nullSerializableShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.ofSerializable((java.io.Serializable) null));
+        }
+
+        @Test
+        void fromJsonStringShouldReturnBooleanAttributeValueWhenBoolean() throws Exception {
+            AttributeValue<java.io.Serializable> expected = AttributeValue.ofSerializable(new TestSerializable("me"));
+
+            AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"FSTSerializer\",\"value\":{\"typ\":\"org.apache.mailet.AttributeValueTest$TestSerializable\",\"obj\":{\"name\":\"me\"}}}");
+
+            assertThat(actual).isEqualTo(expected);
+        }
+    }
+
     @Test
     void fromJsonStringShouldThrowOnUnknownSerializer() {
         assertThatIllegalStateException()
@@ -608,4 +636,27 @@ class AttributeValueTest {
             return Objects.hash(value);
         }
     }
+
+    private static class TestSerializable implements java.io.Serializable {
+        private final String name;
+
+        public TestSerializable(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public final boolean equals(Object o) {
+            if (o instanceof TestSerializable) {
+                TestSerializable that = (TestSerializable) o;
+
+                return Objects.equals(this.name, that.name);
+            }
+            return false;
+        }
+
+        @Override
+        public final int hashCode() {
+            return Objects.hash(name);
+        }
+    }
 }


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


[07/17] james-project git commit: JAMES-2578 Do not allow nulls

Posted by bt...@apache.org.
JAMES-2578 Do not allow nulls


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

Branch: refs/heads/master
Commit: c1f4ba5cda6c31fb6d22c351dce9c868dc67d64e
Parents: dbee6f7
Author: Gautier DI FOLCO <gd...@linagora.com>
Authored: Mon Oct 29 14:44:29 2018 +0100
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 1 11:02:43 2018 +0700

----------------------------------------------------------------------
 .../java/org/apache/mailet/AttributeValue.java  |  12 +++
 .../org/apache/mailet/AttributeValueTest.java   | 107 ++++++-------------
 2 files changed, 43 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c1f4ba5c/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
index 4a548b3..6bf3a6e 100644
--- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -36,6 +36,7 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
 
 /** 
  * Strong typing for attribute value, which represents the value of an attribute stored in a mail.
@@ -46,44 +47,54 @@ public class AttributeValue<T> {
     private static final Logger LOGGER = LoggerFactory.getLogger(AttributeValue.class);
 
     public static AttributeValue<Boolean> of(Boolean value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, Serializer.BOOLEAN_SERIALIZER);
     }
 
     public static AttributeValue<String> of(String value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, Serializer.STRING_SERIALIZER);
     }
 
     public static AttributeValue<Integer> of(Integer value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, Serializer.INT_SERIALIZER);
     }
 
     public static AttributeValue<Long> of(Long value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, Serializer.LONG_SERIALIZER);
     }
 
     public static AttributeValue<Float> of(Float value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, Serializer.FLOAT_SERIALIZER);
     }
 
     public static AttributeValue<Double> of(Double value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, Serializer.DOUBLE_SERIALIZER);
     }
 
     public static <T extends ArbitrarySerializable<T>> AttributeValue<T> of(T value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, new Serializer.ArbitrarySerializableSerializer<>());
     }
 
     public static AttributeValue<URL> of(URL value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, Serializer.URL_SERIALIZER);
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
     public static AttributeValue<Collection<AttributeValue<?>>> of(Collection<AttributeValue<?>> value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, new Serializer.CollectionSerializer());
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
     public static AttributeValue<Map<String, AttributeValue<?>>> of(Map<String, AttributeValue<?>> value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, new Serializer.MapSerializer());
     }
 
@@ -93,6 +104,7 @@ public class AttributeValue<T> {
 
     @SuppressWarnings("unchecked")
     public static AttributeValue<?> ofAny(Object value) {
+        Preconditions.checkNotNull(value, "value should not be null");
         if (value instanceof Boolean) {
             return of((Boolean) value);
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/c1f4ba5c/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
----------------------------------------------------------------------
diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
index 45cfede..dd3f43f 100644
--- a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
+++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java
@@ -20,6 +20,7 @@ package org.apache.mailet;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.assertj.core.api.Assertions.assertThatNullPointerException;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.net.MalformedURLException;
@@ -29,7 +30,6 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
@@ -47,10 +47,9 @@ class AttributeValueTest {
     }
 
     @Test
-    void ofShouldAcceptNullValue() {
-        AttributeValue<String> attributeValue = AttributeValue.of((String) null);
-
-        assertThat(attributeValue.getValue()).isNull();
+    void ofShouldThrowAnExceptionOnNullValue() {
+        assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((String) null));
     }
 
     @Nested
@@ -75,15 +74,10 @@ class AttributeValueTest {
             assertThat(actual).isEqualTo(expected);
         }
 
-        @Disabled("Failing!")
         @Test
-        void nullStringShouldBeSerializedAndBack() {
-            AttributeValue<String> expected = AttributeValue.of((String) null);
-
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullStringShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((String) null));
         }
 
         @Test
@@ -124,15 +118,10 @@ class AttributeValueTest {
             assertThat(actual).isEqualTo(expected);
         }
 
-        @Disabled("Failing")
         @Test
-        void nullBooleanShouldBeSerializedAndBack() {
-            AttributeValue<Boolean> expected = AttributeValue.of((Boolean) null);
-
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullBooleanShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((Boolean) null));
         }
 
         @Test
@@ -163,15 +152,10 @@ class AttributeValueTest {
             assertThat(actual).isEqualTo(expected);
         }
 
-        @Disabled("Failing")
         @Test
-        void nullIntShouldBeSerializedAndBack() {
-            AttributeValue<Integer> expected = AttributeValue.of((Integer) null);
-
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullIntShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((Integer) null));
         }
 
         @Test
@@ -202,15 +186,10 @@ class AttributeValueTest {
             assertThat(actual).isEqualTo(expected);
         }
 
-        @Disabled("Failing")
         @Test
-        void nullLongShouldBeSerializedAndBack() {
-            AttributeValue<Long> expected = AttributeValue.of((Long) null);
-
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullLongShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((Long) null));
         }
 
         @Test
@@ -241,15 +220,10 @@ class AttributeValueTest {
             assertThat(actual).isEqualTo(expected);
         }
 
-        @Disabled("Failing")
         @Test
-        void nullFloatShouldBeSerializedAndBack() {
-            AttributeValue<Float> expected = AttributeValue.of((Float) null);
-
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullFloatShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((Float) null));
         }
 
         @Test
@@ -280,15 +254,10 @@ class AttributeValueTest {
             assertThat(actual).isEqualTo(expected);
         }
 
-        @Disabled("Failing")
         @Test
-        void nullDoubleShouldBeSerializedAndBack() {
-            AttributeValue<Double> expected = AttributeValue.of((Double) null);
-
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullDoubleShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((Double) null));
         }
 
         @Test
@@ -342,15 +311,10 @@ class AttributeValueTest {
             assertThat(actual).isEqualTo(expected);
         }
 
-        @Disabled("Failing!")
         @Test
-        void nullURLShouldBeSerializedAndBack() {
-            AttributeValue<URL> expected = AttributeValue.of((URL) null);
-
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullURLShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((URL) null));
         }
 
         @Test
@@ -377,15 +341,10 @@ class AttributeValueTest {
 
     @Nested
     class ListSerialization {
-        @Disabled("Failing!")
         @Test
-        void nullStringListShouldBeSerializedAndBack() {
-            AttributeValue<?> expected = AttributeValue.ofAny((List<String>) null);
-
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullStringListShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.ofAny((List<String>) null));
         }
 
         @Test
@@ -435,14 +394,10 @@ class AttributeValueTest {
 
     @Nested
     class MapSerialization {
-        @Disabled("Failing!")
         @Test
-        void nullMapShouldBeSerializedAndBack() {
-            AttributeValue<?> expected = AttributeValue.of((Map) null);
-            JsonNode json = expected.toJson();
-            AttributeValue<?> actual = AttributeValue.fromJson(json);
-
-            assertThat(actual).isEqualTo(expected);
+        void nullMapShouldThrowAnException() {
+            assertThatNullPointerException().
+                isThrownBy(() -> AttributeValue.of((Map) null));
         }
 
         @Test


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