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 ad...@apache.org on 2017/01/18 14:54:14 UTC
[2/2] james-project git commit: MAILET-150 ICalendarParser looks for
ICS, parse it with Ical4J then store it as a mail attribute
MAILET-150 ICalendarParser looks for ICS, parse it with Ical4J then store it as a mail attribute
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/2e4005bc
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/2e4005bc
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/2e4005bc
Branch: refs/heads/master
Commit: 2e4005bc233d5f917f7dd56ffa6b9d74710f7569
Parents: c6edcbc
Author: Quynh Nguyen <qn...@linagora.com>
Authored: Mon Jan 16 11:46:14 2017 +0700
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Wed Jan 18 15:46:51 2017 +0100
----------------------------------------------------------------------
mailet/icalendar/pom.xml | 6 +-
.../transport/mailets/ICalendarParser.java | 128 ++++++++++
.../transport/mailets/ICalendarParserTest.java | 235 +++++++++++++++++++
mailet/pom.xml | 13 +-
4 files changed, 380 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/2e4005bc/mailet/icalendar/pom.xml
----------------------------------------------------------------------
diff --git a/mailet/icalendar/pom.xml b/mailet/icalendar/pom.xml
index f63a699..7c35346 100644
--- a/mailet/icalendar/pom.xml
+++ b/mailet/icalendar/pom.xml
@@ -187,6 +187,10 @@
<artifactId>guava</artifactId>
</dependency>
<dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
@@ -283,4 +287,4 @@
</profiles>
-</project>
\ No newline at end of file
+</project>
http://git-wip-us.apache.org/repos/asf/james-project/blob/2e4005bc/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java
----------------------------------------------------------------------
diff --git a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java
new file mode 100644
index 0000000..6930556
--- /dev/null
+++ b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java
@@ -0,0 +1,128 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.transport.mailets;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import javax.mail.MessagingException;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+
+import com.github.steveash.guavate.Guavate;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+import net.fortuna.ical4j.data.CalendarBuilder;
+import net.fortuna.ical4j.data.ParserException;
+import net.fortuna.ical4j.model.Calendar;
+
+/**
+ * <p>
+ * This mailet can be combined with the Strip attachment mailet.
+ * </p>
+ * <p>
+ * The ICS body part byte array is arranged as map then this mailet should look for ICS and parse it with Ical4J then store it as a mail attribute
+ * </p>
+ * <p>
+ * Configuration: The mailet contains 2 mandatory attributes
+ * </p>
+ * <p>
+ *
+ * <pre>
+ * <mailet match="All" class="ICalendarParser" >
+ * <sourceAttribute>source.attribute.name</sourceAttribute> <!-- The attribute which contains output value of StripAttachment mailet -- >
+ * <destAttribute>dest.attribute.name</destAttribute> <!-- The attribute store the map of Calendar -- >
+ * </mailet >
+ *
+ * </pre>
+ *
+ * </p>
+ */
+public class ICalendarParser extends GenericMailet {
+ public static final String SOURCE_ATTRIBUTE_PARAMETER_NAME = "sourceAttribute";
+ public static final String DESTINATION_ATTRIBUTE_PARAMETER_NAME = "destinationAttribute";
+
+ public static final String SOURCE_ATTRIBUTE_PARAMETER_DEFAULT_VALUE = "icsAttachments";
+ public static final String DESTINATION_ATTRIBUTE_PARAMETER_DEFAULT_VALUE = "calendars";
+
+ private String sourceAttributeName;
+ private String destinationAttributeName;
+
+ @Override
+ public void init() throws MessagingException {
+ sourceAttributeName = getInitParameter(SOURCE_ATTRIBUTE_PARAMETER_NAME, SOURCE_ATTRIBUTE_PARAMETER_DEFAULT_VALUE);
+ if (Strings.isNullOrEmpty(sourceAttributeName)) {
+ throw new MessagingException("source attribute cannot be empty");
+ }
+ destinationAttributeName = getInitParameter(DESTINATION_ATTRIBUTE_PARAMETER_NAME, DESTINATION_ATTRIBUTE_PARAMETER_DEFAULT_VALUE);
+ if (Strings.isNullOrEmpty(destinationAttributeName)) {
+ throw new MessagingException("destination attribute cannot be empty");
+ }
+ }
+
+ @VisibleForTesting
+ public String getSourceAttributeName() {
+ return sourceAttributeName;
+ }
+
+ @VisibleForTesting
+ public String getDestinationAttributeName() {
+ return destinationAttributeName;
+ }
+
+ @Override
+ public void service(Mail mail) throws MessagingException {
+ Object icsAttachmentsObj = mail.getAttribute(sourceAttributeName);
+ if (icsAttachmentsObj == null || !(icsAttachmentsObj instanceof Map)) {
+ return;
+ }
+
+ Map<String, byte[]> icsAttachments = (Map<String, byte[]>) icsAttachmentsObj;
+ Map<String, Calendar> calendars = icsAttachments.entrySet()
+ .stream()
+ .flatMap(entry -> createCalendar(entry.getKey(), entry.getValue()))
+ .collect(Guavate.toImmutableMap(Pair::getKey, Pair::getValue));
+
+ mail.setAttribute(destinationAttributeName, (Serializable) calendars);
+ }
+
+ @Override
+ public String getMailetInfo() {
+ return "Calendar Parser";
+ }
+
+ private Stream<Pair<String, Calendar>> createCalendar(String key, byte[] icsContent) {
+ CalendarBuilder builder = new CalendarBuilder();
+ try {
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(icsContent);
+ return Stream.of(Pair.of(key, builder.build(inputStream)));
+ } catch (IOException e) {
+ log("Error while reading input: " + icsContent, e);
+ return Stream.of();
+ } catch (ParserException e) {
+ log("Error while parsing ICal object: " + icsContent, e);
+ return Stream.of();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/2e4005bc/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java
----------------------------------------------------------------------
diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java
new file mode 100644
index 0000000..c65f69f
--- /dev/null
+++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java
@@ -0,0 +1,235 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.transport.mailets;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import javax.mail.MessagingException;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.test.FakeMail;
+import org.apache.mailet.base.test.FakeMailetConfig;
+import org.apache.mailet.base.test.MimeMessageBuilder;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import net.fortuna.ical4j.model.Calendar;
+
+public class ICalendarParserTest {
+ private static final String DESTINATION_ATTRIBUTE = "destinationAttribute";
+ private static final String SOURCE_ATTRIBUTE = "sourceAttribute";
+
+ private static final String DESTINATION_CUSTOM_ATTRIBUTE = "ics.dest.attribute";
+ private static final String SOURCE_CUSTOM_ATTRIBUTE = "ics.source.attribute";
+
+ private static final String CONTENT_TRANSFER_ENCODING_VALUE ="8bit";
+
+ private static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static final String TEXT_CALENDAR_CHARSET_UTF_8 = "text/calendar; charset=utf-8";
+
+ private static final String RIGHT_ICAL_VALUE = "BEGIN:VCALENDAR\n" +
+ "END:VCALENDAR";
+
+ private static final String WRONG_ICAL_VALUE = "anyValue";
+
+ private static MimeMessageBuilder.Header[] CALENDAR_HEADERS = {
+ new MimeMessageBuilder.Header(CONTENT_TRANSFER_ENCODING, CONTENT_TRANSFER_ENCODING_VALUE),
+ new MimeMessageBuilder.Header(CONTENT_TYPE, TEXT_CALENDAR_CHARSET_UTF_8)
+ };
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private ICalendarParser mailet = new ICalendarParser();
+
+ @Test
+ public void initShouldSetSourceAttributeWhenAbsent() throws Exception {
+ mailet.init(FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .build());
+
+ assertThat(mailet.getSourceAttributeName()).isEqualTo(ICalendarParser.SOURCE_ATTRIBUTE_PARAMETER_DEFAULT_VALUE);
+ }
+
+ @Test
+ public void initShouldSetDestinationAttributeWhenAbsent() throws Exception {
+ mailet.init(FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .build());
+
+ assertThat(mailet.getDestinationAttributeName()).isEqualTo(ICalendarParser.DESTINATION_ATTRIBUTE_PARAMETER_DEFAULT_VALUE);
+ }
+
+ @Test
+ public void initShouldSetSourceAttributeWhenPresent() throws Exception {
+ String sourceAttribute = "sourceAttribute";
+ mailet.init(FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(ICalendarParser.SOURCE_ATTRIBUTE_PARAMETER_NAME, sourceAttribute)
+ .build());
+
+ assertThat(mailet.getSourceAttributeName()).isEqualTo(sourceAttribute);
+ }
+
+ @Test
+ public void initShouldSetDestinationAttributeWhenPresent() throws Exception {
+ String destinationAttribute = "destinationAttribute";
+ mailet.init(FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(ICalendarParser.DESTINATION_ATTRIBUTE_PARAMETER_NAME, destinationAttribute)
+ .build());
+
+ assertThat(mailet.getDestinationAttributeName()).isEqualTo(destinationAttribute);
+ }
+
+ @Test
+ public void initShouldThrowOnEmptySourceAttribute() throws Exception {
+ expectedException.expect(MessagingException.class);
+
+ mailet.init(FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(ICalendarParser.SOURCE_ATTRIBUTE_PARAMETER_NAME, "")
+ .build());
+ }
+
+ @Test
+ public void initShouldThrowOnEmptyDestinationAttribute() throws Exception {
+ expectedException.expect(MessagingException.class);
+
+ mailet.init(FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(ICalendarParser.DESTINATION_ATTRIBUTE_PARAMETER_NAME, "")
+ .build());
+ }
+
+ @Test
+ public void serviceShouldNotSetCalendarDataIntoMailAttributeWhenNoSourceAttribute() throws Exception {
+ FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(DESTINATION_ATTRIBUTE, DESTINATION_CUSTOM_ATTRIBUTE)
+ .build();
+ mailet.init(mailetConfiguration);
+
+ Mail mail = FakeMail.builder()
+ .build();
+
+ mailet.service(mail);
+
+ assertThat(mail.getAttributeNames()).isEmpty();
+ }
+
+ @Test
+ public void serviceShouldSetEmptyCalendarDataIntoMailAttributeWhenEmptyICSAttachments() throws Exception {
+ FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(SOURCE_ATTRIBUTE, SOURCE_CUSTOM_ATTRIBUTE)
+ .setProperty(DESTINATION_ATTRIBUTE, DESTINATION_CUSTOM_ATTRIBUTE)
+ .build();
+ mailet.init(mailetConfiguration);
+
+ Mail mail = FakeMail.builder()
+ .attribute(SOURCE_CUSTOM_ATTRIBUTE, ImmutableMap.of())
+ .build();
+
+ mailet.service(mail);
+
+ assertThat((Map<String, Calendar>)mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE))
+ .isEmpty();
+ }
+
+ @Test
+ public void serviceShouldNotSetCalendarDataIntoMailAttributeWhenSourceAttributeIsNotAMap() throws Exception {
+ FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(SOURCE_ATTRIBUTE, SOURCE_CUSTOM_ATTRIBUTE)
+ .setProperty(DESTINATION_ATTRIBUTE, DESTINATION_CUSTOM_ATTRIBUTE)
+ .build();
+ mailet.init(mailetConfiguration);
+
+ Mail mail = FakeMail.builder()
+ .attribute(SOURCE_CUSTOM_ATTRIBUTE, "anyValue")
+ .build();
+
+ mailet.service(mail);
+
+ assertThat(mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE)).isNull();
+ }
+
+ @Test
+ public void serviceShouldReturnRightMapOfCalendarWhenRightAttachments() throws Exception {
+ FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(SOURCE_ATTRIBUTE, SOURCE_CUSTOM_ATTRIBUTE)
+ .setProperty(DESTINATION_ATTRIBUTE, DESTINATION_CUSTOM_ATTRIBUTE)
+ .build();
+ mailet.init(mailetConfiguration);
+
+ Map<String, byte[]> attachments = ImmutableMap.<String, byte[]>builder()
+ .put("key", RIGHT_ICAL_VALUE.getBytes())
+ .build();
+
+ Mail mail = FakeMail.builder()
+ .attribute(SOURCE_CUSTOM_ATTRIBUTE, (Serializable) attachments)
+ .build();
+
+ mailet.service(mail);
+
+ Map<String, Calendar> expectedCalendars = (Map<String, Calendar>)mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE);
+ assertThat(expectedCalendars).hasSize(1);
+ }
+
+ @Test
+ public void serviceShouldFilterResultWhenErrorParsing() throws Exception {
+ FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
+ .mailetName("ICalendarParser")
+ .setProperty(SOURCE_ATTRIBUTE, SOURCE_CUSTOM_ATTRIBUTE)
+ .setProperty(DESTINATION_ATTRIBUTE, DESTINATION_CUSTOM_ATTRIBUTE)
+ .build();
+ mailet.init(mailetConfiguration);
+
+ Map<String, byte[]> attachments = ImmutableMap.<String, byte[]>builder()
+ .put("key1", WRONG_ICAL_VALUE.getBytes())
+ .put("key2", RIGHT_ICAL_VALUE.getBytes())
+ .build();
+ Mail mail = FakeMail.builder()
+ .attribute(SOURCE_CUSTOM_ATTRIBUTE, (Serializable) attachments)
+ .build();
+
+ mailet.service(mail);
+
+ Map<String, Calendar> expectedCalendars = (Map<String, Calendar>)mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE);
+ Map.Entry<String, Calendar> expectedCalendar = Maps.immutableEntry("key2", new Calendar());
+
+ assertThat(expectedCalendars).hasSize(1)
+ .containsExactly(expectedCalendar);
+ }
+
+ @Test
+ public void getMailetInfoShouldReturn() throws MessagingException {
+ assertThat(mailet.getMailetInfo()).isEqualTo("Calendar Parser");
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/2e4005bc/mailet/pom.xml
----------------------------------------------------------------------
diff --git a/mailet/pom.xml b/mailet/pom.xml
index b5d7cb6..8b443b0 100644
--- a/mailet/pom.xml
+++ b/mailet/pom.xml
@@ -46,6 +46,7 @@
<commons-collections.version>3.2.1</commons-collections.version>
<commons-io.version>2.4</commons-io.version>
<commons-lang.version>2.6</commons-lang.version>
+ <commons-lang3.version>3.3.2</commons-lang3.version>
<httpclient-osgi.version>4.5.1</httpclient-osgi.version>
<!-- maven-mailetdocs-plugin artifacts -->
<maven-artifact.version>3.0-alpha-1</maven-artifact.version>
@@ -62,7 +63,7 @@
<jackson-data.version>2.6.3</jackson-data.version>
<guavate.version>1.0.0</guavate.version>
<ical4j.version>1.0.2</ical4j.version>
- <assertj-3.version>3.3.0</assertj-3.version>
+ <guavate.version>1.0.0</guavate.version>
</properties>
@@ -165,6 +166,11 @@
<version>${commons-io.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>${commons-lang3.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-osgi</artifactId>
<version>${httpclient-osgi.version}</version>
@@ -197,6 +203,11 @@
<version>18.0</version>
</dependency>
<dependency>
+ <groupId>com.github.steveash.guavate</groupId>
+ <artifactId>guavate</artifactId>
+ <version>${guavate.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org