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/06/14 08:35:19 UTC

[01/13] james-project git commit: MAILBOX-341 Adding board for Mailbox listeners

Repository: james-project
Updated Branches:
  refs/heads/master 946c68bea -> cf143b6e8


MAILBOX-341 Adding board for Mailbox listeners


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

Branch: refs/heads/master
Commit: 7b6bfb868cbfee6c9720ef389a447aa1139abf51
Parents: 946c68b
Author: benwa <bt...@linagora.com>
Authored: Thu Jun 14 13:46:39 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:13:37 2018 +0700

----------------------------------------------------------------------
 .../MailboxListeners-1528958667486.json         | 784 +++++++++++++++++++
 grafana-reporting/README.md                     |   1 +
 src/site/xdoc/server/metrics.xml                |   1 +
 3 files changed, 786 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/7b6bfb86/grafana-reporting/MailboxListeners-1528958667486.json
----------------------------------------------------------------------
diff --git a/grafana-reporting/MailboxListeners-1528958667486.json b/grafana-reporting/MailboxListeners-1528958667486.json
new file mode 100644
index 0000000..7f6f0d4
--- /dev/null
+++ b/grafana-reporting/MailboxListeners-1528958667486.json
@@ -0,0 +1,784 @@
+{
+  "__inputs": [
+    {
+      "name": "DS_JAMES_ES",
+      "label": "james es",
+      "description": "",
+      "type": "datasource",
+      "pluginId": "elasticsearch",
+      "pluginName": "Elasticsearch"
+    }
+  ],
+  "__requires": [
+    {
+      "type": "datasource",
+      "id": "elasticsearch",
+      "name": "Elasticsearch",
+      "version": "3.0.0"
+    },
+    {
+      "type": "grafana",
+      "id": "grafana",
+      "name": "Grafana",
+      "version": "4.1.2"
+    },
+    {
+      "type": "panel",
+      "id": "graph",
+      "name": "Graph",
+      "version": ""
+    }
+  ],
+  "annotations": {
+    "list": []
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "hideControls": false,
+  "id": null,
+  "links": [],
+  "refresh": false,
+  "rows": [
+    {
+      "collapse": false,
+      "height": 431,
+      "panels": [
+        {
+          "aliasColors": {},
+          "bars": false,
+          "datasource": "${DS_JAMES_ES}",
+          "fill": 1,
+          "id": 23,
+          "legend": {
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "span": 4,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "dsType": "elasticsearch",
+              "metrics": [
+                {
+                  "field": "p99",
+                  "id": "1",
+                  "meta": {},
+                  "pipelineAgg": "3",
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p50",
+                  "id": "3",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p75",
+                  "id": "4",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p95",
+                  "id": "5",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                }
+              ],
+              "query": "name:mailbox-listener-ElasticSearchListeningMessageSearchIndex",
+              "refId": "A",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeShift": null,
+          "title": "ElasticSearch indexing",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "ms",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ]
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "datasource": "${DS_JAMES_ES}",
+          "fill": 1,
+          "id": 2,
+          "legend": {
+            "avg": true,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "span": 4,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "dsType": "elasticsearch",
+              "metrics": [
+                {
+                  "field": "p99",
+                  "id": "1",
+                  "meta": {},
+                  "pipelineAgg": "3",
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p50",
+                  "id": "3",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p75",
+                  "id": "4",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p95",
+                  "id": "5",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                }
+              ],
+              "query": "name:mailbox-listener-ElasticSearchQuotaMailboxListener",
+              "refId": "A",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeShift": null,
+          "title": "Quota Search ElasticSearch indexing",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "ms",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ]
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "datasource": "${DS_JAMES_ES}",
+          "fill": 1,
+          "id": 11,
+          "legend": {
+            "avg": true,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "span": 4,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "dsType": "elasticsearch",
+              "metrics": [
+                {
+                  "field": "p99",
+                  "id": "1",
+                  "meta": {},
+                  "pipelineAgg": "3",
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p50",
+                  "id": "3",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p75",
+                  "id": "4",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p95",
+                  "id": "5",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                }
+              ],
+              "query": "name:mailbox-listener-SpamAssassinListener",
+              "refId": "A",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeShift": null,
+          "title": "SpamAssassin HAM/SPAM reporting",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "ms",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ]
+        }
+      ],
+      "repeat": null,
+      "repeatIteration": null,
+      "repeatRowId": null,
+      "showTitle": false,
+      "title": "Dashboard Row",
+      "titleSize": "h6"
+    },
+    {
+      "collapse": false,
+      "height": 416,
+      "panels": [
+        {
+          "aliasColors": {},
+          "bars": false,
+          "datasource": "${DS_JAMES_ES}",
+          "fill": 1,
+          "id": 10,
+          "legend": {
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "span": 4,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "dsType": "elasticsearch",
+              "metrics": [
+                {
+                  "field": "p99",
+                  "id": "1",
+                  "meta": {},
+                  "pipelineAgg": "3",
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p50",
+                  "id": "3",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p75",
+                  "id": "4",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p95",
+                  "id": "5",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                }
+              ],
+              "query": "name:mailbox-listener-ListeningCurrentQuotaUpdater",
+              "refId": "A",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeShift": null,
+          "title": "Quota updates",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "ms",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ]
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "datasource": "${DS_JAMES_ES}",
+          "fill": 1,
+          "id": 6,
+          "legend": {
+            "avg": true,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "span": 4,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "dsType": "elasticsearch",
+              "metrics": [
+                {
+                  "field": "p99",
+                  "id": "1",
+                  "meta": {},
+                  "pipelineAgg": "3",
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p50",
+                  "id": "3",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p75",
+                  "id": "4",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p95",
+                  "id": "5",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                }
+              ],
+              "query": "name:mailbox-listener-MailboxAnnotationListener",
+              "refId": "A",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeShift": null,
+          "title": "Mailbox annotations",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "ms",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ]
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "datasource": "${DS_JAMES_ES}",
+          "fill": 1,
+          "id": 24,
+          "legend": {
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "span": 4,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "dsType": "elasticsearch",
+              "metrics": [
+                {
+                  "field": "p99",
+                  "id": "1",
+                  "meta": {},
+                  "pipelineAgg": "3",
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p50",
+                  "id": "3",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p75",
+                  "id": "4",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "p95",
+                  "id": "5",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                }
+              ],
+              "query": "name: mailbox-listener-QuotaThresholdCrossingListener",
+              "refId": "A",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeShift": null,
+          "title": "Quota mailing",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "ms",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ]
+        }
+      ],
+      "repeat": null,
+      "repeatIteration": null,
+      "repeatRowId": null,
+      "showTitle": false,
+      "title": "Dashboard Row",
+      "titleSize": "h6"
+    }
+  ],
+  "schemaVersion": 14,
+  "style": "dark",
+  "tags": [],
+  "templating": {
+    "list": []
+  },
+  "time": {
+    "from": "now-24h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "browser",
+  "title": "MailboxListeners",
+  "version": 6
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/7b6bfb86/grafana-reporting/README.md
----------------------------------------------------------------------
diff --git a/grafana-reporting/README.md b/grafana-reporting/README.md
index 95a5491..a628536 100644
--- a/grafana-reporting/README.md
+++ b/grafana-reporting/README.md
@@ -34,3 +34,4 @@ Note that you need to run a guice version of James.
  - Cassandra driver statistics
  - Tika HTTP client statistics
  - SpamAssassin TCP client statistics
+ - Mailbox listeners statistics

http://git-wip-us.apache.org/repos/asf/james-project/blob/7b6bfb86/src/site/xdoc/server/metrics.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/server/metrics.xml b/src/site/xdoc/server/metrics.xml
index 31150fc..433d62f 100644
--- a/src/site/xdoc/server/metrics.xml
+++ b/src/site/xdoc/server/metrics.xml
@@ -65,6 +65,7 @@
                     <li>Cassandra Java driver metrics</li>
                     <li>Tika HTTP client statistics</li>
                     <li>SpamAssassin TCP client statistics</li>
+                    <li>Mailbox listeners statistics time percentiles</li>
                 </ul>
 
                 Retrieve <a href="https://github.com/apache/james-project/tree/master/grafana-reporting">available boards</a> for Grafana.


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


[07/13] james-project git commit: JAMES-2418 Provide MailRepositoryUrlStore JPA implementation

Posted by bt...@apache.org.
JAMES-2418 Provide MailRepositoryUrlStore JPA implementation


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

Branch: refs/heads/master
Commit: 0f7ec3c131a211220424645d628f32600f3ed232
Parents: c2dadb2
Author: benwa <bt...@linagora.com>
Authored: Fri Jun 8 13:28:14 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:16:59 2018 +0700

----------------------------------------------------------------------
 .../james/backends/jpa/TransactionRunner.java   | 22 ++++++-
 .../james/backends/jpa/JpaTestCluster.java      |  1 +
 .../src/main/resources/META-INF/persistence.xml |  1 +
 .../src/main/resources/META-INF/persistence.xml |  1 +
 .../src/main/resources/META-INF/persistence.xml |  1 +
 .../org/apache/james/JPAJamesServerTest.java    |  3 +-
 server/data/data-jpa/pom.xml                    | 34 ++++++++--
 .../jpa/JPAMailRepositoryUrlStore.java          | 67 ++++++++++++++++++++
 .../apache/james/mailrepository/jpa/JPAUrl.java | 65 +++++++++++++++++++
 .../src/main/resources/META-INF/persistence.xml |  1 +
 .../jpa/JPAMailRepositoryUrlStoreExtension.java | 47 ++++++++++++++
 .../jpa/JPAMailRepositoryUrlStoreTest.java      | 28 ++++++++
 12 files changed, 263 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/backends-common/jpa/src/main/java/org/apache/james/backends/jpa/TransactionRunner.java
----------------------------------------------------------------------
diff --git a/backends-common/jpa/src/main/java/org/apache/james/backends/jpa/TransactionRunner.java b/backends-common/jpa/src/main/java/org/apache/james/backends/jpa/TransactionRunner.java
index 0b3c914..dae6f2e 100644
--- a/backends-common/jpa/src/main/java/org/apache/james/backends/jpa/TransactionRunner.java
+++ b/backends-common/jpa/src/main/java/org/apache/james/backends/jpa/TransactionRunner.java
@@ -20,6 +20,7 @@
 package org.apache.james.backends.jpa;
 
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
@@ -32,6 +33,7 @@ import org.slf4j.LoggerFactory;
 public class TransactionRunner {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(TransactionRunner.class);
+    public static final Function<PersistenceException, Object> IGNORE_EXCEPTION = e -> null;
 
     private final EntityManagerFactory entityManagerFactory;
 
@@ -40,17 +42,35 @@ public class TransactionRunner {
     }
 
     public void run(Consumer<EntityManager> runnable) {
+        runAndRetrieveResult(entityManager -> {
+                runnable.accept(entityManager);
+                return null;
+            },
+            IGNORE_EXCEPTION);
+    }
+
+    public <T> T runAndRetrieveResult(Function<EntityManager, T> toResult) {
+        return runAndRetrieveResult(toResult,
+            e -> {
+                throw new RuntimeException(e);
+            });
+    }
+
+    public <T> T runAndRetrieveResult(Function<EntityManager, T> toResult,
+                                      Function<PersistenceException, T> errorHandler) {
         EntityManager entityManager = entityManagerFactory.createEntityManager();
         EntityTransaction transaction = entityManager.getTransaction();
         try {
             transaction.begin();
-            runnable.accept(entityManager);
+            T result = toResult.apply(entityManager);
             transaction.commit();
+            return result;
         } catch (PersistenceException e) {
             LOGGER.warn("Could not execute transaction", e);
             if (transaction.isActive()) {
                 transaction.rollback();
             }
+            return errorHandler.apply(e);
         } finally {
             entityManager.close();
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/backends-common/jpa/src/test/java/org/apache/james/backends/jpa/JpaTestCluster.java
----------------------------------------------------------------------
diff --git a/backends-common/jpa/src/test/java/org/apache/james/backends/jpa/JpaTestCluster.java b/backends-common/jpa/src/test/java/org/apache/james/backends/jpa/JpaTestCluster.java
index e845801..fc96085 100644
--- a/backends-common/jpa/src/test/java/org/apache/james/backends/jpa/JpaTestCluster.java
+++ b/backends-common/jpa/src/test/java/org/apache/james/backends/jpa/JpaTestCluster.java
@@ -22,6 +22,7 @@ package org.apache.james.backends.jpa;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/app/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/server/app/src/main/resources/META-INF/persistence.xml b/server/app/src/main/resources/META-INF/persistence.xml
index 4688e39..6f68e20 100644
--- a/server/app/src/main/resources/META-INF/persistence.xml
+++ b/server/app/src/main/resources/META-INF/persistence.xml
@@ -33,6 +33,7 @@
         <class>org.apache.james.mailbox.jpa.mail.model.JPAMailboxAnnotation</class>
         <class>org.apache.james.mailbox.jpa.user.model.JPASubscription</class>
         <class>org.apache.james.domainlist.jpa.model.JPADomain</class>
+        <class>org.apache.james.mailrepository.jpa.JPAUrl</class>
         <class>org.apache.james.user.jpa.model.JPAUser</class>
         <class>org.apache.james.rrt.jpa.model.JPARecipientRewrite</class>
         <class>org.apache.james.mailbox.jpa.quota.model.MaxDomainMessageCount</class>

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/container/guice/jpa-guice/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/jpa-guice/src/main/resources/META-INF/persistence.xml b/server/container/guice/jpa-guice/src/main/resources/META-INF/persistence.xml
index 9f00fa9..fd1711d 100644
--- a/server/container/guice/jpa-guice/src/main/resources/META-INF/persistence.xml
+++ b/server/container/guice/jpa-guice/src/main/resources/META-INF/persistence.xml
@@ -32,6 +32,7 @@
         <class>org.apache.james.mailbox.jpa.user.model.JPASubscription</class>
 
         <class>org.apache.james.domainlist.jpa.model.JPADomain</class>
+        <class>org.apache.james.mailrepository.jpa.JPAUrl</class>
         <class>org.apache.james.user.jpa.model.JPAUser</class>
         <class>org.apache.james.rrt.jpa.model.JPARecipientRewrite</class>
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/container/guice/jpa-smtp/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/jpa-smtp/src/main/resources/META-INF/persistence.xml b/server/container/guice/jpa-smtp/src/main/resources/META-INF/persistence.xml
index d82c703..0656779 100644
--- a/server/container/guice/jpa-smtp/src/main/resources/META-INF/persistence.xml
+++ b/server/container/guice/jpa-smtp/src/main/resources/META-INF/persistence.xml
@@ -25,6 +25,7 @@
 
     <persistence-unit name="Global" transaction-type="RESOURCE_LOCAL">
         <class>org.apache.james.domainlist.jpa.model.JPADomain</class>
+        <class>org.apache.james.mailrepository.jpa.JPAUrl</class>
         <class>org.apache.james.user.jpa.model.JPAUser</class>
         <class>org.apache.james.rrt.jpa.model.JPARecipientRewrite</class>
         <properties>

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/container/guice/jpa-smtp/src/test/java/org/apache/james/JPAJamesServerTest.java
----------------------------------------------------------------------
diff --git a/server/container/guice/jpa-smtp/src/test/java/org/apache/james/JPAJamesServerTest.java b/server/container/guice/jpa-smtp/src/test/java/org/apache/james/JPAJamesServerTest.java
index 93a74f1..87962dd 100644
--- a/server/container/guice/jpa-smtp/src/test/java/org/apache/james/JPAJamesServerTest.java
+++ b/server/container/guice/jpa-smtp/src/test/java/org/apache/james/JPAJamesServerTest.java
@@ -31,6 +31,7 @@ import javax.persistence.EntityManagerFactory;
 
 import org.apache.james.backends.jpa.JpaTestCluster;
 import org.apache.james.domainlist.jpa.model.JPADomain;
+import org.apache.james.mailrepository.jpa.JPAUrl;
 import org.apache.james.rrt.jpa.model.JPARecipientRewrite;
 import org.apache.james.server.core.configuration.Configuration;
 import org.apache.james.user.jpa.model.JPAUser;
@@ -66,7 +67,7 @@ public class JPAJamesServerTest {
                 .overrideWith(
                         new TestJPAConfigurationModule(),
                         (binder) -> binder.bind(EntityManagerFactory.class)
-                            .toInstance(JpaTestCluster.create(JPAUser.class, JPADomain.class, JPARecipientRewrite.class)
+                            .toInstance(JpaTestCluster.create(JPAUser.class, JPADomain.class, JPARecipientRewrite.class, JPAUrl.class)
                                     .getEntityManagerFactory()));
     }
     

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/data/data-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/pom.xml b/server/data/data-jpa/pom.xml
index eab6334..7bb4925 100644
--- a/server/data/data-jpa/pom.xml
+++ b/server/data/data-jpa/pom.xml
@@ -49,6 +49,12 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-data-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-data-library</artifactId>
         </dependency>
         <dependency>
@@ -109,13 +115,23 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.assertj</groupId>
-            <artifactId>assertj-core</artifactId>
+            <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>
@@ -137,7 +153,10 @@
                 <artifactId>openjpa-maven-plugin</artifactId>
                 <version>2.4.2</version>
                 <configuration>
-                    <includes>org/apache/james/user/jpa/model/JPAUser.class,org/apache/james/rrt/jpa/model/JPARecipientRewrite.class,org/apache/james/domainlist/jpa/model/JPADomain.class</includes>
+                    <includes>org/apache/james/user/jpa/model/JPAUser.class,
+                        org/apache/james/rrt/jpa/model/JPARecipientRewrite.class,
+                        org/apache/james/domainlist/jpa/model/JPADomain.class,
+                        org/apache/james/mailrepository/jpa/JPAUrl.class</includes>
                     <addDefaultConstructor>true</addDefaultConstructor>
                     <enforcePropertyRestrictions>true</enforcePropertyRestrictions>
                     <toolProperties>
@@ -147,7 +166,10 @@
                         </property>
                         <property>
                             <name>metaDataFactory</name>
-                            <value>jpa(Types=org.apache.james.user.jpa.model.JPAUser;org.apache.james.rrt.jpa.model.JPARecipientRewrite;org.apache.james.domainlist.jpa.model.JPADomain)</value>
+                            <value>jpa(Types=org.apache.james.user.jpa.model.JPAUser;
+                                org.apache.james.rrt.jpa.model.JPARecipientRewrite;
+                                org.apache.james.domainlist.jpa.model.JPADomain;
+                                org.apache.james.mailrepository.jpa.JPAUrl)</value>
                         </property>
                     </toolProperties>
                 </configuration>

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
new file mode 100644
index 0000000..576b774
--- /dev/null
+++ b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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.mailrepository.jpa;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.james.backends.jpa.TransactionRunner;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
+
+import com.github.steveash.guavate.Guavate;
+
+public class JPAMailRepositoryUrlStore implements MailRepositoryUrlStore {
+    private final TransactionRunner transactionRunner;
+
+    @Inject
+    public JPAMailRepositoryUrlStore(EntityManagerFactory entityManagerFactory) {
+        this.transactionRunner = new TransactionRunner(entityManagerFactory);
+    }
+
+    @Override
+    public void add(MailRepositoryUrl url) {
+        transactionRunner.run(entityManager ->
+            entityManager.merge(JPAUrl.from(url)));
+    }
+
+    @Override
+    public Set<MailRepositoryUrl> list() {
+        return transactionRunner.runAndRetrieveResult(entityManager ->
+            entityManager
+                .createNamedQuery("listUrls", JPAUrl.class)
+                .getResultList()
+                .stream()
+                .map(JPAUrl::toMailRepositoryUrl)
+                .collect(Guavate.toImmutableSet()));
+    }
+
+    @Override
+    public boolean contains(MailRepositoryUrl url) {
+        return transactionRunner.runAndRetrieveResult(entityManager ->
+            ! entityManager.createNamedQuery("getUrl", JPAUrl.class)
+                .setParameter("value", url.asString())
+                .getResultList()
+                .isEmpty());
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAUrl.java
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAUrl.java b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAUrl.java
new file mode 100644
index 0000000..c775ad7
--- /dev/null
+++ b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAUrl.java
@@ -0,0 +1,65 @@
+/****************************************************************
+ * 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.mailrepository.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
+
+@Entity(name = "JamesMailRepos")
+@Table(name = "JAMES_MAIL_REPOS")
+@NamedQueries({
+    @NamedQuery(name = "listUrls", query = "SELECT url FROM JamesMailRepos url"),
+    @NamedQuery(name = "getUrl", query = "SELECT url FROM JamesMailRepos url WHERE url.value=:value")})
+public class JPAUrl {
+    public static JPAUrl from(MailRepositoryUrl url) {
+        return new JPAUrl(url.asString());
+    }
+
+    @Id
+    @Column(name = "MAIL_REPO_NAME", nullable = false, length = 1024)
+    private String value;
+
+    /**
+     * Default no-args constructor for JPA class enhancement.
+     * The constructor need to be public or protected to be used by JPA.
+     * See:  http://docs.oracle.com/javaee/6/tutorial/doc/bnbqa.html
+     * Do not us this constructor, it is for JPA only.
+     */
+    protected JPAUrl() {
+    }
+
+    public JPAUrl(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public MailRepositoryUrl toMailRepositoryUrl() {
+        return MailRepositoryUrl.from(value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/data/data-jpa/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/main/resources/META-INF/persistence.xml b/server/data/data-jpa/src/main/resources/META-INF/persistence.xml
index 14a6a4f..0e43be9 100644
--- a/server/data/data-jpa/src/main/resources/META-INF/persistence.xml
+++ b/server/data/data-jpa/src/main/resources/META-INF/persistence.xml
@@ -29,6 +29,7 @@
         <class>org.apache.james.domainlist.jpa.model.JPADomain</class>
         <class>org.apache.james.user.jpa.model.JPAUser</class>
         <class>org.apache.james.rrt.jpa.model.JPARecipientRewrite</class>
+        <class>org.apache.james.mailrepository.jpa.JPAUrl</class>
         <exclude-unlisted-classes>true</exclude-unlisted-classes>
         <properties>
             <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/data/data-jpa/src/test/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStoreExtension.java
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/test/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStoreExtension.java b/server/data/data-jpa/src/test/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStoreExtension.java
new file mode 100644
index 0000000..402a5de
--- /dev/null
+++ b/server/data/data-jpa/src/test/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStoreExtension.java
@@ -0,0 +1,47 @@
+/****************************************************************
+ * 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.mailrepository.jpa;
+
+import org.apache.james.backends.jpa.JpaTestCluster;
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+
+public class JPAMailRepositoryUrlStoreExtension implements ParameterResolver, AfterEachCallback{
+    private static final JpaTestCluster JPA_TEST_CLUSTER = JpaTestCluster.create(JPAUrl.class);
+
+    @Override
+    public void afterEach(ExtensionContext context) {
+        JPA_TEST_CLUSTER.clear("JAMES_MAIL_REPOS");
+    }
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return (parameterContext.getParameter().getType() == MailRepositoryUrlStore.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return new JPAMailRepositoryUrlStore(JPA_TEST_CLUSTER.getEntityManagerFactory());
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7ec3c1/server/data/data-jpa/src/test/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStoreTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/test/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStoreTest.java b/server/data/data-jpa/src/test/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStoreTest.java
new file mode 100644
index 0000000..5a58174
--- /dev/null
+++ b/server/data/data-jpa/src/test/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStoreTest.java
@@ -0,0 +1,28 @@
+/****************************************************************
+ * 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.mailrepository.jpa;
+
+import org.apache.james.mailrepository.api.MailRepositoryUrlStoreContract;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(JPAMailRepositoryUrlStoreExtension.class)
+public class JPAMailRepositoryUrlStoreTest implements MailRepositoryUrlStoreContract {
+
+}


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


[11/13] james-project git commit: JAMES-2420 checkstyle fixes

Posted by bt...@apache.org.
JAMES-2420 checkstyle fixes


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

Branch: refs/heads/master
Commit: cf143b6e89a8238224a22fc788d7acd2779d40a8
Parents: ab900b8
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Jun 13 17:45:45 2018 +0200
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:23:13 2018 +0700

----------------------------------------------------------------------
 .../org/apache/james/backends/es/search/ScrollIterableTest.java     | 1 -
 .../main/java/org/apache/james/dlp/api/DLPConfigurationItem.java    | 1 -
 .../org/apache/james/dlp/api/DLPConfigurationStoreContract.java     | 1 +
 .../src/test/java/org/apache/james/webadmin/WebAdminUtils.java      | 1 -
 4 files changed, 1 insertion(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/cf143b6e/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/search/ScrollIterableTest.java
----------------------------------------------------------------------
diff --git a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/search/ScrollIterableTest.java b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/search/ScrollIterableTest.java
index cd99e90..c9bb496 100644
--- a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/search/ScrollIterableTest.java
+++ b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/search/ScrollIterableTest.java
@@ -28,7 +28,6 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import org.apache.james.backends.es.AliasName;
 import org.apache.james.backends.es.ClientProvider;
 import org.apache.james.backends.es.EmbeddedElasticSearch;
 import org.apache.james.backends.es.IndexCreationFactory;

http://git-wip-us.apache.org/repos/asf/james-project/blob/cf143b6e/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
index 04747cb..d0babdb 100644
--- a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
+++ b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
@@ -28,7 +28,6 @@ import org.apache.commons.lang3.StringUtils;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
 
 public class DLPConfigurationItem {
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/cf143b6e/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java
index fa506b7..4a5e417 100644
--- a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java
+++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java
@@ -80,6 +80,7 @@ public interface DLPConfigurationStoreContract {
 
         assertThat(dlpConfigurationStore.list(OTHER_DOMAIN)).containsOnly(RULE_2);
     }
+
     @Test
     default void clearShouldOnlyRemovePreviouslyExistingEntries(DLPConfigurationStore dlpConfigurationStore) {
         dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE, RULE_2));

http://git-wip-us.apache.org/repos/asf/james-project/blob/cf143b6e/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java
index 6e5a717..8d5534a 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java
@@ -22,7 +22,6 @@ package org.apache.james.webadmin;
 import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
 import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
 
-import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 
 import org.apache.james.metrics.api.MetricFactory;


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


[06/13] james-project git commit: JAMES-2418 Provide MailRepositoryUrlStore cassandra implementation

Posted by bt...@apache.org.
JAMES-2418 Provide MailRepositoryUrlStore cassandra implementation


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

Branch: refs/heads/master
Commit: c2dadb276225a1f8d3e5948b48b052a2cad78bcb
Parents: 435a327
Author: benwa <bt...@linagora.com>
Authored: Fri Jun 8 11:54:48 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:16:59 2018 +0700

----------------------------------------------------------------------
 .../backends/cassandra/CassandraCluster.java    |  5 +
 server/data/data-cassandra/pom.xml              | 26 +++++-
 .../CassandraMailRepositoryUrlModule.java       | 61 ++++++++++++
 .../CassandraMailRepositoryUrlStore.java        | 58 ++++++++++++
 .../james/mailrepository/cassandra/UrlsDao.java | 98 ++++++++++++++++++++
 .../mailrepository/cassandra/UrlsTable.java     | 26 ++++++
 ...assandraMailRepositoryUrlStoreExtension.java | 66 +++++++++++++
 .../CassandraMailRepositoryUrlStoreTest.java    | 28 ++++++
 8 files changed, 363 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c2dadb27/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java
----------------------------------------------------------------------
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java
index 19ab763..f03ae27 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java
@@ -33,6 +33,7 @@ import org.apache.james.backends.cassandra.init.ClusterBuilder;
 import org.apache.james.backends.cassandra.init.ClusterWithKeyspaceCreatedFactory;
 import org.apache.james.backends.cassandra.init.SessionWithInitializedTablesFactory;
 import org.apache.james.backends.cassandra.utils.FunctionRunnerWithRetry;
+import org.apache.james.util.Host;
 
 import com.datastax.driver.core.Cluster;
 import com.datastax.driver.core.Session;
@@ -55,6 +56,10 @@ public final class CassandraCluster implements AutoCloseable {
     public static CassandraCluster create(CassandraModule module, String host, int port) {
         return new CassandraCluster(module, host, port);
     }
+
+    public static CassandraCluster create(CassandraModule module, Host host) {
+        return new CassandraCluster(module, host.getHostName(), host.getPort());
+    }
     
     @Inject
     private CassandraCluster(CassandraModule module, @Named("cassandraHost") String host, @Named("cassandraPort") int port) throws RuntimeException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/c2dadb27/server/data/data-cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/pom.xml b/server/data/data-cassandra/pom.xml
index fcf3065..5e86b05 100644
--- a/server/data/data-cassandra/pom.xml
+++ b/server/data/data-cassandra/pom.xml
@@ -47,6 +47,12 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-data-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-data-library</artifactId>
         </dependency>
         <dependency>
@@ -97,11 +103,6 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>nl.jqno.equalsverifier</groupId>
             <artifactId>equalsverifier</artifactId>
             <scope>test</scope>
@@ -112,6 +113,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/c2dadb27/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlModule.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlModule.java b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlModule.java
new file mode 100644
index 0000000..6caf5e1
--- /dev/null
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlModule.java
@@ -0,0 +1,61 @@
+/****************************************************************
+ * 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.mailrepository.cassandra;
+
+import static com.datastax.driver.core.DataType.text;
+
+import java.util.List;
+
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.components.CassandraTable;
+import org.apache.james.backends.cassandra.components.CassandraType;
+import org.apache.james.backends.cassandra.utils.CassandraConstants;
+
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
+import com.google.common.collect.ImmutableList;
+
+public class CassandraMailRepositoryUrlModule implements CassandraModule {
+
+    private final List<CassandraTable> tables;
+    private final List<CassandraType> types;
+
+    public CassandraMailRepositoryUrlModule() {
+        tables = ImmutableList.of(
+            new CassandraTable(UrlsTable.TABLE_NAME,
+                SchemaBuilder.createTable(UrlsTable.TABLE_NAME)
+                    .ifNotExists()
+                    .addPartitionKey(UrlsTable.URL, text())
+                    .withOptions()
+                    .comment("Holds the list of available mail repository")
+                    .caching(SchemaBuilder.KeyCaching.ALL,
+                        SchemaBuilder.rows(CassandraConstants.DEFAULT_CACHED_ROW_PER_PARTITION))));
+        types = ImmutableList.of();
+    }
+
+    @Override
+    public List<CassandraTable> moduleTables() {
+        return tables;
+    }
+
+    @Override
+    public List<CassandraType> moduleTypes() {
+        return types;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c2dadb27/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
new file mode 100644
index 0000000..65296fc
--- /dev/null
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
@@ -0,0 +1,58 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailrepository.cassandra;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
+
+import com.github.steveash.guavate.Guavate;
+
+public class CassandraMailRepositoryUrlStore implements MailRepositoryUrlStore {
+
+    private final UrlsDao urlsDao;
+
+    @Inject
+    public CassandraMailRepositoryUrlStore(UrlsDao urlsDao) {
+        this.urlsDao = urlsDao;
+    }
+
+    @Override
+    public void add(MailRepositoryUrl url) {
+        urlsDao.addUrl(url).join();
+    }
+
+    @Override
+    public Set<MailRepositoryUrl> list() {
+        return urlsDao.retrieveUsedUrls()
+            .join()
+            .collect(Guavate.toImmutableSet());
+    }
+
+    @Override
+    public boolean contains(MailRepositoryUrl url) {
+        return urlsDao.retrieve(url)
+            .join()
+            .isPresent();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c2dadb27/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/UrlsDao.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/UrlsDao.java b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/UrlsDao.java
new file mode 100644
index 0000000..0a05b6e
--- /dev/null
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/UrlsDao.java
@@ -0,0 +1,98 @@
+/****************************************************************
+ * 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.mailrepository.cassandra;
+
+import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static org.apache.james.mailrepository.cassandra.UrlsTable.TABLE_NAME;
+import static org.apache.james.mailrepository.cassandra.UrlsTable.URL;
+
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
+
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+
+public class UrlsDao {
+    private final CassandraAsyncExecutor executor;
+    private final PreparedStatement insert;
+    private final PreparedStatement selectAll;
+    private final PreparedStatement select;
+    private final CassandraUtils cassandraUtils;
+
+    @Inject
+    public UrlsDao(Session session, CassandraUtils cassandraUtils) {
+        this.executor = new CassandraAsyncExecutor(session);
+        this.cassandraUtils = cassandraUtils;
+
+        this.insert = prepareInsert(session);
+        this.selectAll = prepareSelectAll(session);
+        this.select = prepareSelect(session);
+    }
+
+    private PreparedStatement prepareSelect(Session session) {
+        return session.prepare(select(URL)
+            .from(TABLE_NAME)
+            .where(eq(URL, bindMarker(URL))));
+    }
+
+    private PreparedStatement prepareSelectAll(Session session) {
+        return session.prepare(select(URL)
+            .from(TABLE_NAME));
+    }
+
+    private PreparedStatement prepareInsert(Session session) {
+        return session.prepare(insertInto(TABLE_NAME)
+            .value(URL, bindMarker(URL)));
+    }
+
+    public CompletableFuture<Void> addUrl(MailRepositoryUrl url) {
+        return executor.executeVoid(
+            insert.bind()
+                .setString(URL, url.asString()));
+    }
+
+    public CompletableFuture<Optional<MailRepositoryUrl>> retrieve(MailRepositoryUrl url) {
+        return executor.executeSingleRow(
+            select.bind()
+                .setString(URL, url.asString()))
+            .thenApply(optional -> optional.map(this::toUrl));
+    }
+
+    public CompletableFuture<Stream<MailRepositoryUrl>> retrieveUsedUrls() {
+        return executor.execute(selectAll.bind())
+            .thenApply(resultSet -> cassandraUtils.convertToStream(resultSet)
+                .map(this::toUrl));
+    }
+
+    private MailRepositoryUrl toUrl(Row row) {
+        return MailRepositoryUrl.from(row.getString(URL));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c2dadb27/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/UrlsTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/UrlsTable.java b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/UrlsTable.java
new file mode 100644
index 0000000..7a2eaa8
--- /dev/null
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/UrlsTable.java
@@ -0,0 +1,26 @@
+/****************************************************************
+ * 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.mailrepository.cassandra;
+
+public interface UrlsTable {
+    String TABLE_NAME = "mailRepositoryUrls";
+
+    String URL = "url";
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c2dadb27/server/data/data-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStoreExtension.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStoreExtension.java b/server/data/data-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStoreExtension.java
new file mode 100644
index 0000000..2dec108
--- /dev/null
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStoreExtension.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.mailrepository.cassandra;
+
+import org.apache.james.backends.cassandra.CassandraCluster;
+import org.apache.james.backends.cassandra.DockerCassandraRule;
+import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+
+public class CassandraMailRepositoryUrlStoreExtension implements ParameterResolver, BeforeAllCallback, AfterAllCallback {
+    private final DockerCassandraRule cassandra;
+
+    public CassandraMailRepositoryUrlStoreExtension() {
+        this.cassandra = new DockerCassandraRule();
+    }
+
+    @Override
+    public void beforeAll(ExtensionContext context) {
+        cassandra.start();
+    }
+
+    @Override
+    public void afterAll(ExtensionContext context) {
+        cassandra.stop();
+    }
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return (parameterContext.getParameter().getType() == MailRepositoryUrlStore.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        CassandraCluster cassandraCluster = CassandraCluster.create(
+            new CassandraMailRepositoryUrlModule(),
+            cassandra.getHost());
+
+        return new CassandraMailRepositoryUrlStore(
+            new UrlsDao(
+                cassandraCluster.getConf(),
+                CassandraUtils.WITH_DEFAULT_CONFIGURATION));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c2dadb27/server/data/data-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStoreTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStoreTest.java b/server/data/data-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStoreTest.java
new file mode 100644
index 0000000..92a8a37
--- /dev/null
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStoreTest.java
@@ -0,0 +1,28 @@
+/****************************************************************
+ * 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.mailrepository.cassandra;
+
+import org.apache.james.mailrepository.api.MailRepositoryUrlStoreContract;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(CassandraMailRepositoryUrlStoreExtension.class)
+public class CassandraMailRepositoryUrlStoreTest implements MailRepositoryUrlStoreContract {
+
+}


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


[12/13] james-project git commit: JAMES-2420 checks that expression is a valid Pattern

Posted by bt...@apache.org.
JAMES-2420 checks that expression is a valid Pattern


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

Branch: refs/heads/master
Commit: ab900b8f8e30b9980b770b29e959d4d31b7605f5
Parents: 386387e
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Jun 13 17:18:26 2018 +0200
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:23:13 2018 +0700

----------------------------------------------------------------------
 .../org/apache/james/dlp/api/DLPConfigurationItem.java | 13 +++++++++++++
 .../apache/james/dlp/api/DLPConfigurationItemTest.java | 11 +++++++++++
 2 files changed, 24 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ab900b8f/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
index 727322b..04747cb 100644
--- a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
+++ b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
@@ -21,6 +21,8 @@ package org.apache.james.dlp.api;
 
 import java.util.Objects;
 import java.util.Optional;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 
 import org.apache.commons.lang3.StringUtils;
 
@@ -122,6 +124,8 @@ public class DLPConfigurationItem {
         public DLPConfigurationItem build() {
             Preconditions.checkState(id.isPresent(), "`id` is mandatory");
             Preconditions.checkState(expression.isPresent(), "`expression` is mandatory");
+            Preconditions.checkState(isValidPattern(expression.get()), "`expression` must be a valid regex");
+
             return new DLPConfigurationItem(
                 id.get(),
                 explanation,
@@ -131,6 +135,15 @@ public class DLPConfigurationItem {
                     targetsRecipients.orElse(NOT_TARGETED),
                     targetsContent.orElse(NOT_TARGETED)));
         }
+
+        private static boolean isValidPattern(String regex) {
+            try {
+                Pattern.compile(regex);
+                return true;
+            } catch (PatternSyntaxException e) {
+                return false;
+            }
+        }
     }
 
     public static class Targets {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ab900b8f/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
index 2646f74..b0d8f9b 100644
--- a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
+++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
@@ -107,6 +107,17 @@ public class DLPConfigurationItemTest {
     }
 
     @Test
+    void expressionShouldBeValidPattern() {
+        assertThatThrownBy(() ->
+            DLPConfigurationItem.builder()
+                .id(UNIQUE_ID)
+                .expression("*")
+                .build())
+            .isInstanceOf(IllegalStateException.class);
+    }
+
+
+    @Test
     void builderShouldPreserveExpression() {
         DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
             .id(UNIQUE_ID)


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


[04/13] james-project git commit: JAMES-2418 Rely on Stream rather than on collections for getUrls

Posted by bt...@apache.org.
JAMES-2418 Rely on Stream rather than on collections for getUrls


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

Branch: refs/heads/master
Commit: 87b3b1850d5365240289887568505ff266e9aa23
Parents: fb4e7c6
Author: benwa <bt...@linagora.com>
Authored: Tue Jun 12 09:52:58 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:16:59 2018 +0700

----------------------------------------------------------------------
 .../org/apache/james/utils/InMemoryMailRepositoryStore.java | 5 +++--
 .../org/apache/james/utils/MailRepositoryProbeImpl.java     | 4 +++-
 .../mailrepositorystore/MailRepositoryStoreBeanFactory.java | 6 +++---
 .../james/mailrepository/api/MailRepositoryStore.java       | 3 ++-
 .../james/mailrepository/api/MailRepositoryUrlStore.java    | 4 ++--
 .../cassandra/CassandraMailRepositoryUrlStore.java          | 9 +++------
 .../james/mailrepository/jpa/JPAMailRepositoryUrlStore.java | 9 +++------
 .../james/mailrepository/mock/MockMailRepositoryStore.java  | 7 +++----
 .../mailrepository/memory/MemoryMailRepositoryUrlStore.java | 6 +++---
 .../james/webadmin/service/MailRepositoryStoreService.java  | 1 -
 .../james/webadmin/routes/MailRepositoriesRoutesTest.java   | 7 +++++--
 .../webadmin/service/MailRepositoryStoreServiceTest.java    | 9 +++++----
 12 files changed, 35 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
index 6ec37a4..1d809f5 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
@@ -26,6 +26,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Stream;
 
 import org.apache.commons.configuration.CombinedConfiguration;
 import org.apache.commons.configuration.ConfigurationException;
@@ -65,8 +66,8 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
     }
 
     @Override
-    public List<MailRepositoryUrl> getUrls() {
-        return ImmutableList.copyOf(urlStore.list());
+    public Stream<MailRepositoryUrl> getUrls() {
+        return urlStore.list();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
index 71f7dec..b908450 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
@@ -27,6 +27,7 @@ import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 
+import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableList;
 
 public class MailRepositoryProbeImpl implements GuiceProbe {
@@ -56,7 +57,8 @@ public class MailRepositoryProbeImpl implements GuiceProbe {
     }
 
     public List<MailRepositoryUrl> listRepositoryUrls() {
-        return ImmutableList.copyOf(repositoryStore.getUrls());
+        return repositoryStore.getUrls()
+            .collect(Guavate.toImmutableList());
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java
----------------------------------------------------------------------
diff --git a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java b/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java
index b83af66..a05b3ca 100644
--- a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java
+++ b/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java
@@ -18,11 +18,11 @@
  ****************************************************************/
 package org.apache.james.container.spring.bean.factory.mailrepositorystore;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 import javax.annotation.PostConstruct;
 
@@ -201,8 +201,8 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen
     }
 
     @Override
-    public synchronized List<MailRepositoryUrl> getUrls() {
-        return new ArrayList<>(repositories.keySet());
+    public synchronized Stream<MailRepositoryUrl> getUrls() {
+        return repositories.keySet().stream();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java
index e13c31c..1ae2b5d 100644
--- a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java
+++ b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java
@@ -21,6 +21,7 @@ package org.apache.james.mailrepository.api;
 
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 public interface MailRepositoryStore {
 
@@ -53,7 +54,7 @@ public interface MailRepositoryStore {
      * 
      * @return urls
      */
-    List<MailRepositoryUrl> getUrls();
+    Stream<MailRepositoryUrl> getUrls();
 
     class MailRepositoryStoreException extends Exception {
         public MailRepositoryStoreException(String msg, Throwable t) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
index d16232a..f30b332 100644
--- a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
+++ b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
@@ -19,13 +19,13 @@
 
 package org.apache.james.mailrepository.api;
 
-import java.util.Set;
+import java.util.stream.Stream;
 
 public interface MailRepositoryUrlStore {
 
     void add(MailRepositoryUrl url);
 
-    Set<MailRepositoryUrl> list();
+    Stream<MailRepositoryUrl> list();
 
     boolean contains(MailRepositoryUrl url);
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
index 65296fc..9d9fc02 100644
--- a/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
@@ -19,15 +19,13 @@
 
 package org.apache.james.mailrepository.cassandra;
 
-import java.util.Set;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
 
-import com.github.steveash.guavate.Guavate;
-
 public class CassandraMailRepositoryUrlStore implements MailRepositoryUrlStore {
 
     private final UrlsDao urlsDao;
@@ -43,10 +41,9 @@ public class CassandraMailRepositoryUrlStore implements MailRepositoryUrlStore {
     }
 
     @Override
-    public Set<MailRepositoryUrl> list() {
+    public Stream<MailRepositoryUrl> list() {
         return urlsDao.retrieveUsedUrls()
-            .join()
-            .collect(Guavate.toImmutableSet());
+            .join();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
index 576b774..068c4f6 100644
--- a/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
+++ b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
@@ -19,7 +19,7 @@
 
 package org.apache.james.mailrepository.jpa;
 
-import java.util.Set;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.persistence.EntityManagerFactory;
@@ -28,8 +28,6 @@ import org.apache.james.backends.jpa.TransactionRunner;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
 
-import com.github.steveash.guavate.Guavate;
-
 public class JPAMailRepositoryUrlStore implements MailRepositoryUrlStore {
     private final TransactionRunner transactionRunner;
 
@@ -45,14 +43,13 @@ public class JPAMailRepositoryUrlStore implements MailRepositoryUrlStore {
     }
 
     @Override
-    public Set<MailRepositoryUrl> list() {
+    public Stream<MailRepositoryUrl> list() {
         return transactionRunner.runAndRetrieveResult(entityManager ->
             entityManager
                 .createNamedQuery("listUrls", JPAUrl.class)
                 .getResultList()
                 .stream()
-                .map(JPAUrl::toMailRepositoryUrl)
-                .collect(Guavate.toImmutableSet()));
+                .map(JPAUrl::toMailRepositoryUrl));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java b/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java
index f232e43..dc3e1d9 100644
--- a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java
+++ b/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java
@@ -19,11 +19,10 @@
 
 package org.apache.james.mailrepository.mock;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
@@ -48,8 +47,8 @@ public class MockMailRepositoryStore implements MailRepositoryStore {
     }
 
     @Override
-    public List<MailRepositoryUrl> getUrls() {
-        return new ArrayList<>(storedObjectMap.keySet());
+    public Stream<MailRepositoryUrl> getUrls() {
+        return storedObjectMap.keySet().stream();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java b/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
index c6ab960..130bd5d 100644
--- a/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
+++ b/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
@@ -20,11 +20,11 @@
 package org.apache.james.mailrepository.memory;
 
 import java.util.Set;
+import java.util.stream.Stream;
 
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
 
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 
 public class MemoryMailRepositoryUrlStore implements MailRepositoryUrlStore {
@@ -40,8 +40,8 @@ public class MemoryMailRepositoryUrlStore implements MailRepositoryUrlStore {
     }
 
     @Override
-    public Set<MailRepositoryUrl> list() {
-        return ImmutableSet.copyOf(urls);
+    public Stream<MailRepositoryUrl> list() {
+        return urls.stream();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java
index 7a0d691..d8e0e95 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java
@@ -55,7 +55,6 @@ public class MailRepositoryStoreService {
 
     public List<MailRepositoryResponse> listMailRepositories() {
         return mailRepositoryStore.getUrls()
-            .stream()
             .map(MailRepositoryResponse::new)
             .collect(Guavate.toImmutableList());
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
index 73f8539..2fdcea3 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
@@ -42,6 +42,7 @@ import static org.mockito.Mockito.when;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
@@ -170,6 +171,8 @@ public class MailRepositoriesRoutesTest {
 
     @Test
     public void getMailRepositoriesShouldReturnEmptyWhenEmpty() {
+        when(mailRepositoryStore.getUrls()).thenReturn(Stream.empty());
+
         List<Object> mailRepositories =
             when()
                 .get()
@@ -187,7 +190,7 @@ public class MailRepositoriesRoutesTest {
     @Test
     public void getMailRepositoriesShouldReturnRepositoryWhenOne() {
         when(mailRepositoryStore.getUrls())
-            .thenReturn(ImmutableList.of(URL_MY_REPO));
+            .thenReturn(Stream.of(URL_MY_REPO));
 
         when()
             .get()
@@ -202,7 +205,7 @@ public class MailRepositoriesRoutesTest {
     public void getMailRepositoriesShouldReturnTwoRepositoriesWhenTwo() {
         ImmutableList<MailRepositoryUrl> myRepositories = ImmutableList.of(URL_MY_REPO, MailRepositoryUrl.from("url://mySecondRepo"));
         when(mailRepositoryStore.getUrls())
-            .thenReturn(myRepositories);
+            .thenReturn(myRepositories.stream());
 
         List<String> mailRepositories =
             when()

http://git-wip-us.apache.org/repos/asf/james-project/blob/87b3b185/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java
index 927c5136..b505244 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
 
 import java.nio.charset.StandardCharsets;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 import javax.mail.internet.MimeMessage;
 
@@ -43,8 +44,6 @@ import org.apache.mailet.base.test.FakeMail;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.google.common.collect.ImmutableList;
-
 public class MailRepositoryStoreServiceTest {
     private static final MailRepositoryUrl FIRST_REPOSITORY = MailRepositoryUrl.from("url://repository");
     private static final MailRepositoryUrl SECOND_REPOSITORY = MailRepositoryUrl.from("url://repository2");
@@ -64,13 +63,15 @@ public class MailRepositoryStoreServiceTest {
 
     @Test
     public void listMailRepositoriesShouldReturnEmptyWhenEmpty() {
+        when(mailRepositoryStore.getUrls()).thenReturn(Stream.empty());
+
         assertThat(testee.listMailRepositories()).isEmpty();
     }
 
     @Test
     public void listMailRepositoriesShouldReturnOneRepositoryWhenOne() {
         when(mailRepositoryStore.getUrls())
-            .thenReturn(ImmutableList.of(FIRST_REPOSITORY));
+            .thenReturn(Stream.of(FIRST_REPOSITORY));
         assertThat(testee.listMailRepositories())
             .extracting(MailRepositoryResponse::getRepository)
             .containsOnly(FIRST_REPOSITORY.asString());
@@ -79,7 +80,7 @@ public class MailRepositoryStoreServiceTest {
     @Test
     public void listMailRepositoriesShouldReturnTwoRepositoriesWhentwo() {
         when(mailRepositoryStore.getUrls())
-            .thenReturn(ImmutableList.of(FIRST_REPOSITORY, SECOND_REPOSITORY));
+            .thenReturn(Stream.of(FIRST_REPOSITORY, SECOND_REPOSITORY));
         assertThat(testee.listMailRepositories())
             .extracting(MailRepositoryResponse::getRepository)
             .containsOnly(FIRST_REPOSITORY.asString(), SECOND_REPOSITORY.asString());


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


[08/13] james-project git commit: JAMES-2420 MailRepositoryURLStore should not add duplicates in a concurrent environment

Posted by bt...@apache.org.
JAMES-2420 MailRepositoryURLStore should not add duplicates in a concurrent environment


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

Branch: refs/heads/master
Commit: 18ab2d487328fc29da6e5146976001ee5fdb1add
Parents: 87b3b18
Author: benwa <bt...@linagora.com>
Authored: Tue Jun 12 16:01:23 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:17:12 2018 +0700

----------------------------------------------------------------------
 .../utils/InMemoryMailRepositoryStore.java      |  2 +-
 .../api/MailRepositoryUrlStore.java             |  2 +-
 .../api/MailRepositoryUrlStoreContract.java     | 31 ++++++++++++++------
 .../CassandraMailRepositoryUrlStore.java        |  2 +-
 .../jpa/JPAMailRepositoryUrlStore.java          |  2 +-
 .../memory/MemoryMailRepositoryUrlStore.java    |  2 +-
 6 files changed, 27 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/18ab2d48/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
index 1d809f5..06c2cf3 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
@@ -67,7 +67,7 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
 
     @Override
     public Stream<MailRepositoryUrl> getUrls() {
-        return urlStore.list();
+        return urlStore.listDistinct();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/18ab2d48/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
index f30b332..be53c72 100644
--- a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
+++ b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
@@ -25,7 +25,7 @@ public interface MailRepositoryUrlStore {
 
     void add(MailRepositoryUrl url);
 
-    Stream<MailRepositoryUrl> list();
+    Stream<MailRepositoryUrl> listDistinct();
 
     boolean contains(MailRepositoryUrl url);
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/18ab2d48/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java b/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java
index 38b7ee4..8260deb 100644
--- a/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java
+++ b/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java
@@ -31,31 +31,31 @@ public interface MailRepositoryUrlStoreContract {
     MailRepositoryUrl URL_2 = MailRepositoryUrl.from("proto://var/mail/tata");
 
     @Test
-    default void retrieveUsedUrlsShouldBeEmptyByDefault(MailRepositoryUrlStore store) {
-        assertThat(store.list()).isEmpty();
+    default void listDistinctShouldBeEmptyByDefault(MailRepositoryUrlStore store) {
+        assertThat(store.listDistinct()).isEmpty();
     }
 
     @Test
-    default void retrieveUsedUrlsShouldReturnAddedUrl(MailRepositoryUrlStore store) {
+    default void listDistinctShouldReturnAddedUrl(MailRepositoryUrlStore store) {
         store.add(URL_1);
 
-        assertThat(store.list()).containsOnly(URL_1);
+        assertThat(store.listDistinct()).containsOnly(URL_1);
     }
 
     @Test
-    default void retrieveUsedUrlsShouldNotReturnDuplicates(MailRepositoryUrlStore store) {
+    default void listDistinctShouldNotReturnDuplicates(MailRepositoryUrlStore store) {
         store.add(URL_1);
         store.add(URL_1);
 
-        assertThat(store.list()).containsOnly(URL_1);
+        assertThat(store.listDistinct()).containsOnly(URL_1);
     }
 
     @Test
-    default void retrieveUsedUrlsShouldReturnAddedUrls(MailRepositoryUrlStore store) {
+    default void listDistinctShouldReturnAddedUrls(MailRepositoryUrlStore store) {
         store.add(URL_1);
         store.add(URL_2);
 
-        assertThat(store.list()).containsOnly(URL_1, URL_2);
+        assertThat(store.listDistinct()).containsOnly(URL_1, URL_2);
     }
 
     @Test
@@ -80,7 +80,20 @@ public interface MailRepositoryUrlStoreContract {
         testRunner.awaitTermination(1, TimeUnit.MINUTES);
         testRunner.assertNoException();
 
-        assertThat(store.list()).hasSize(threadCount * operationCount);
+        assertThat(store.listDistinct()).hasSize(threadCount * operationCount);
+    }
+
+    @Test
+    default void addShouldNotAddDuplicatesInConcurrentEnvironment(MailRepositoryUrlStore store) throws Exception {
+        int operationCount = 10;
+        int threadCount = 10;
+        ConcurrentTestRunner testRunner = new ConcurrentTestRunner(threadCount, operationCount,
+            (a, b) -> store.add(MailRepositoryUrl.from("proto://" + b)))
+            .run();
+        testRunner.awaitTermination(1, TimeUnit.MINUTES);
+        testRunner.assertNoException();
+
+        assertThat(store.listDistinct()).hasSize(operationCount);
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/18ab2d48/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
index 9d9fc02..b4c482a 100644
--- a/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryUrlStore.java
@@ -41,7 +41,7 @@ public class CassandraMailRepositoryUrlStore implements MailRepositoryUrlStore {
     }
 
     @Override
-    public Stream<MailRepositoryUrl> list() {
+    public Stream<MailRepositoryUrl> listDistinct() {
         return urlsDao.retrieveUsedUrls()
             .join();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/18ab2d48/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
index 068c4f6..ca1b8d2 100644
--- a/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
+++ b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepositoryUrlStore.java
@@ -43,7 +43,7 @@ public class JPAMailRepositoryUrlStore implements MailRepositoryUrlStore {
     }
 
     @Override
-    public Stream<MailRepositoryUrl> list() {
+    public Stream<MailRepositoryUrl> listDistinct() {
         return transactionRunner.runAndRetrieveResult(entityManager ->
             entityManager
                 .createNamedQuery("listUrls", JPAUrl.class)

http://git-wip-us.apache.org/repos/asf/james-project/blob/18ab2d48/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java b/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
index 130bd5d..40bd239 100644
--- a/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
+++ b/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
@@ -40,7 +40,7 @@ public class MemoryMailRepositoryUrlStore implements MailRepositoryUrlStore {
     }
 
     @Override
-    public Stream<MailRepositoryUrl> list() {
+    public Stream<MailRepositoryUrl> listDistinct() {
         return urls.stream();
     }
 


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


[03/13] james-project git commit: JAMES-2418 Provide MailRepositoryUrlStore API, contract and memory implementation

Posted by bt...@apache.org.
JAMES-2418 Provide MailRepositoryUrlStore API, contract and memory implementation


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

Branch: refs/heads/master
Commit: 435a3277012887a0bb9de886acb84497cc22ae1b
Parents: b3d27f8
Author: benwa <bt...@linagora.com>
Authored: Fri Jun 8 11:29:07 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:15:29 2018 +0700

----------------------------------------------------------------------
 server/data/data-api/pom.xml                    |  4 +
 .../api/MailRepositoryUrlStore.java             | 31 +++++++
 .../api/MailRepositoryUrlStoreContract.java     | 86 ++++++++++++++++++++
 server/data/data-memory/pom.xml                 | 24 +++++-
 .../memory/MemoryMailRepositoryUrlStore.java    | 51 ++++++++++++
 .../MemoryMailRepositoryUrlStoreExtension.java  | 38 +++++++++
 .../MemoryMailRepositoryUrlStoreTest.java       | 28 +++++++
 7 files changed, 258 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/435a3277/server/data/data-api/pom.xml
----------------------------------------------------------------------
diff --git a/server/data/data-api/pom.xml b/server/data/data-api/pom.xml
index 35a2572..7a58cfc 100644
--- a/server/data/data-api/pom.xml
+++ b/server/data/data-api/pom.xml
@@ -47,6 +47,10 @@
             <artifactId>james-server-mailrepository-api</artifactId>
         </dependency>
         <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-util</artifactId>
+        </dependency>
+        <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/435a3277/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
new file mode 100644
index 0000000..d16232a
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrlStore.java
@@ -0,0 +1,31 @@
+/****************************************************************
+ * 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.mailrepository.api;
+
+import java.util.Set;
+
+public interface MailRepositoryUrlStore {
+
+    void add(MailRepositoryUrl url);
+
+    Set<MailRepositoryUrl> list();
+
+    boolean contains(MailRepositoryUrl url);
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/435a3277/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java b/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java
new file mode 100644
index 0000000..38b7ee4
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlStoreContract.java
@@ -0,0 +1,86 @@
+/****************************************************************
+ * 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.mailrepository.api;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.james.util.concurrency.ConcurrentTestRunner;
+import org.junit.jupiter.api.Test;
+
+public interface MailRepositoryUrlStoreContract {
+    MailRepositoryUrl URL_1 = MailRepositoryUrl.from("proto://var/mail/toto");
+    MailRepositoryUrl URL_2 = MailRepositoryUrl.from("proto://var/mail/tata");
+
+    @Test
+    default void retrieveUsedUrlsShouldBeEmptyByDefault(MailRepositoryUrlStore store) {
+        assertThat(store.list()).isEmpty();
+    }
+
+    @Test
+    default void retrieveUsedUrlsShouldReturnAddedUrl(MailRepositoryUrlStore store) {
+        store.add(URL_1);
+
+        assertThat(store.list()).containsOnly(URL_1);
+    }
+
+    @Test
+    default void retrieveUsedUrlsShouldNotReturnDuplicates(MailRepositoryUrlStore store) {
+        store.add(URL_1);
+        store.add(URL_1);
+
+        assertThat(store.list()).containsOnly(URL_1);
+    }
+
+    @Test
+    default void retrieveUsedUrlsShouldReturnAddedUrls(MailRepositoryUrlStore store) {
+        store.add(URL_1);
+        store.add(URL_2);
+
+        assertThat(store.list()).containsOnly(URL_1, URL_2);
+    }
+
+    @Test
+    default void containsShouldReturnFalseWhenNotExisting(MailRepositoryUrlStore store) {
+        assertThat(store.contains(URL_1)).isFalse();
+    }
+
+    @Test
+    default void containsShouldReturnTrueWhenExisting(MailRepositoryUrlStore store) {
+        store.add(URL_1);
+
+        assertThat(store.contains(URL_1)).isTrue();
+    }
+
+    @Test
+    default void addShouldWorkInConcurrentEnvironment(MailRepositoryUrlStore store) throws Exception {
+        int operationCount = 10;
+        int threadCount = 10;
+        ConcurrentTestRunner testRunner = new ConcurrentTestRunner(threadCount, operationCount,
+            (a, b) -> store.add(MailRepositoryUrl.from("proto://" + a + "/" + b)))
+            .run();
+        testRunner.awaitTermination(1, TimeUnit.MINUTES);
+        testRunner.assertNoException();
+
+        assertThat(store.list()).hasSize(threadCount * operationCount);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/435a3277/server/data/data-memory/pom.xml
----------------------------------------------------------------------
diff --git a/server/data/data-memory/pom.xml b/server/data/data-memory/pom.xml
index 8e14a9e..6b4661b 100644
--- a/server/data/data-memory/pom.xml
+++ b/server/data/data-memory/pom.xml
@@ -39,6 +39,12 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-data-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-data-library</artifactId>
         </dependency>
         <dependency>
@@ -69,13 +75,23 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.assertj</groupId>
-            <artifactId>assertj-core</artifactId>
+            <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>

http://git-wip-us.apache.org/repos/asf/james-project/blob/435a3277/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java b/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
new file mode 100644
index 0000000..c6ab960
--- /dev/null
+++ b/server/data/data-memory/src/main/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStore.java
@@ -0,0 +1,51 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailrepository.memory;
+
+import java.util.Set;
+
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+public class MemoryMailRepositoryUrlStore implements MailRepositoryUrlStore {
+    private final Set<MailRepositoryUrl> urls;
+
+    public MemoryMailRepositoryUrlStore() {
+        urls = Sets.newConcurrentHashSet();
+    }
+
+    @Override
+    public void add(MailRepositoryUrl url) {
+        urls.add(url);
+    }
+
+    @Override
+    public Set<MailRepositoryUrl> list() {
+        return ImmutableSet.copyOf(urls);
+    }
+
+    @Override
+    public boolean contains(MailRepositoryUrl url) {
+        return urls.contains(url);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/435a3277/server/data/data-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStoreExtension.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStoreExtension.java b/server/data/data-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStoreExtension.java
new file mode 100644
index 0000000..bb4cb10
--- /dev/null
+++ b/server/data/data-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStoreExtension.java
@@ -0,0 +1,38 @@
+/****************************************************************
+ * 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.mailrepository.memory;
+
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+
+public class MemoryMailRepositoryUrlStoreExtension implements ParameterResolver {
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return (parameterContext.getParameter().getType() == MailRepositoryUrlStore.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return new MemoryMailRepositoryUrlStore();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/435a3277/server/data/data-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStoreTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStoreTest.java b/server/data/data-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStoreTest.java
new file mode 100644
index 0000000..047957f
--- /dev/null
+++ b/server/data/data-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryUrlStoreTest.java
@@ -0,0 +1,28 @@
+/****************************************************************
+ * 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.mailrepository.memory;
+
+import org.apache.james.mailrepository.api.MailRepositoryUrlStoreContract;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(MemoryMailRepositoryUrlStoreExtension.class)
+public class MemoryMailRepositoryUrlStoreTest implements MailRepositoryUrlStoreContract {
+
+}


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


[10/13] james-project git commit: JAMES-2420 DLPConfigurationItem should have an Id property

Posted by bt...@apache.org.
JAMES-2420 DLPConfigurationItem should have an Id property


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

Branch: refs/heads/master
Commit: 386387ef6c321d4a45df67ca355e655afc4ad8ef
Parents: e08277e
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Jun 13 17:13:58 2018 +0200
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:23:13 2018 +0700

----------------------------------------------------------------------
 .../james/dlp/api/DLPConfigurationItem.java     | 67 +++++++++++++++++++-
 .../james/dlp/api/DLPConfigurationItemTest.java | 47 +++++++++++++-
 .../org/apache/james/dlp/api/DLPFixture.java    |  2 +
 3 files changed, 112 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/386387ef/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
index bda1c24..727322b 100644
--- a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
+++ b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
@@ -22,11 +22,54 @@ package org.apache.james.dlp.api;
 import java.util.Objects;
 import java.util.Optional;
 
+import org.apache.commons.lang3.StringUtils;
+
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 
 public class DLPConfigurationItem {
 
+    public static class Id {
+
+        public static Id of(String id) {
+            Preconditions.checkNotNull(id, "id should no be null");
+            Preconditions.checkArgument(StringUtils.isNotBlank(id), "id should no be empty");
+            return new Id(id);
+        }
+
+        private final String value;
+
+        private Id(String value) {
+            this.value = value;
+        }
+
+        public String asString() {
+            return value;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof Id) {
+                Id id = (Id) o;
+                return Objects.equals(value, id.value);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(value);
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                .add("value", value)
+                .toString();
+        }
+    }
+
     public static class Builder {
         private static final boolean NOT_TARGETED = false;
 
@@ -35,6 +78,7 @@ public class DLPConfigurationItem {
         private Optional<Boolean> targetsContent;
         private Optional<String> explanation;
         private Optional<String> expression;
+        private Optional<Id> id;
 
         public Builder() {
             targetsSender = Optional.empty();
@@ -42,6 +86,7 @@ public class DLPConfigurationItem {
             targetsContent = Optional.empty();
             explanation = Optional.empty();
             expression = Optional.empty();
+            id = Optional.empty();
         }
 
         public Builder targetsSender() {
@@ -69,9 +114,16 @@ public class DLPConfigurationItem {
             return this;
         }
 
+        public Builder id(Id id) {
+            this.id = Optional.of(id);
+            return this;
+        }
+
         public DLPConfigurationItem build() {
+            Preconditions.checkState(id.isPresent(), "`id` is mandatory");
             Preconditions.checkState(expression.isPresent(), "`expression` is mandatory");
             return new DLPConfigurationItem(
+                id.get(),
                 explanation,
                 expression.get(),
                 new Targets(
@@ -125,6 +177,7 @@ public class DLPConfigurationItem {
         public String toString() {
             return MoreObjects.toStringHelper(this)
                 .add("senderTargeted", senderTargeted)
+                .add("senderTargeted", senderTargeted)
                 .add("recipientTargeted", recipientTargeted)
                 .add("contentTargeted", contentTargeted)
                 .toString();
@@ -135,11 +188,13 @@ public class DLPConfigurationItem {
         return new Builder();
     }
 
+    private final Id id;
     private final Optional<String> explanation;
     private final String regexp;
     private final Targets targets;
 
-    private DLPConfigurationItem(Optional<String> explanation, String regexp, Targets targets) {
+    private DLPConfigurationItem(Id id, Optional<String> explanation, String regexp, Targets targets) {
+        this.id = id;
         this.explanation = explanation;
         this.regexp = regexp;
         this.targets = targets;
@@ -157,12 +212,17 @@ public class DLPConfigurationItem {
         return targets;
     }
 
+    public Id getId() {
+        return id;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof DLPConfigurationItem) {
             DLPConfigurationItem dlpConfigurationItem = (DLPConfigurationItem) o;
 
-            return Objects.equals(this.explanation, dlpConfigurationItem.explanation)
+            return Objects.equals(this.id, dlpConfigurationItem.id)
+                && Objects.equals(this.explanation, dlpConfigurationItem.explanation)
                 && Objects.equals(this.regexp, dlpConfigurationItem.regexp)
                 && Objects.equals(this.targets, dlpConfigurationItem.targets);
         }
@@ -171,12 +231,13 @@ public class DLPConfigurationItem {
 
     @Override
     public final int hashCode() {
-        return Objects.hash(explanation, regexp, targets);
+        return Objects.hash(id, explanation, regexp, targets);
     }
 
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
+            .add("id", id)
             .add("explanation", explanation)
             .add("regexp", regexp)
             .add("targets", targets)

http://git-wip-us.apache.org/repos/asf/james-project/blob/386387ef/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
index 4a38bf1..2646f74 100644
--- a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
+++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
@@ -32,6 +32,7 @@ public class DLPConfigurationItemTest {
 
     private static final String EXPLANATION = "explanation";
     private static final String REGEX = "regex";
+    public static final DLPConfigurationItem.Id UNIQUE_ID = DLPConfigurationItem.Id.of("uniqueId");
 
     @Test
     void shouldMatchBeanContract() {
@@ -48,9 +49,45 @@ public class DLPConfigurationItemTest {
     }
 
     @Test
+    void innerClassIdShouldMatchBeanContract() {
+        EqualsVerifier.forClass(DLPConfigurationItem.Targets.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    void idShouldThrowOnNull() {
+        assertThatThrownBy(() -> DLPConfigurationItem.Id.of(null)).isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    void idShouldThrowOnEmpty() {
+        assertThatThrownBy(() -> DLPConfigurationItem.Id.of("")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void idShouldThrowOnBlank() {
+        assertThatThrownBy(() -> DLPConfigurationItem.Id.of("   ")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void idShouldBeMandatory() {
+        assertThatThrownBy(() ->
+            DLPConfigurationItem.builder()
+                .expression("my expression")
+                .targetsRecipients()
+                .targetsSender()
+                .targetsContent()
+                .explanation(EXPLANATION)
+                .build())
+            .isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
     void expressionShouldBeMandatory() {
         assertThatThrownBy(() ->
             DLPConfigurationItem.builder()
+                .id(UNIQUE_ID)
                 .targetsRecipients()
                 .targetsSender()
                 .targetsContent()
@@ -60,9 +97,10 @@ public class DLPConfigurationItemTest {
     }
 
     @Test
-    void expressionShouldBeTheOnlyMandatoryField() {
+    void expressionAndIdShouldBeTheOnlyMandatoryFields() {
         assertThatCode(() ->
             DLPConfigurationItem.builder()
+                .id(UNIQUE_ID)
                 .expression(REGEX)
                 .build())
             .doesNotThrowAnyException();
@@ -71,6 +109,7 @@ public class DLPConfigurationItemTest {
     @Test
     void builderShouldPreserveExpression() {
         DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .id(UNIQUE_ID)
             .expression(REGEX)
             .build();
 
@@ -80,6 +119,7 @@ public class DLPConfigurationItemTest {
     @Test
     void builderShouldPreserveExplanation() {
         DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .id(UNIQUE_ID)
             .explanation(EXPLANATION)
             .expression(REGEX)
             .build();
@@ -90,6 +130,7 @@ public class DLPConfigurationItemTest {
     @Test
     void dlpRuleShouldHaveNoTargetsWhenNoneSpecified() {
         DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .id(UNIQUE_ID)
             .expression(REGEX)
             .build();
 
@@ -103,6 +144,7 @@ public class DLPConfigurationItemTest {
     @Test
     void targetsRecipientsShouldBeReportedInTargets() {
         DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .id(UNIQUE_ID)
             .targetsRecipients()
             .expression(REGEX)
             .build();
@@ -117,6 +159,7 @@ public class DLPConfigurationItemTest {
     @Test
     void targetsSenderShouldBeReportedInTargets() {
         DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .id(UNIQUE_ID)
             .targetsSender()
             .expression(REGEX)
             .build();
@@ -131,6 +174,7 @@ public class DLPConfigurationItemTest {
     @Test
     void targetsContentShouldBeReportedInTargets() {
         DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .id(UNIQUE_ID)
             .targetsContent()
             .expression(REGEX)
             .build();
@@ -145,6 +189,7 @@ public class DLPConfigurationItemTest {
     @Test
     void allTargetsShouldBeReportedInTargets() {
         DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .id(UNIQUE_ID)
             .targetsContent()
             .targetsSender()
             .targetsRecipients()

http://git-wip-us.apache.org/repos/asf/james-project/blob/386387ef/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java
index 9eea6fc..4b7e86c 100644
--- a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java
+++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java
@@ -21,11 +21,13 @@ package org.apache.james.dlp.api;
 
 public interface DLPFixture {
     DLPConfigurationItem RULE = DLPConfigurationItem.builder()
+        .id(DLPConfigurationItem.Id.of("id1"))
         .explanation("explanation")
         .expression("regex")
         .targetsSender()
         .build();
     DLPConfigurationItem RULE_2 = DLPConfigurationItem.builder()
+        .id(DLPConfigurationItem.Id.of("id2"))
         .explanation("explanation2")
         .expression("regex2")
         .targetsSender()


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


[05/13] james-project git commit: JAMES-2418 Mail repository store should rely on persistent storage

Posted by bt...@apache.org.
JAMES-2418 Mail repository store should rely on persistent storage


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

Branch: refs/heads/master
Commit: fb4e7c668adda2816665dd346ba463e4eab164ea
Parents: 0f7ec3c
Author: benwa <bt...@linagora.com>
Authored: Fri Jun 8 13:51:57 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:16:59 2018 +0700

----------------------------------------------------------------------
 .../data/CassandraMailRepositoryModule.java     | 11 ++++--
 server/container/guice/guice-common/pom.xml     |  5 +++
 .../utils/InMemoryMailRepositoryStore.java      | 13 ++++++--
 .../utils/InMemoryMailRepositoryStoreTest.java  | 22 +++++++++---
 .../james/modules/data/JPADataModule.java       |  1 +
 .../modules/data/JPAMailRepositoryModule.java   | 35 ++++++++++++++++++++
 .../james/modules/data/MemoryDataModule.java    |  5 +++
 7 files changed, 82 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/fb4e7c66/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java
index dc4a7c5..7f2cf90 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java
@@ -23,10 +23,13 @@ import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.blob.api.ObjectStore;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
 import org.apache.james.mailrepository.cassandra.CassandraMailRepository;
 import org.apache.james.mailrepository.cassandra.CassandraMailRepositoryCountDAO;
 import org.apache.james.mailrepository.cassandra.CassandraMailRepositoryKeysDAO;
 import org.apache.james.mailrepository.cassandra.CassandraMailRepositoryMailDAO;
+import org.apache.james.mailrepository.cassandra.CassandraMailRepositoryUrlModule;
+import org.apache.james.mailrepository.cassandra.CassandraMailRepositoryUrlStore;
 import org.apache.james.utils.MailRepositoryProvider;
 
 import com.google.inject.AbstractModule;
@@ -37,15 +40,19 @@ import com.google.inject.multibindings.Multibinder;
 public class CassandraMailRepositoryModule extends AbstractModule {
     @Override
     protected void configure() {
+        bind(CassandraMailRepositoryUrlStore.class).in(Scopes.SINGLETON);
         bind(CassandraMailRepositoryKeysDAO.class).in(Scopes.SINGLETON);
         bind(CassandraMailRepositoryCountDAO.class).in(Scopes.SINGLETON);
         bind(CassandraMailRepositoryMailDAO.class).in(Scopes.SINGLETON);
 
+        bind(MailRepositoryUrlStore.class).to(CassandraMailRepositoryUrlStore.class);
+
         Multibinder<MailRepositoryProvider> multibinder = Multibinder.newSetBinder(binder(), MailRepositoryProvider.class);
         multibinder.addBinding().to(CassandraMailRepositoryProvider.class);
 
-        Multibinder.newSetBinder(binder(), CassandraModule.class).addBinding()
-            .to(org.apache.james.mailrepository.cassandra.CassandraMailRepositoryModule.class);
+        Multibinder<CassandraModule> cassandraModuleBinder = Multibinder.newSetBinder(binder(), CassandraModule.class);
+        cassandraModuleBinder.addBinding().to(org.apache.james.mailrepository.cassandra.CassandraMailRepositoryModule.class);
+        cassandraModuleBinder.addBinding().to(CassandraMailRepositoryUrlModule.class);
     }
 
     public static class CassandraMailRepositoryProvider implements MailRepositoryProvider {

http://git-wip-us.apache.org/repos/asf/james-project/blob/fb4e7c66/server/container/guice/guice-common/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/pom.xml b/server/container/guice/guice-common/pom.xml
index 9f03660..caec572 100644
--- a/server/container/guice/guice-common/pom.xml
+++ b/server/container/guice/guice-common/pom.xml
@@ -56,6 +56,11 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-data-memory</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-dnsservice-api</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/fb4e7c66/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
index 0d87a8d..6ec37a4 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
@@ -35,6 +35,7 @@ import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
 import org.apache.james.mailrepository.api.Protocol;
 import org.apache.james.repository.api.Initializable;
 import org.slf4j.Logger;
@@ -47,6 +48,7 @@ import com.google.inject.Inject;
 public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configurable {
     private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryMailRepositoryStore.class);
 
+    private final MailRepositoryUrlStore urlStore;
     private final Set<MailRepositoryProvider> mailRepositories;
     private final ConcurrentMap<MailRepositoryUrl, MailRepository> destinationToRepositoryAssociations;
     private final Map<Protocol, MailRepositoryProvider> protocolToRepositoryProvider;
@@ -54,7 +56,8 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
     private HierarchicalConfiguration configuration;
 
     @Inject
-    public InMemoryMailRepositoryStore(Set<MailRepositoryProvider> mailRepositories) {
+    public InMemoryMailRepositoryStore(MailRepositoryUrlStore urlStore, Set<MailRepositoryProvider> mailRepositories) {
+        this.urlStore = urlStore;
         this.mailRepositories = mailRepositories;
         this.destinationToRepositoryAssociations = new ConcurrentHashMap<>();
         this.protocolToRepositoryProvider = new HashMap<>();
@@ -63,7 +66,7 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
 
     @Override
     public List<MailRepositoryUrl> getUrls() {
-        return ImmutableList.copyOf(destinationToRepositoryAssociations.keySet());
+        return ImmutableList.copyOf(urlStore.list());
     }
 
     @Override
@@ -90,7 +93,10 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
 
     @Override
     public Optional<MailRepository> get(MailRepositoryUrl url) {
-        return Optional.ofNullable(destinationToRepositoryAssociations.get(url));
+        if (urlStore.contains(url)) {
+            return Optional.of(select(url));
+        }
+        return Optional.empty();
     }
 
     @Override
@@ -102,6 +108,7 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
     }
 
     private MailRepository createNewMailRepository(MailRepositoryUrl mailRepositoryUrl) throws MailRepositoryStoreException {
+        urlStore.add(mailRepositoryUrl);
         MailRepository newMailRepository = retrieveMailRepository(mailRepositoryUrl);
         newMailRepository = initializeNewRepository(newMailRepository, createRepositoryCombinedConfig(mailRepositoryUrl));
         MailRepository previousRepository = destinationToRepositoryAssociations.putIfAbsent(mailRepositoryUrl, newMailRepository);

http://git-wip-us.apache.org/repos/asf/james-project/blob/fb4e7c66/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
index cb1e18a..f373bbe 100644
--- a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
+++ b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
@@ -32,6 +32,7 @@ import org.apache.james.mailrepository.api.MailRepositoryStore;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.mailrepository.file.FileMailRepository;
 import org.apache.james.mailrepository.memory.MemoryMailRepository;
+import org.apache.james.mailrepository.memory.MemoryMailRepositoryUrlStore;
 import org.apache.james.modules.server.MailStoreRepositoryModule;
 import org.apache.james.server.core.configuration.Configuration;
 import org.apache.james.server.core.configuration.FileConfigurationProvider;
@@ -46,6 +47,8 @@ import com.google.common.collect.Sets;
 public class InMemoryMailRepositoryStoreTest {
     private static final MailRepositoryUrl FILE_REPO = MailRepositoryUrl.from("file://repo");
 
+    private MemoryMailRepositoryUrlStore urlStore;
+
     private static class MemoryMailRepositoryProvider implements MailRepositoryProvider {
         @Override
         public String canonicalName() {
@@ -69,9 +72,10 @@ public class InMemoryMailRepositoryStoreTest {
             .configurationFromClasspath()
             .build();
         fileSystem = new FileSystemImpl(configuration.directories());
-        repositoryStore = new InMemoryMailRepositoryStore(Sets.newHashSet(
-                new MailStoreRepositoryModule.FileMailRepositoryProvider(
-                        fileSystem),
+        urlStore = new MemoryMailRepositoryUrlStore();
+        MailStoreRepositoryModule.FileMailRepositoryProvider fileProvider = new MailStoreRepositoryModule.FileMailRepositoryProvider(fileSystem);
+        repositoryStore = new InMemoryMailRepositoryStore(urlStore, Sets.newHashSet(
+            fileProvider,
                 new MemoryMailRepositoryProvider()));
         repositoryStore.configure(new FileConfigurationProvider(fileSystem, configuration)
             .getConfiguration("mailrepositorystore"));
@@ -103,7 +107,7 @@ public class InMemoryMailRepositoryStoreTest {
 
     @Test
     public void configureShouldThrowWhenNonValidClassesAreProvided() throws Exception {
-        repositoryStore = new InMemoryMailRepositoryStore(Sets.newHashSet(
+        repositoryStore = new InMemoryMailRepositoryStore(urlStore, Sets.newHashSet(
             new MailStoreRepositoryModule.FileMailRepositoryProvider(
                 fileSystem)));
         repositoryStore.configure(new FileConfigurationProvider(fileSystem, configuration).getConfiguration("fakemailrepositorystore"));
@@ -114,7 +118,7 @@ public class InMemoryMailRepositoryStoreTest {
 
     @Test
     public void configureShouldNotThrowOnEmptyConfiguration() throws Exception {
-        repositoryStore = new InMemoryMailRepositoryStore(Sets.newHashSet(
+        repositoryStore = new InMemoryMailRepositoryStore(urlStore, Sets.newHashSet(
             new MailStoreRepositoryModule.FileMailRepositoryProvider(
                 fileSystem)));
         repositoryStore.configure(new HierarchicalConfiguration());
@@ -152,6 +156,14 @@ public class InMemoryMailRepositoryStoreTest {
     }
 
     @Test
+    public void getShouldReturnRepositoryWhenUrlExists() {
+        urlStore.add(FILE_REPO);
+
+        assertThat(repositoryStore.get(FILE_REPO))
+            .isNotEmpty();
+    }
+
+    @Test
     public void getShouldReturnPreviouslyCreatedMailRepository() {
         MailRepository mailRepository = repositoryStore.select(FILE_REPO);
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/fb4e7c66/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPADataModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPADataModule.java b/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPADataModule.java
index ec8023e..ee79def 100644
--- a/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPADataModule.java
+++ b/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPADataModule.java
@@ -27,6 +27,7 @@ public class JPADataModule extends AbstractModule {
         install(new JPAUsersRepositoryModule());
         install(new JPADomainListModule());
         install(new JPARecipientRewriteTableModule());
+        install(new JPAMailRepositoryModule());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/fb4e7c66/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPAMailRepositoryModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPAMailRepositoryModule.java b/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPAMailRepositoryModule.java
new file mode 100644
index 0000000..5e9f398
--- /dev/null
+++ b/server/container/guice/jpa-common-guice/src/main/java/org/apache/james/modules/data/JPAMailRepositoryModule.java
@@ -0,0 +1,35 @@
+/****************************************************************
+ * 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.modules.data;
+
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
+import org.apache.james.mailrepository.jpa.JPAMailRepositoryUrlStore;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
+
+public class JPAMailRepositoryModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        bind(JPAMailRepositoryUrlStore.class).in(Scopes.SINGLETON);
+
+        bind(MailRepositoryUrlStore.class).to(JPAMailRepositoryUrlStore.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/fb4e7c66/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/data/MemoryDataModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/data/MemoryDataModule.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/data/MemoryDataModule.java
index f5c4c80..6fd5de2 100644
--- a/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/data/MemoryDataModule.java
+++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/data/MemoryDataModule.java
@@ -25,6 +25,8 @@ import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.memory.MemoryDomainList;
 import org.apache.james.lifecycle.api.Configurable;
+import org.apache.james.mailrepository.api.MailRepositoryUrlStore;
+import org.apache.james.mailrepository.memory.MemoryMailRepositoryUrlStore;
 import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.memory.MemoryRecipientRewriteTable;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
@@ -51,6 +53,9 @@ public class MemoryDataModule extends AbstractModule {
         bind(MemoryRecipientRewriteTable.class).in(Scopes.SINGLETON);
         bind(RecipientRewriteTable.class).to(MemoryRecipientRewriteTable.class);
 
+        bind(MemoryMailRepositoryUrlStore.class).in(Scopes.SINGLETON);
+        bind(MailRepositoryUrlStore.class).to(MemoryMailRepositoryUrlStore.class);
+
         bind(MemoryUsersRepository.class).toInstance(MemoryUsersRepository.withVirtualHosting());
         bind(UsersRepository.class).to(MemoryUsersRepository.class);
 


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


[02/13] james-project git commit: JAMES-2423 Webadmin should list the mails in a mail repository in the correct format

Posted by bt...@apache.org.
JAMES-2423 Webadmin should list the mails in a mail repository in the correct format


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

Branch: refs/heads/master
Commit: b3d27f878167d9218d35d0b60026ea6ccb60dfe1
Parents: 7b6bfb8
Author: Gautier DI FOLCO <gd...@linagora.com>
Authored: Tue Jun 12 16:19:40 2018 +0200
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:14:24 2018 +0700

----------------------------------------------------------------------
 .../main/java/org/apache/james/webadmin/dto/MailKeyDTO.java  | 3 +++
 .../james/webadmin/routes/MailRepositoriesRoutesTest.java    | 8 ++++----
 2 files changed, 7 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/b3d27f87/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailKeyDTO.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailKeyDTO.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailKeyDTO.java
index 64d4504..fa75fc4 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailKeyDTO.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailKeyDTO.java
@@ -23,6 +23,8 @@ import java.util.Objects;
 
 import org.apache.james.mailrepository.api.MailKey;
 
+import com.fasterxml.jackson.annotation.JsonValue;
+
 public class MailKeyDTO {
 
     private final MailKey mailKey;
@@ -31,6 +33,7 @@ public class MailKeyDTO {
         this.mailKey = mailKey;
     }
 
+    @JsonValue
     public String getMailKey() {
         return mailKey.asString();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/b3d27f87/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
index ae90244..73f8539 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
@@ -258,7 +258,7 @@ public class MailRepositoriesRoutesTest {
         .then()
             .statusCode(HttpStatus.OK_200)
             .body("", hasSize(2))
-            .body("mailKey", containsInAnyOrder("name1", "name2"));
+            .body("", containsInAnyOrder("name1", "name2"));
     }
 
     @Test
@@ -283,7 +283,7 @@ public class MailRepositoriesRoutesTest {
         .then()
             .statusCode(HttpStatus.OK_200)
             .body("", hasSize(1))
-            .body("mailKey", contains("name2"));
+            .body("", contains("name2"));
     }
 
     @Test
@@ -394,7 +394,7 @@ public class MailRepositoriesRoutesTest {
         .then()
             .statusCode(HttpStatus.OK_200)
             .body("", hasSize(2))
-            .body("mailKey", containsInAnyOrder(NAME_1, NAME_2));
+            .body("", containsInAnyOrder(NAME_1, NAME_2));
     }
 
     @Test
@@ -596,7 +596,7 @@ public class MailRepositoriesRoutesTest {
             .then()
             .statusCode(HttpStatus.OK_200)
             .body("", hasSize(1))
-            .body("mailKey", contains(NAME_2));
+            .body("", contains(NAME_2));
     }
 
     @Test


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


[13/13] james-project git commit: JAMES-2420 add a message to EventStoreFailedException to ease debugging

Posted by bt...@apache.org.
JAMES-2420 add a message to EventStoreFailedException to ease debugging


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

Branch: refs/heads/master
Commit: e08277ecdc16fa30c19e61fa470903f10f75ca6d
Parents: 3f368fc
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Jun 13 11:51:07 2018 +0200
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:23:13 2018 +0700

----------------------------------------------------------------------
 .../eventsourcing/eventstore/EventStoreFailedException.java      | 3 +++
 .../java/org/apache/james/eventsourcing/eventstore/History.java  | 2 +-
 .../eventsourcing/eventstore/cassandra/CassandraEventStore.java  | 2 +-
 .../eventsourcing/eventstore/memory/InMemoryEventStore.java      | 4 ++--
 4 files changed, 7 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/e08277ec/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/EventStoreFailedException.java
----------------------------------------------------------------------
diff --git a/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/EventStoreFailedException.java b/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/EventStoreFailedException.java
index 93bcb2f..fb94373 100644
--- a/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/EventStoreFailedException.java
+++ b/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/EventStoreFailedException.java
@@ -20,4 +20,7 @@
 package org.apache.james.eventsourcing.eventstore;
 
 public class EventStoreFailedException extends RuntimeException {
+    public EventStoreFailedException(String message) {
+        super(message);
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/e08277ec/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/History.java
----------------------------------------------------------------------
diff --git a/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/History.java b/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/History.java
index 5a91306..62cc119 100644
--- a/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/History.java
+++ b/event-sourcing/event-store-api/src/main/java/org/apache/james/eventsourcing/eventstore/History.java
@@ -48,7 +48,7 @@ public class History {
 
     private History(List<Event> events) {
         if (hasEventIdDuplicates(events)) {
-            throw new EventStoreFailedException();
+            throw new EventStoreFailedException("Event History contains duplicated EventId");
         }
         this.events = events;
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/e08277ec/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/CassandraEventStore.java
----------------------------------------------------------------------
diff --git a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/CassandraEventStore.java b/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/CassandraEventStore.java
index 0e8fd5f..7804de1 100644
--- a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/CassandraEventStore.java
+++ b/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/CassandraEventStore.java
@@ -53,7 +53,7 @@ public class CassandraEventStore implements EventStore {
 
         boolean success = eventStoreDao.appendAll(events).join();
         if (!success) {
-            throw new EventStoreFailedException();
+            throw new EventStoreFailedException("Concurrent update to the EventStore detected");
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/e08277ec/event-sourcing/event-store-memory/src/main/java/org/apache/james/eventsourcing/eventstore/memory/InMemoryEventStore.java
----------------------------------------------------------------------
diff --git a/event-sourcing/event-store-memory/src/main/java/org/apache/james/eventsourcing/eventstore/memory/InMemoryEventStore.java b/event-sourcing/event-store-memory/src/main/java/org/apache/james/eventsourcing/eventstore/memory/InMemoryEventStore.java
index 69ccf5f..de65ca6 100644
--- a/event-sourcing/event-store-memory/src/main/java/org/apache/james/eventsourcing/eventstore/memory/InMemoryEventStore.java
+++ b/event-sourcing/event-store-memory/src/main/java/org/apache/james/eventsourcing/eventstore/memory/InMemoryEventStore.java
@@ -69,7 +69,7 @@ public class InMemoryEventStore implements EventStore {
 
         History previousHistory = store.putIfAbsent(aggregateId, newHistory);
         if (previousHistory != null) {
-            throw new EventStoreFailedException();
+            throw new EventStoreFailedException("Concurrent update to the EventStore detected");
         }
     }
 
@@ -80,7 +80,7 @@ public class InMemoryEventStore implements EventStore {
 
         boolean isReplaced = store.replace(aggregateId, currentHistory, updatedHistory);
         if (!isReplaced) {
-            throw new EventStoreFailedException();
+            throw new EventStoreFailedException("Concurrent update to the EventStore detected");
         }
     }
 


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


[09/13] james-project git commit: JAMES-2420 DLP rule store API, contract & event sourcing implementation

Posted by bt...@apache.org.
JAMES-2420 DLP rule store API, contract & event sourcing implementation


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

Branch: refs/heads/master
Commit: 3f368fc7c870e15f254f2fc97359e1d9c678d775
Parents: 18ab2d4
Author: benwa <bt...@linagora.com>
Authored: Fri Jun 8 17:15:48 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jun 14 15:22:58 2018 +0700

----------------------------------------------------------------------
 .../james/eventsourcing/CommandDispatcher.java  |   2 +-
 .../apache/james/eventsourcing/EventBus.java    |   5 +-
 server/data/data-api/pom.xml                    |   6 +-
 .../james/dlp/api/DLPConfigurationItem.java     | 185 +++++++++++++++++++
 .../james/dlp/api/DLPConfigurationStore.java    |  41 ++++
 .../james/dlp/api/DLPConfigurationItemTest.java | 162 ++++++++++++++++
 .../dlp/api/DLPConfigurationStoreContract.java  | 101 ++++++++++
 .../org/apache/james/dlp/api/DLPFixture.java    |  34 ++++
 server/data/data-library/pom.xml                |  10 +
 .../EventSourcingDLPConfigurationStore.java     |  81 ++++++++
 .../aggregates/DLPAggregateId.java              |  60 ++++++
 .../aggregates/DLPDomainConfiguration.java      | 151 +++++++++++++++
 .../eventsourcing/commands/ClearCommand.java    |  64 +++++++
 .../commands/ClearCommandHandler.java           |  52 ++++++
 .../eventsourcing/commands/StoreCommand.java    |  75 ++++++++
 .../commands/StoreCommandHandler.java           |  52 ++++++
 .../events/ConfigurationItemsAdded.java         |  89 +++++++++
 .../events/ConfigurationItemsRemoved.java       |  91 +++++++++
 .../aggregates/DLPAggregateIdTest.java          |  51 +++++
 .../commands/ClearCommandTest.java              |  43 +++++
 .../commands/StoreCommandTest.java              |  53 ++++++
 .../events/ConfigurationItemsAddedTest.java     |  67 +++++++
 .../events/ConfigurationItemsRemovedTest.java   |  67 +++++++
 server/data/data-memory/pom.xml                 |  11 ++
 .../EventSourcingDLPConfigurationStoreTest.java |  28 +++
 ...tSourcingDLPConfigurationStoreExtension.java |  40 ++++
 26 files changed, 1615 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java
----------------------------------------------------------------------
diff --git a/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java b/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java
index 15d128c..14498ae 100644
--- a/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java
+++ b/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java
@@ -86,7 +86,7 @@ public class CommandDispatcher {
             .orElseThrow(() -> new TooManyRetries(c, MAX_RETRY));
     }
 
-    public Optional<Integer> trySeveralTimes(Supplier<Boolean> singleTry) {
+    private Optional<Integer> trySeveralTimes(Supplier<Boolean> singleTry) {
         return IntStream.range(0, MAX_RETRY)
             .boxed()
             .filter(any -> singleTry.get())

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java
----------------------------------------------------------------------
diff --git a/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java b/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java
index 289433e..22b817f 100644
--- a/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java
+++ b/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java
@@ -34,7 +34,8 @@ import com.google.common.collect.ImmutableSet;
 
 public class EventBus {
 
-    public static final Logger LOGGER = LoggerFactory.getLogger(EventBus.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(EventBus.class);
+
     private final EventStore eventStore;
     private final Set<Subscriber> subscribers;
 
@@ -51,7 +52,7 @@ public class EventBus {
             .forEach(this::handle);
     }
 
-    public void handle(Pair<Event, Subscriber> pair) {
+    private void handle(Pair<Event, Subscriber> pair) {
         Subscriber subscriber = pair.getRight();
         Event event = pair.getLeft();
         try {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/pom.xml
----------------------------------------------------------------------
diff --git a/server/data/data-api/pom.xml b/server/data/data-api/pom.xml
index 7a58cfc..26de148 100644
--- a/server/data/data-api/pom.xml
+++ b/server/data/data-api/pom.xml
@@ -34,13 +34,13 @@
 
     <dependencies>
         <dependency>
+            <!-- only used by JamesUser (for MailAddress) -->
             <groupId>${project.groupId}</groupId>
-            <artifactId>james-core</artifactId>
+            <artifactId>apache-mailet-api</artifactId>
         </dependency>
         <dependency>
-            <!-- only used by JamesUser (for MailAddress) -->
             <groupId>${project.groupId}</groupId>
-            <artifactId>apache-mailet-api</artifactId>
+            <artifactId>james-core</artifactId>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
new file mode 100644
index 0000000..bda1c24
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java
@@ -0,0 +1,185 @@
+/****************************************************************
+ * 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.dlp.api;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+
+public class DLPConfigurationItem {
+
+    public static class Builder {
+        private static final boolean NOT_TARGETED = false;
+
+        private Optional<Boolean> targetsSender;
+        private Optional<Boolean> targetsRecipients;
+        private Optional<Boolean> targetsContent;
+        private Optional<String> explanation;
+        private Optional<String> expression;
+
+        public Builder() {
+            targetsSender = Optional.empty();
+            targetsRecipients = Optional.empty();
+            targetsContent = Optional.empty();
+            explanation = Optional.empty();
+            expression = Optional.empty();
+        }
+
+        public Builder targetsSender() {
+            this.targetsSender = Optional.of(true);
+            return this;
+        }
+
+        public Builder targetsRecipients() {
+            this.targetsRecipients = Optional.of(true);
+            return this;
+        }
+
+        public Builder targetsContent() {
+            this.targetsContent = Optional.of(true);
+            return this;
+        }
+
+        public Builder expression(String expression) {
+            this.expression = Optional.of(expression);
+            return this;
+        }
+
+        public Builder explanation(String explanation) {
+            this.explanation = Optional.of(explanation);
+            return this;
+        }
+
+        public DLPConfigurationItem build() {
+            Preconditions.checkState(expression.isPresent(), "`expression` is mandatory");
+            return new DLPConfigurationItem(
+                explanation,
+                expression.get(),
+                new Targets(
+                    targetsSender.orElse(NOT_TARGETED),
+                    targetsRecipients.orElse(NOT_TARGETED),
+                    targetsContent.orElse(NOT_TARGETED)));
+        }
+    }
+
+    public static class Targets {
+        private final boolean senderTargeted;
+        private final boolean recipientTargeted;
+        private final boolean contentTargeted;
+
+        public Targets(boolean senderTargeted, boolean recipientTargeted, boolean contentTargeted) {
+            this.senderTargeted = senderTargeted;
+            this.recipientTargeted = recipientTargeted;
+            this.contentTargeted = contentTargeted;
+        }
+
+        public boolean isSenderTargeted() {
+            return senderTargeted;
+        }
+
+        public boolean isRecipientTargeted() {
+            return recipientTargeted;
+        }
+
+        public boolean isContentTargeted() {
+            return contentTargeted;
+        }
+
+        @Override
+        public final boolean equals(Object o) {
+            if (o instanceof Targets) {
+                Targets targets = (Targets) o;
+
+                return Objects.equals(this.senderTargeted, targets.senderTargeted)
+                    && Objects.equals(this.recipientTargeted, targets.recipientTargeted)
+                    && Objects.equals(this.contentTargeted, targets.contentTargeted);
+            }
+            return false;
+        }
+
+        @Override
+        public final int hashCode() {
+            return Objects.hash(senderTargeted, recipientTargeted, contentTargeted);
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                .add("senderTargeted", senderTargeted)
+                .add("recipientTargeted", recipientTargeted)
+                .add("contentTargeted", contentTargeted)
+                .toString();
+        }
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    private final Optional<String> explanation;
+    private final String regexp;
+    private final Targets targets;
+
+    private DLPConfigurationItem(Optional<String> explanation, String regexp, Targets targets) {
+        this.explanation = explanation;
+        this.regexp = regexp;
+        this.targets = targets;
+    }
+
+    public Optional<String> getExplanation() {
+        return explanation;
+    }
+
+    public String getRegexp() {
+        return regexp;
+    }
+
+    public Targets getTargets() {
+        return targets;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof DLPConfigurationItem) {
+            DLPConfigurationItem dlpConfigurationItem = (DLPConfigurationItem) o;
+
+            return Objects.equals(this.explanation, dlpConfigurationItem.explanation)
+                && Objects.equals(this.regexp, dlpConfigurationItem.regexp)
+                && Objects.equals(this.targets, dlpConfigurationItem.targets);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(explanation, regexp, targets);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("explanation", explanation)
+            .add("regexp", regexp)
+            .add("targets", targets)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationStore.java b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationStore.java
new file mode 100644
index 0000000..457341e
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationStore.java
@@ -0,0 +1,41 @@
+/****************************************************************
+ * 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.dlp.api;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.apache.james.core.Domain;
+
+import com.google.common.collect.ImmutableList;
+
+public interface DLPConfigurationStore {
+
+    Stream<DLPConfigurationItem> list(Domain domain);
+
+    void store(Domain domain, List<DLPConfigurationItem> rule);
+
+    default void store(Domain domain, DLPConfigurationItem rule) {
+        store(domain, ImmutableList.of(rule));
+    }
+
+    void clear(Domain domain);
+    
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
new file mode 100644
index 0000000..4a38bf1
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java
@@ -0,0 +1,162 @@
+/****************************************************************
+ * 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.dlp.api;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class DLPConfigurationItemTest {
+
+    private static final String EXPLANATION = "explanation";
+    private static final String REGEX = "regex";
+
+    @Test
+    void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(DLPConfigurationItem.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    void innerClassTargetsShouldMatchBeanContract() {
+        EqualsVerifier.forClass(DLPConfigurationItem.Targets.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    void expressionShouldBeMandatory() {
+        assertThatThrownBy(() ->
+            DLPConfigurationItem.builder()
+                .targetsRecipients()
+                .targetsSender()
+                .targetsContent()
+                .explanation(EXPLANATION)
+                .build())
+            .isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void expressionShouldBeTheOnlyMandatoryField() {
+        assertThatCode(() ->
+            DLPConfigurationItem.builder()
+                .expression(REGEX)
+                .build())
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void builderShouldPreserveExpression() {
+        DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .expression(REGEX)
+            .build();
+
+        assertThat(dlpConfigurationItem.getRegexp()).isEqualTo(REGEX);
+    }
+
+    @Test
+    void builderShouldPreserveExplanation() {
+        DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .explanation(EXPLANATION)
+            .expression(REGEX)
+            .build();
+
+        assertThat(dlpConfigurationItem.getExplanation()).contains(EXPLANATION);
+    }
+
+    @Test
+    void dlpRuleShouldHaveNoTargetsWhenNoneSpecified() {
+        DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .expression(REGEX)
+            .build();
+
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isFalse();
+            softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isFalse();
+            softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isFalse();
+        });
+    }
+
+    @Test
+    void targetsRecipientsShouldBeReportedInTargets() {
+        DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .targetsRecipients()
+            .expression(REGEX)
+            .build();
+
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isFalse();
+            softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isTrue();
+            softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isFalse();
+        });
+    }
+
+    @Test
+    void targetsSenderShouldBeReportedInTargets() {
+        DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .targetsSender()
+            .expression(REGEX)
+            .build();
+
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isFalse();
+            softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isFalse();
+            softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isTrue();
+        });
+    }
+
+    @Test
+    void targetsContentShouldBeReportedInTargets() {
+        DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .targetsContent()
+            .expression(REGEX)
+            .build();
+
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isTrue();
+            softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isFalse();
+            softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isFalse();
+        });
+    }
+
+    @Test
+    void allTargetsShouldBeReportedInTargets() {
+        DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder()
+            .targetsContent()
+            .targetsSender()
+            .targetsRecipients()
+            .expression(REGEX)
+            .build();
+
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isTrue();
+            softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isTrue();
+            softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isTrue();
+        });
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java
new file mode 100644
index 0000000..fa506b7
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java
@@ -0,0 +1,101 @@
+/****************************************************************
+ * 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.dlp.api;
+
+import static org.apache.james.dlp.api.DLPFixture.RULE;
+import static org.apache.james.dlp.api.DLPFixture.RULE_2;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+
+import org.apache.james.core.Domain;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public interface DLPConfigurationStoreContract {
+
+    Domain OTHER_DOMAIN = Domain.of("any.com");
+
+    @Test
+    default void listShouldReturnEmptyWhenNone(DLPConfigurationStore dlpConfigurationStore) {
+        assertThat(dlpConfigurationStore.list(Domain.LOCALHOST))
+            .isEmpty();
+    }
+
+    @Test
+    default void listShouldReturnExistingEntries(DLPConfigurationStore dlpConfigurationStore) {
+        dlpConfigurationStore.store(Domain.LOCALHOST, RULE);
+        dlpConfigurationStore.store(Domain.LOCALHOST, RULE_2);
+
+        assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).containsOnly(RULE_2);
+    }
+
+    @Test
+    default void listShouldNotReturnEntriesOfOtherDomains(DLPConfigurationStore dlpConfigurationStore) {
+        dlpConfigurationStore.store(Domain.LOCALHOST, RULE);
+        dlpConfigurationStore.store(OTHER_DOMAIN, RULE_2);
+
+        assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).containsOnly(RULE);
+    }
+
+    @Test
+    default void clearShouldRemoveAllEnriesOfADomain(DLPConfigurationStore dlpConfigurationStore) {
+        dlpConfigurationStore.store(Domain.LOCALHOST, RULE);
+        dlpConfigurationStore.store(Domain.LOCALHOST, RULE_2);
+
+        dlpConfigurationStore.clear(Domain.LOCALHOST);
+
+        assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).isEmpty();
+    }
+
+    @Test
+    default void clearShouldNotFailWhenDomainDoesNotExist(DLPConfigurationStore dlpConfigurationStore) {
+        assertThatCode(() -> dlpConfigurationStore.clear(Domain.LOCALHOST))
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    default void clearShouldOnlyRemoveEntriesOfADomain(DLPConfigurationStore dlpConfigurationStore) {
+        dlpConfigurationStore.store(Domain.LOCALHOST, RULE);
+        dlpConfigurationStore.store(OTHER_DOMAIN, RULE_2);
+
+        dlpConfigurationStore.clear(Domain.LOCALHOST);
+
+        assertThat(dlpConfigurationStore.list(OTHER_DOMAIN)).containsOnly(RULE_2);
+    }
+    @Test
+    default void clearShouldOnlyRemovePreviouslyExistingEntries(DLPConfigurationStore dlpConfigurationStore) {
+        dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE, RULE_2));
+
+        dlpConfigurationStore.clear(Domain.LOCALHOST);
+
+        dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE));
+
+        assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).containsOnly(RULE);
+    }
+
+    @Test
+    default void storeShouldOverwritePreviouslyStoredEntries(DLPConfigurationStore dlpConfigurationStore) {
+        dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE, RULE_2));
+        dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE));
+
+        assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).containsOnly(RULE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java
new file mode 100644
index 0000000..9eea6fc
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java
@@ -0,0 +1,34 @@
+/****************************************************************
+ * 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.dlp.api;
+
+public interface DLPFixture {
+    DLPConfigurationItem RULE = DLPConfigurationItem.builder()
+        .explanation("explanation")
+        .expression("regex")
+        .targetsSender()
+        .build();
+    DLPConfigurationItem RULE_2 = DLPConfigurationItem.builder()
+        .explanation("explanation2")
+        .expression("regex2")
+        .targetsSender()
+        .targetsRecipients()
+        .build();
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/pom.xml
----------------------------------------------------------------------
diff --git a/server/data/data-library/pom.xml b/server/data/data-library/pom.xml
index fe9bb3e..1f3d16d 100644
--- a/server/data/data-library/pom.xml
+++ b/server/data/data-library/pom.xml
@@ -39,6 +39,10 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>event-sourcing-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-core</artifactId>
             <scope>test</scope>
         </dependency>
@@ -48,6 +52,12 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-data-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-dnsservice-api</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/EventSourcingDLPConfigurationStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/EventSourcingDLPConfigurationStore.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/EventSourcingDLPConfigurationStore.java
new file mode 100644
index 0000000..f367135
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/EventSourcingDLPConfigurationStore.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.james.dlp.eventsourcing;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.james.core.Domain;
+import org.apache.james.dlp.api.DLPConfigurationItem;
+import org.apache.james.dlp.api.DLPConfigurationStore;
+import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId;
+import org.apache.james.dlp.eventsourcing.aggregates.DLPDomainConfiguration;
+import org.apache.james.dlp.eventsourcing.commands.ClearCommand;
+import org.apache.james.dlp.eventsourcing.commands.ClearCommandHandler;
+import org.apache.james.dlp.eventsourcing.commands.StoreCommand;
+import org.apache.james.dlp.eventsourcing.commands.StoreCommandHandler;
+import org.apache.james.eventsourcing.EventSourcingSystem;
+import org.apache.james.eventsourcing.Subscriber;
+import org.apache.james.eventsourcing.eventstore.EventStore;
+
+import com.google.common.collect.ImmutableSet;
+
+public class EventSourcingDLPConfigurationStore implements DLPConfigurationStore {
+
+    private static final ImmutableSet<Subscriber> NO_SUBSCRIBER = ImmutableSet.of();
+
+    private final EventSourcingSystem eventSourcingSystem;
+    private final EventStore eventStore;
+
+    @Inject
+    public EventSourcingDLPConfigurationStore(EventStore eventStore) {
+        this.eventSourcingSystem = new EventSourcingSystem(
+            ImmutableSet.of(
+                new ClearCommandHandler(eventStore),
+                new StoreCommandHandler(eventStore)),
+            NO_SUBSCRIBER,
+            eventStore);
+        this.eventStore = eventStore;
+    }
+
+    @Override
+    public Stream<DLPConfigurationItem> list(Domain domain) {
+
+        DLPAggregateId aggregateId = new DLPAggregateId(domain);
+
+        return DLPDomainConfiguration.load(
+                aggregateId,
+                eventStore.getEventsOfAggregate(aggregateId))
+            .retrieveRules();
+    }
+
+    @Override
+    public void store(Domain domain, List<DLPConfigurationItem> rules) {
+        eventSourcingSystem.dispatch(new StoreCommand(domain, rules));
+    }
+
+    @Override
+    public void clear(Domain domain) {
+        eventSourcingSystem.dispatch(new ClearCommand(domain));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateId.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateId.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateId.java
new file mode 100644
index 0000000..9e4a61b
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateId.java
@@ -0,0 +1,60 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.aggregates;
+
+import java.util.Objects;
+
+import org.apache.james.core.Domain;
+import org.apache.james.eventsourcing.AggregateId;
+
+import com.google.common.base.Preconditions;
+
+public class DLPAggregateId implements AggregateId {
+    private static final String SEPARATOR = "/";
+    private static final String PREFIX = "DLPRule";
+
+    private final Domain domain;
+
+    public DLPAggregateId(Domain domain) {
+        Preconditions.checkNotNull(domain);
+
+        this.domain = domain;
+    }
+
+    @Override
+    public String asAggregateKey() {
+        return PREFIX + SEPARATOR + domain.asString();
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof DLPAggregateId) {
+            DLPAggregateId that = (DLPAggregateId) o;
+
+            return Objects.equals(this.domain, that.domain);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(domain);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPDomainConfiguration.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPDomainConfiguration.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPDomainConfiguration.java
new file mode 100644
index 0000000..ece6353
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPDomainConfiguration.java
@@ -0,0 +1,151 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.aggregates;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.apache.james.dlp.api.DLPConfigurationItem;
+import org.apache.james.dlp.eventsourcing.events.ConfigurationItemsAdded;
+import org.apache.james.dlp.eventsourcing.events.ConfigurationItemsRemoved;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.eventsourcing.eventstore.History;
+import org.apache.james.util.OptionalUtils;
+
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+public class DLPDomainConfiguration {
+
+    public static DLPDomainConfiguration load(DLPAggregateId aggregateId, History history) {
+        return new DLPDomainConfiguration(aggregateId, history);
+    }
+
+    private static class State {
+
+        static State initial() {
+            return new State(ImmutableSet.of());
+        }
+
+        final ImmutableSet<DLPConfigurationItem> rules;
+
+        private State(ImmutableSet<DLPConfigurationItem> rules) {
+            this.rules = rules;
+        }
+
+        State add(DLPConfigurationItem rule) {
+            return add(ImmutableList.of(rule));
+        }
+
+        State add(List<DLPConfigurationItem> toAdd) {
+            ImmutableSet<DLPConfigurationItem> union = Stream.concat(this.rules.stream(), toAdd.stream()).collect(Guavate.toImmutableSet());
+            return new State(union);
+        }
+
+        State remove(DLPConfigurationItem toRemove) {
+            return remove(ImmutableList.of(toRemove));
+        }
+
+        State remove(List<DLPConfigurationItem> toRemove) {
+            ImmutableSet<DLPConfigurationItem> filtered = rules.stream().filter(rule -> !toRemove.contains(rule)).collect(Guavate.toImmutableSet());
+            return new State(filtered);
+        }
+    }
+
+    private final DLPAggregateId aggregateId;
+    private final History history;
+    private State state;
+
+    private DLPDomainConfiguration(DLPAggregateId aggregateId, History history) {
+        this.aggregateId = aggregateId;
+        this.state = State.initial();
+        history.getEvents().forEach(this::apply);
+        this.history = history;
+    }
+
+    public Stream<DLPConfigurationItem> retrieveRules() {
+        return state.rules.stream();
+    }
+
+    public List<Event> clear() {
+        ImmutableList<DLPConfigurationItem> rules = retrieveRules().collect(Guavate.toImmutableList());
+        if (!rules.isEmpty()) {
+            ImmutableList<Event> events = ImmutableList.of(new ConfigurationItemsRemoved(aggregateId, history.getNextEventId(), rules));
+            events.forEach(this::apply);
+            return events;
+        } else {
+            return ImmutableList.of();
+        }
+    }
+
+    public List<Event> store(List<DLPConfigurationItem> updatedRules) {
+        ImmutableSet<DLPConfigurationItem> existingRules = retrieveRules().collect(Guavate.toImmutableSet());
+        ImmutableSet<DLPConfigurationItem> updatedRulesSet = ImmutableSet.copyOf(updatedRules);
+
+        Optional<Event> removedRulesEvent = generateRemovedRulesEvent(existingRules, updatedRulesSet);
+        Optional<Event> addedRulesEvent = generateAddedRulesEvent(existingRules, updatedRulesSet, computeNextEventId(removedRulesEvent));
+
+        ImmutableList<Event> events = Stream
+            .of(removedRulesEvent, addedRulesEvent)
+            .flatMap(OptionalUtils::toStream)
+            .collect(Guavate.toImmutableList());
+
+        events.forEach(this::apply);
+        return events;
+    }
+
+    private EventId computeNextEventId(Optional<Event> removedRulesEvent) {
+        return removedRulesEvent
+            .map(Event::eventId)
+            .map(EventId::next)
+            .orElse(history.getNextEventId());
+    }
+
+    private Optional<Event> generateRemovedRulesEvent(ImmutableSet<DLPConfigurationItem> existingRules, ImmutableSet<DLPConfigurationItem> updateRulesSet) {
+        Set<DLPConfigurationItem> removedRules = Sets.difference(existingRules, updateRulesSet);
+        if (!removedRules.isEmpty()) {
+            return Optional.of(new ConfigurationItemsRemoved(aggregateId, history.getNextEventId(), removedRules));
+        }
+        return Optional.empty();
+    }
+
+    private Optional<Event> generateAddedRulesEvent(Set<DLPConfigurationItem> existingRules, Set<DLPConfigurationItem> updateRulesSet, EventId nextEventId) {
+        Set<DLPConfigurationItem> addedRules = Sets.difference(updateRulesSet, existingRules);
+        if (!addedRules.isEmpty()) {
+            return Optional.of(new ConfigurationItemsAdded(aggregateId, nextEventId, addedRules));
+        }
+        return Optional.empty();
+    }
+
+    private void apply(Event event) {
+        if (event instanceof ConfigurationItemsAdded) {
+            state = state.add(((ConfigurationItemsAdded) event).getRules());
+        }
+        if (event instanceof ConfigurationItemsRemoved) {
+            state = state.remove(((ConfigurationItemsRemoved) event).getRules());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommand.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommand.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommand.java
new file mode 100644
index 0000000..1cb4513
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommand.java
@@ -0,0 +1,64 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.commands;
+
+import java.util.Objects;
+
+import org.apache.james.core.Domain;
+import org.apache.james.eventsourcing.Command;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+
+public class ClearCommand implements Command {
+    private final Domain domain;
+
+    public ClearCommand(Domain domain) {
+        Preconditions.checkNotNull(domain);
+
+        this.domain = domain;
+    }
+
+    public Domain getDomain() {
+        return domain;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof ClearCommand) {
+            ClearCommand that = (ClearCommand) o;
+
+            return Objects.equals(this.domain, that.domain);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(domain);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("domain", domain)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandHandler.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandHandler.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandHandler.java
new file mode 100644
index 0000000..a0b0c18
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandHandler.java
@@ -0,0 +1,52 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.commands;
+
+import java.util.List;
+
+import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId;
+import org.apache.james.dlp.eventsourcing.aggregates.DLPDomainConfiguration;
+import org.apache.james.eventsourcing.CommandHandler;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.eventstore.EventStore;
+
+public class ClearCommandHandler implements CommandHandler<ClearCommand> {
+
+    private final EventStore eventStore;
+
+    public ClearCommandHandler(EventStore eventStore) {
+        this.eventStore = eventStore;
+    }
+
+    @Override
+    public Class<ClearCommand> handledClass() {
+        return ClearCommand.class;
+    }
+
+    @Override
+    public List<? extends Event> handle(ClearCommand clearCommand) {
+        DLPAggregateId aggregateId = new DLPAggregateId(clearCommand.getDomain());
+
+        return DLPDomainConfiguration.load(
+                aggregateId,
+                eventStore.getEventsOfAggregate(aggregateId))
+            .clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommand.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommand.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommand.java
new file mode 100644
index 0000000..d48bfa4
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommand.java
@@ -0,0 +1,75 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.commands;
+
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.james.core.Domain;
+import org.apache.james.dlp.api.DLPConfigurationItem;
+import org.apache.james.eventsourcing.Command;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+
+public class StoreCommand implements Command {
+    private final Domain domain;
+    private final List<DLPConfigurationItem> rules;
+
+    public StoreCommand(Domain domain, List<DLPConfigurationItem> rules) {
+        Preconditions.checkNotNull(domain);
+        Preconditions.checkNotNull(rules);
+
+        this.domain = domain;
+        this.rules = rules;
+    }
+
+    public Domain getDomain() {
+        return domain;
+    }
+
+    public List<DLPConfigurationItem> getRules() {
+        return rules;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof StoreCommand) {
+            StoreCommand that = (StoreCommand) o;
+
+            return Objects.equals(this.domain, that.domain)
+                && Objects.equals(this.rules, that.rules);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(domain, rules);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("domain", domain)
+            .add("rules", rules)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandHandler.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandHandler.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandHandler.java
new file mode 100644
index 0000000..dc81548
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandHandler.java
@@ -0,0 +1,52 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.commands;
+
+import java.util.List;
+
+import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId;
+import org.apache.james.dlp.eventsourcing.aggregates.DLPDomainConfiguration;
+import org.apache.james.eventsourcing.CommandHandler;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.eventstore.EventStore;
+
+public class StoreCommandHandler implements CommandHandler<StoreCommand> {
+
+    private final EventStore eventStore;
+
+    public StoreCommandHandler(EventStore eventStore) {
+        this.eventStore = eventStore;
+    }
+
+    @Override
+    public Class<StoreCommand> handledClass() {
+        return StoreCommand.class;
+    }
+
+    @Override
+    public List<? extends Event> handle(StoreCommand storeCommand) {
+        DLPAggregateId aggregateId = new DLPAggregateId(storeCommand.getDomain());
+
+        return DLPDomainConfiguration.load(
+                aggregateId,
+                eventStore.getEventsOfAggregate(aggregateId))
+            .store(storeCommand.getRules());
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAdded.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAdded.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAdded.java
new file mode 100644
index 0000000..7a150df
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAdded.java
@@ -0,0 +1,89 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.events;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.james.dlp.api.DLPConfigurationItem;
+import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.EventId;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+public class ConfigurationItemsAdded implements Event {
+    private final DLPAggregateId aggregateId;
+    private final EventId eventId;
+    private final List<DLPConfigurationItem> rules;
+
+    public ConfigurationItemsAdded(DLPAggregateId aggregateId, EventId eventId, Collection<DLPConfigurationItem> rules) {
+        Preconditions.checkNotNull(aggregateId);
+        Preconditions.checkNotNull(eventId);
+        Preconditions.checkNotNull(rules);
+        Preconditions.checkArgument(!rules.isEmpty());
+
+        this.aggregateId = aggregateId;
+        this.eventId = eventId;
+        this.rules = ImmutableList.copyOf(rules);
+    }
+
+    @Override
+    public EventId eventId() {
+        return eventId;
+    }
+
+    public DLPAggregateId getAggregateId() {
+        return aggregateId;
+    }
+
+    public List<DLPConfigurationItem> getRules() {
+        return rules;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof ConfigurationItemsAdded) {
+            ConfigurationItemsAdded that = (ConfigurationItemsAdded) o;
+
+            return Objects.equals(this.aggregateId, that.aggregateId)
+                && Objects.equals(this.eventId, that.eventId)
+                && Objects.equals(this.rules, that.rules);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(aggregateId, eventId, rules);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("aggregateId", aggregateId)
+            .add("eventId", eventId)
+            .add("rules", rules)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemoved.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemoved.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemoved.java
new file mode 100644
index 0000000..572617a
--- /dev/null
+++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemoved.java
@@ -0,0 +1,91 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.events;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.james.dlp.api.DLPConfigurationItem;
+import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId;
+import org.apache.james.eventsourcing.AggregateId;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.EventId;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+public class ConfigurationItemsRemoved implements Event {
+    private final DLPAggregateId aggregateId;
+    private final EventId eventId;
+    private final List<DLPConfigurationItem> rules;
+
+    public ConfigurationItemsRemoved(DLPAggregateId aggregateId, EventId eventId, Collection<DLPConfigurationItem> rules) {
+        Preconditions.checkNotNull(aggregateId);
+        Preconditions.checkNotNull(eventId);
+        Preconditions.checkNotNull(rules);
+        Preconditions.checkArgument(!rules.isEmpty());
+
+        this.aggregateId = aggregateId;
+        this.eventId = eventId;
+        this.rules = ImmutableList.copyOf(rules);
+    }
+
+    @Override
+    public EventId eventId() {
+        return eventId;
+    }
+
+    @Override
+    public AggregateId getAggregateId() {
+        return aggregateId;
+    }
+
+    public List<DLPConfigurationItem> getRules() {
+        return rules;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof ConfigurationItemsRemoved) {
+            ConfigurationItemsRemoved that = (ConfigurationItemsRemoved) o;
+
+            return Objects.equals(this.aggregateId, that.aggregateId)
+                && Objects.equals(this.eventId, that.eventId)
+                && Objects.equals(this.rules, that.rules);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(aggregateId, eventId, rules);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("aggregateId", aggregateId)
+            .add("eventId", eventId)
+            .add("rules", rules)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateIdTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateIdTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateIdTest.java
new file mode 100644
index 0000000..3604974
--- /dev/null
+++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateIdTest.java
@@ -0,0 +1,51 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.dlp.eventsourcing.aggregates;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.core.Domain;
+import org.junit.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class DLPAggregateIdTest {
+
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(DLPAggregateId.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullDomain() {
+        assertThatThrownBy(() -> new DLPAggregateId(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void asAggregateKeyShouldReturnAStringContainingThePrefixAndTheDomain() {
+        assertThat(new DLPAggregateId(Domain.LOCALHOST).asAggregateKey())
+            .isEqualTo("DLPRule/localhost");
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandTest.java
new file mode 100644
index 0000000..d859728
--- /dev/null
+++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandTest.java
@@ -0,0 +1,43 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.commands;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class ClearCommandTest {
+
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(ClearCommand.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullDomain() {
+        assertThatThrownBy(() -> new ClearCommand(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandTest.java
new file mode 100644
index 0000000..5b6b473
--- /dev/null
+++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandTest.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.james.dlp.eventsourcing.commands;
+
+import static org.apache.james.dlp.api.DLPFixture.RULE;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.core.Domain;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class StoreCommandTest {
+
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(StoreCommand.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullDomain() {
+        assertThatThrownBy(() -> new StoreCommand(null, ImmutableList.of(RULE)))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullRules() {
+        assertThatThrownBy(() -> new StoreCommand(Domain.LOCALHOST, null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAddedTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAddedTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAddedTest.java
new file mode 100644
index 0000000..3aa81b5
--- /dev/null
+++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAddedTest.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.events;
+
+import static org.apache.james.dlp.api.DLPFixture.RULE;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.core.Domain;
+import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId;
+import org.apache.james.eventsourcing.EventId;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class ConfigurationItemsAddedTest {
+
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(ConfigurationItemsAdded.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullAggregateId() {
+        assertThatThrownBy(() -> new ConfigurationItemsAdded(null, EventId.first(), ImmutableList.of(RULE)))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullEventId() {
+        assertThatThrownBy(() -> new ConfigurationItemsAdded(new DLPAggregateId(Domain.LOCALHOST), null, ImmutableList.of(RULE)))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullRules() {
+        assertThatThrownBy(() -> new ConfigurationItemsAdded(new DLPAggregateId(Domain.LOCALHOST), EventId.first(), null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void constructorShouldThrowWhenEmptyRulesList() {
+        assertThatThrownBy(() -> new ConfigurationItemsAdded(new DLPAggregateId(Domain.LOCALHOST), EventId.first(), ImmutableList.of()))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemovedTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemovedTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemovedTest.java
new file mode 100644
index 0000000..2a2027b
--- /dev/null
+++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemovedTest.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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.dlp.eventsourcing.events;
+
+import static org.apache.james.dlp.api.DLPFixture.RULE;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.core.Domain;
+import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId;
+import org.apache.james.eventsourcing.EventId;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class ConfigurationItemsRemovedTest {
+
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(ConfigurationItemsRemoved.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullAggregateId() {
+        assertThatThrownBy(() -> new ConfigurationItemsRemoved(null, EventId.first(), ImmutableList.of(RULE)))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullEventId() {
+        assertThatThrownBy(() -> new ConfigurationItemsRemoved(new DLPAggregateId(Domain.LOCALHOST), null, ImmutableList.of()))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void constructorShouldThrowWhenEmptyRulesList() {
+        assertThatThrownBy(() -> new ConfigurationItemsRemoved(new DLPAggregateId(Domain.LOCALHOST), EventId.first(), ImmutableList.of()))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void constructorShouldThrowWhenNullRulesList() {
+        assertThatThrownBy(() -> new ConfigurationItemsRemoved(new DLPAggregateId(Domain.LOCALHOST), EventId.first(), null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-memory/pom.xml
----------------------------------------------------------------------
diff --git a/server/data/data-memory/pom.xml b/server/data/data-memory/pom.xml
index 6b4661b..38c543b 100644
--- a/server/data/data-memory/pom.xml
+++ b/server/data/data-memory/pom.xml
@@ -35,7 +35,18 @@
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>event-sourcing-event-store-memory</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-data-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/EventSourcingDLPConfigurationStoreTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/EventSourcingDLPConfigurationStoreTest.java b/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/EventSourcingDLPConfigurationStoreTest.java
new file mode 100644
index 0000000..a226fce
--- /dev/null
+++ b/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/EventSourcingDLPConfigurationStoreTest.java
@@ -0,0 +1,28 @@
+/****************************************************************
+ * 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.dlp.memory;
+
+import org.apache.james.dlp.api.DLPConfigurationStoreContract;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(InMemoryEventSourcingDLPConfigurationStoreExtension.class)
+public class EventSourcingDLPConfigurationStoreTest implements DLPConfigurationStoreContract {
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/InMemoryEventSourcingDLPConfigurationStoreExtension.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/InMemoryEventSourcingDLPConfigurationStoreExtension.java b/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/InMemoryEventSourcingDLPConfigurationStoreExtension.java
new file mode 100644
index 0000000..fe9392c
--- /dev/null
+++ b/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/InMemoryEventSourcingDLPConfigurationStoreExtension.java
@@ -0,0 +1,40 @@
+/****************************************************************
+ * 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.dlp.memory;
+
+import org.apache.james.dlp.api.DLPConfigurationStore;
+import org.apache.james.dlp.eventsourcing.EventSourcingDLPConfigurationStore;
+import org.apache.james.eventsourcing.eventstore.memory.InMemoryEventStore;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+
+public class InMemoryEventSourcingDLPConfigurationStoreExtension implements ParameterResolver {
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return (parameterContext.getParameter().getType() == DLPConfigurationStore.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return new EventSourcingDLPConfigurationStore(new InMemoryEventStore());
+    }
+}


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