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 2016/01/18 12:42:08 UTC
svn commit: r1725240 - in /james/project/trunk/server: ./
protocols/jmap-integration-testing/
protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/
protocols/jmap/ protocols/jmap/src/main/java/org/apache/james/jmap/methods/
pr...
Author: aduprat
Date: Mon Jan 18 11:42:07 2016
New Revision: 1725240
URL: http://svn.apache.org/viewvc?rev=1725240&view=rev
Log:
JAMES-1648 Handle header filtering. Contributed by Ouazana <ra...@linagora.com>
Added:
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessagePropertyTest.java
Modified:
james/project/trunk/server/pom.xml
james/project/trunk/server/protocols/jmap-integration-testing/pom.xml
james/project/trunk/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java
james/project/trunk/server/protocols/jmap/pom.xml
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponse.java
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponseWriterImpl.java
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageProperty.java
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java
Modified: james/project/trunk/server/pom.xml
URL: http://svn.apache.org/viewvc/james/project/trunk/server/pom.xml?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/pom.xml (original)
+++ james/project/trunk/server/pom.xml Mon Jan 18 11:42:07 2016
@@ -1399,6 +1399,11 @@
<version>1.6.3</version>
</dependency>
<dependency>
+ <groupId>com.jayway.jsonpath</groupId>
+ <artifactId>json-path</artifactId>
+ <version>2.1.0</version>
+ </dependency>
+ <dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>2.6.0</version>
Modified: james/project/trunk/server/protocols/jmap-integration-testing/pom.xml
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap-integration-testing/pom.xml?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap-integration-testing/pom.xml (original)
+++ james/project/trunk/server/protocols/jmap-integration-testing/pom.xml Mon Jan 18 11:42:07 2016
@@ -183,7 +183,6 @@
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
- <version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.jayway.restassured</groupId>
Modified: james/project/trunk/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java (original)
+++ james/project/trunk/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java Mon Jan 18 11:42:07 2016
@@ -50,7 +50,10 @@ import org.junit.rules.RuleChain;
import org.junit.rules.TemporaryFolder;
import com.google.common.base.Charsets;
+import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
+import com.jayway.jsonpath.Option;
+import com.jayway.jsonpath.ParseContext;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.http.ContentType;
@@ -70,11 +73,15 @@ public abstract class GetMessagesMethodT
.around(jmapServer);
private AccessToken accessToken;
+ private ParseContext jsonPath;
@Before
public void setup() throws Exception {
RestAssured.port = jmapServer.getPort();
RestAssured.config = newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8));
+ jsonPath = JsonPath.using(Configuration.builder()
+ .options(Option.DEFAULT_PATH_LEAF_TO_NULL)
+ .build());
String domain = "domain.tld";
String username = "username@" + domain;
@@ -201,4 +208,79 @@ public abstract class GetMessagesMethodT
assertThat(JsonPath.parse(response).<Map<String, String>>read(firstMessagePath + ".headers")).containsExactly(MapEntry.entry("subject", "my test subject"));
assertThat(JsonPath.parse(response).<String>read(firstMessagePath + ".date")).isEqualTo("2014-10-30T14:12:00Z");
}
+
+ @Test
+ public void getMessagesShouldReturnFilteredPropertiesMessagesWhenAsked() throws Exception {
+ ZonedDateTime dateTime = ZonedDateTime.parse("2014-10-30T14:12:00Z");
+ jmapServer.serverProbe().appendMessage("username", new MailboxPath(MailboxConstants.USER_NAMESPACE, "username", "inbox"),
+ new ByteArrayInputStream("Subject: my test subject\r\n\r\ntestmail".getBytes()), Date.from(dateTime.toInstant()), false, new Flags());
+
+ embeddedElasticSearch.awaitForElasticSearch();
+
+ String response = given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"username-inbox-1\"], \"properties\": [\"id\", \"subject\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .content(startsWith("[[\"messages\","))
+ .extract()
+ .asString();
+
+ String firstResponsePath = "$.[0].[1]";
+ String firstMessagePath = firstResponsePath + ".list[0]";
+
+ assertThat(jsonPath.parse(response).<Integer>read("$.length()")).isEqualTo(1);
+ assertThat(jsonPath.parse(response).<Integer>read(firstResponsePath + ".list.length()")).isEqualTo(1);
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".id")).isEqualTo("username@domain.tld-inbox-1");
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".subject")).isEqualTo("my test subject");
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".textBody")).isNull();
+ assertThat(jsonPath.parse(response).<Boolean>read(firstMessagePath + ".isUnread")).isNull();
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".preview")).isNull();
+ assertThat(jsonPath.parse(response).<Map<String, String>>read(firstMessagePath + ".headers")).isNull();
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".date")).isNull();
+ }
+
+ @Test
+ public void getMessagesShouldReturnFilteredHeaderPropertyWhenAsked() throws Exception {
+ ZonedDateTime dateTime = ZonedDateTime.parse("2014-10-30T14:12:00Z");
+ jmapServer.serverProbe().appendMessage("username", new MailboxPath(MailboxConstants.USER_NAMESPACE, "username", "inbox"),
+ new ByteArrayInputStream(("From: user@domain.tld\r\n"
+ + "header1: Header1Content\r\n"
+ + "HEADer2: Header2Content\r\n"
+ + "Subject: my test subject\r\n"
+ + "\r\n"
+ + "testmail").getBytes()), Date.from(dateTime.toInstant()), false, new Flags());
+
+ embeddedElasticSearch.awaitForElasticSearch();
+
+ String response = given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"username-inbox-1\"], \"properties\": [\"headers.from\", \"headers.heADER2\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .content(startsWith("[[\"messages\","))
+ .extract()
+ .asString();
+
+ String firstResponsePath = "$.[0].[1]";
+ String firstMessagePath = firstResponsePath + ".list[0]";
+
+ assertThat(jsonPath.parse(response).<Integer>read("$.length()")).isEqualTo(1);
+ assertThat(jsonPath.parse(response).<Integer>read(firstResponsePath + ".list.length()")).isEqualTo(1);
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".id")).isEqualTo("username@domain.tld-inbox-1");
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".subject")).isNull();
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".textBody")).isNull();
+ assertThat(jsonPath.parse(response).<Boolean>read(firstMessagePath + ".isUnread")).isNull();
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".preview")).isNull();
+ assertThat(jsonPath.parse(response).<Map<String, String>>read(firstMessagePath + ".headers")).containsOnly(MapEntry.entry("from", "user@domain.tld"), MapEntry.entry("header2", "Header2Content"));
+ assertThat(jsonPath.parse(response).<String>read(firstMessagePath + ".date")).isNull();
+ }
}
Modified: james/project/trunk/server/protocols/jmap/pom.xml
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/pom.xml?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap/pom.xml (original)
+++ james/project/trunk/server/protocols/jmap/pom.xml Mon Jan 18 11:42:07 2016
@@ -251,6 +251,11 @@
<type>test-jar</type>
</dependency>
<dependency>
+ <groupId>com.jayway.jsonpath</groupId>
+ <artifactId>json-path</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
Modified: james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java (original)
+++ james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java Mon Jan 18 11:42:07 2016
@@ -19,9 +19,9 @@
package org.apache.james.jmap.methods;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -48,18 +48,22 @@ import org.apache.james.mailbox.store.ma
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
import org.javatuples.Pair;
+import com.fasterxml.jackson.databind.ser.PropertyWriter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.github.fge.lambdas.Throwing;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
public class GetMessagesMethod<Id extends MailboxId> implements Method {
+ public static final String HEADERS_FILTER = "headersFilter";
private static final Method.Request.Name METHOD_NAME = Method.Request.name("getMessages");
private static final Method.Response.Name RESPONSE_NAME = Method.Response.name("messages");
private final MessageMapperFactory<Id> messageMapperFactory;
private final MailboxMapperFactory<Id> mailboxMapperFactory;
-
@Inject
@VisibleForTesting GetMessagesMethod(
@@ -85,18 +89,21 @@ public class GetMessagesMethod<Id extend
Preconditions.checkNotNull(mailboxSession);
Preconditions.checkArgument(request instanceof GetMessagesRequest);
GetMessagesRequest getMessagesRequest = (GetMessagesRequest) request;
+ Optional<ImmutableSet<MessageProperty>> requestedProperties = getMessagesRequest.getProperties();
return Stream.of(JmapResponse.builder().clientId(clientId)
- .response(getMessagesResponse(mailboxSession, getMessagesRequest))
+ .response(getMessagesResponse(mailboxSession, getMessagesRequest, requestedProperties))
.responseName(RESPONSE_NAME)
- .properties(getMessagesRequest.getProperties().map(this::handleSpecificProperties))
+ .properties(requestedProperties.map(this::handleSpecificProperties))
+ .filterProvider(Optional.of(buildFilteringHeadersFilterProvider(requestedProperties)))
.build());
}
private Set<MessageProperty> handleSpecificProperties(Set<MessageProperty> input) {
- Set<MessageProperty> toAdd = new HashSet<MessageProperty>();
- Set<MessageProperty> toRemove = new HashSet<MessageProperty>();
+ Set<MessageProperty> toAdd = Sets.newHashSet();
+ Set<MessageProperty> toRemove = Sets.newHashSet();
ensureContainsId(input, toAdd);
handleBody(input, toAdd, toRemove);
+ handleHeadersProperties(input, toAdd, toRemove);
return Sets.union(Sets.difference(input, toRemove), toAdd).immutableCopy();
}
@@ -112,8 +119,48 @@ public class GetMessagesMethod<Id extend
toRemove.add(MessageProperty.body);
}
}
+
+ private void handleHeadersProperties(Set<MessageProperty> input, Set<MessageProperty> toAdd, Set<MessageProperty> toRemove) {
+ Set<MessageProperty> selectHeadersProperties = MessageProperty.selectHeadersProperties(input);
+ if (!selectHeadersProperties.isEmpty()) {
+ toAdd.add(MessageProperty.headers);
+ toRemove.addAll(selectHeadersProperties);
+ }
+ }
+
+ private SimpleFilterProvider buildFilteringHeadersFilterProvider(Optional<ImmutableSet<MessageProperty>> requestedProperties) {
+ Set<MessageProperty> selectedHeadersProperties = requestedProperties
+ .map(MessageProperty::selectHeadersProperties)
+ .orElse(ImmutableSet.of());
+
+ return new SimpleFilterProvider()
+ .addFilter(HEADERS_FILTER, buildPropertyFilter(selectedHeadersProperties))
+ .addFilter(JmapResponseWriterImpl.PROPERTIES_FILTER, SimpleBeanPropertyFilter.serializeAll());
+ }
+
+ private SimpleBeanPropertyFilter buildPropertyFilter(Set<MessageProperty> propertiesToInclude) {
+ if (propertiesToInclude.isEmpty()) {
+ return SimpleBeanPropertyFilter.serializeAll();
+ } else {
+ return new IncludeMessagePropertyPropertyFilter(propertiesToInclude);
+ }
+ }
+
+ private static class IncludeMessagePropertyPropertyFilter extends SimpleBeanPropertyFilter {
+ private Set<MessageProperty> propertiesToInclude;
- private GetMessagesResponse getMessagesResponse(MailboxSession mailboxSession, GetMessagesRequest getMessagesRequest) {
+ public IncludeMessagePropertyPropertyFilter(Set<MessageProperty> propertiesToInclude) {
+ this.propertiesToInclude = propertiesToInclude;
+ }
+
+ @Override
+ protected boolean include(PropertyWriter writer) {
+ String currentProperty = writer.getName();
+ return propertiesToInclude.contains(MessageProperty.headerValueOf(currentProperty));
+ }
+ }
+
+ private GetMessagesResponse getMessagesResponse(MailboxSession mailboxSession, GetMessagesRequest getMessagesRequest, Optional<ImmutableSet<MessageProperty>> requestedProperties) {
getMessagesRequest.getAccountId().ifPresent(GetMessagesMethod::notImplemented);
Function<MessageId, Stream<Pair<MailboxMessage<Id>, MailboxPath>>> loadMessages = loadMessage(mailboxSession);
Modified: james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponse.java
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponse.java?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponse.java (original)
+++ james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponse.java Mon Jan 18 11:42:07 2016
@@ -25,6 +25,7 @@ import java.util.Set;
import org.apache.james.jmap.model.ClientId;
import org.apache.james.jmap.model.Property;
+import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.google.common.annotations.VisibleForTesting;
public class JmapResponse {
@@ -39,6 +40,7 @@ public class JmapResponse {
private ClientId id;
private Method.Response response;
private Optional<? extends Set<? extends Property>> properties = Optional.empty();
+ private Optional<SimpleFilterProvider> filterProvider = Optional.empty();
private Builder() {
}
@@ -67,6 +69,11 @@ public class JmapResponse {
this.properties = Optional.ofNullable(properties);
return this;
}
+
+ public Builder filterProvider(Optional<SimpleFilterProvider> filterProvider) {
+ this.filterProvider = filterProvider;
+ return this;
+ }
public Builder error() {
return error(DEFAULT_ERROR_MESSAGE);
@@ -80,7 +87,7 @@ public class JmapResponse {
public JmapResponse build() {
- return new JmapResponse(responseName, id, response, properties);
+ return new JmapResponse(responseName, id, response, properties, filterProvider);
}
}
@@ -105,12 +112,14 @@ public class JmapResponse {
private final ClientId clientId;
private final Method.Response response;
private Optional<? extends Set<? extends Property>> properties;
+ private Optional<SimpleFilterProvider> filterProvider;
- private JmapResponse(Method.Response.Name method, ClientId clientId, Method.Response response, Optional<? extends Set<? extends Property>> properties) {
+ private JmapResponse(Method.Response.Name method, ClientId clientId, Method.Response response, Optional<? extends Set<? extends Property>> properties, Optional<SimpleFilterProvider> filterProvider) {
this.method = method;
this.clientId = clientId;
this.response = response;
this.properties = properties;
+ this.filterProvider = filterProvider;
}
public Method.Response.Name getResponseName() {
@@ -128,4 +137,8 @@ public class JmapResponse {
public Optional<? extends Set<? extends Property>> getProperties() {
return properties;
}
+
+ public Optional<SimpleFilterProvider> getFilterProvider() {
+ return filterProvider;
+ }
}
Modified: james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponseWriterImpl.java
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponseWriterImpl.java?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponseWriterImpl.java (original)
+++ james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/JmapResponseWriterImpl.java Mon Jan 18 11:42:07 2016
@@ -39,6 +39,7 @@ import com.fasterxml.jackson.databind.se
public class JmapResponseWriterImpl implements JmapResponseWriter {
+ public static final String PROPERTIES_FILTER = "propertiesFilter";
private final Set<Module> jacksonModules;
@Inject
@@ -59,20 +60,25 @@ public class JmapResponseWriterImpl impl
}
private ObjectMapper newConfiguredObjectMapper(JmapResponse jmapResponse) {
- ObjectMapper objectMapper = new ObjectMapper().registerModules(jacksonModules)
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.registerModules(jacksonModules)
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
-
- objectMapper.setFilterProvider(buildPropertiesFilter(jmapResponse.getProperties()));
+
+ FilterProvider filterProvider = jmapResponse
+ .getFilterProvider()
+ .orElseGet(SimpleFilterProvider::new)
+ .addFilter(PROPERTIES_FILTER, getPropertiesFilter(jmapResponse.getProperties()));
+
+ objectMapper.setFilterProvider(filterProvider);
return objectMapper;
}
-
- private FilterProvider buildPropertiesFilter(Optional<? extends Set<? extends Property>> properties) {
- PropertyFilter filter = properties
+
+ private PropertyFilter getPropertiesFilter(Optional<? extends Set<? extends Property>> properties) {
+ return properties
.map(this::toFieldNames)
.map(SimpleBeanPropertyFilter::filterOutAllExcept)
.orElse(SimpleBeanPropertyFilter.serializeAll());
- return new SimpleFilterProvider().addFilter("propertiesFilter", filter);
}
private Set<String> toFieldNames(Set<? extends Property> properties) {
Modified: james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java (original)
+++ james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java Mon Jan 18 11:42:07 2016
@@ -30,6 +30,8 @@ import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonFilter;
import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.jmap.methods.GetMessagesMethod;
+import org.apache.james.jmap.methods.JmapResponseWriterImpl;
import org.apache.james.jmap.model.message.EMailer;
import org.apache.james.jmap.model.message.IndexableMessage;
import org.apache.james.mailbox.store.extractor.DefaultTextExtractor;
@@ -46,7 +48,7 @@ import com.google.common.collect.Multima
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
@JsonDeserialize(builder = Message.Builder.class)
-@JsonFilter("propertiesFilter")
+@JsonFilter(JmapResponseWriterImpl.PROPERTIES_FILTER)
public class Message {
public static final String NO_SUBJECT = "(No subject)";
public static final String MULTIVALUED_HEADERS_SEPARATOR = ", ";
@@ -343,6 +345,7 @@ public class Message {
private final boolean isAnswered;
private final boolean isDraft;
private final boolean hasAttachment;
+ @JsonFilter(GetMessagesMethod.HEADERS_FILTER)
private final ImmutableMap<String, String> headers;
private final Optional<Emailer> from;
private final ImmutableList<Emailer> to;
Modified: james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageProperty.java
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageProperty.java?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageProperty.java (original)
+++ james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageProperty.java Mon Jan 18 11:42:07 2016
@@ -18,47 +18,89 @@
****************************************************************/
package org.apache.james.jmap.model;
-import com.google.common.collect.ImmutableSet;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Set;
-public enum MessageProperty implements Property {
- id("id"),
- blobId("blobId"),
- threadId("threadId"),
- mailboxIds("mailboxIds"),
- inReplyToMessageId("inReplyToMessageId"),
- isUnread("isUnread"),
- isFlagged("isFlagged"),
- isAnswered("isAnswered"),
- isDraft("isDraft"),
- hasAttachment("hasAttachment"),
- headers("headers"),
- from("from"),
- to("to"),
- cc("cc"),
- bcc("bcc"),
- replyTo("replyTo"),
- subject("subject"),
- date("date"),
- size("size"),
- preview("preview"),
- textBody("textBody"),
- htmlBody("htmlBody"),
- attachments("attachments"),
- attachedMessages("attachedMessages"),
- body("body"),
- headers_property("headers.property");
+import org.apache.james.util.streams.Collectors;
+
+import com.google.common.base.Preconditions;
+
+public class MessageProperty implements Property {
+ public static MessageProperty id = valueOf("id");
+ public static MessageProperty blobId = valueOf("blobId");
+ public static MessageProperty threadId = valueOf("threadId");
+ public static MessageProperty mailboxIds = valueOf("mailboxIds");
+ public static MessageProperty inReplyToMessageId = valueOf("inReplyToMessageId");
+ public static MessageProperty isUnread = valueOf("isUnread");
+ public static MessageProperty isFlagged = valueOf("isFlagged");
+ public static MessageProperty isAnswered = valueOf("isAnswered");
+ public static MessageProperty isDraft = valueOf("isDraft");
+ public static MessageProperty hasAttachment = valueOf("hasAttachment");
+ public static MessageProperty headers = valueOf("headers");
+ public static MessageProperty from = valueOf("from");
+ public static MessageProperty to = valueOf("to");
+ public static MessageProperty cc = valueOf("cc");
+ public static MessageProperty bcc = valueOf("bcc");
+ public static MessageProperty replyTo = valueOf("replyTo");
+ public static MessageProperty subject = valueOf("subject");
+ public static MessageProperty date = valueOf("date");
+ public static MessageProperty size = valueOf("size");
+ public static MessageProperty preview = valueOf("preview");
+ public static MessageProperty textBody = valueOf("textBody");
+ public static MessageProperty htmlBody = valueOf("htmlBody");
+ public static MessageProperty attachments = valueOf("attachments");
+ public static MessageProperty attachedMessages = valueOf("attachedMessages");
+ public static MessageProperty body = valueOf("body");
+
+ private static String HEADER_PROPERTY_PREFIX = "headers.";
private String property;
+
+ private MessageProperty(String property) {
+ this.property = property.toLowerCase(Locale.US);
+ }
- MessageProperty(String property) {
- this.property = property;
+ public static MessageProperty valueOf(String property) {
+ return new MessageProperty(property);
+ }
+
+ public static MessageProperty headerValueOf(String headerProperty) {
+ Preconditions.checkNotNull(headerProperty);
+ return new MessageProperty(HEADER_PROPERTY_PREFIX + headerProperty);
}
+ public static Set<MessageProperty> selectHeadersProperties(Set<MessageProperty> properties) {
+ return properties.stream()
+ .filter(MessageProperty::isHeaderProperty)
+ .collect(Collectors.toImmutableSet());
+ }
+
+ @Override
public String asFieldName() {
return property;
}
- public static ImmutableSet<MessageProperty> all() {
- return ImmutableSet.copyOf(values());
+ public boolean isHeaderProperty() {
+ return property.startsWith(HEADER_PROPERTY_PREFIX);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof MessageProperty) {
+ MessageProperty other = (MessageProperty) obj;
+ return Objects.equals(this.property, other.property);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(property);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toString(property);
}
}
Modified: james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java?rev=1725240&r1=1725239&r2=1725240&view=diff
==============================================================================
--- james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java (original)
+++ james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java Mon Jan 18 11:42:07 2016
@@ -26,6 +26,7 @@ import java.io.ByteArrayInputStream;
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -46,14 +47,18 @@ import org.apache.james.mailbox.inmemory
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.MockAuthenticator;
import org.apache.james.mailbox.store.StoreMailboxManager;
+import org.assertj.core.api.Condition;
+import org.assertj.core.data.MapEntry;
import org.assertj.core.groups.Tuple;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
+import com.jayway.jsonpath.JsonPath;
public class GetMessagesMethodTest {
@@ -235,4 +240,58 @@ public class GetMessagesMethodTest {
.asList()
.containsOnly(MessageProperty.id, MessageProperty.textBody);
}
+
+ @Test
+ public void processShouldReturnHeadersFieldWhenSpecificHeadersRequestedInPropertyList() throws MailboxException {
+ MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);
+ Date now = new Date();
+ ByteArrayInputStream message1Content = new ByteArrayInputStream(("From: user@domain.tld\r\n"
+ + "header1: Header1Content\r\n"
+ + "HEADer2: Header2Content\r\n"
+ + "Subject: message 1 subject\r\n\r\nmy message").getBytes(Charsets.UTF_8));
+ long message1Uid = inbox.appendMessage(message1Content, now, session, false, null);
+
+ GetMessagesRequest request = GetMessagesRequest.builder()
+ .ids(new MessageId(ROBERT, inboxPath, message1Uid))
+ .properties(MessageProperty.valueOf("headers.from"), MessageProperty.valueOf("headers.heADER2"))
+ .build();
+
+ GetMessagesMethod<InMemoryId> testee = new GetMessagesMethod<>(mailboxSessionMapperFactory, mailboxSessionMapperFactory);
+ List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
+
+ assertThat(result)
+ .hasSize(1)
+ .extracting(JmapResponse::getProperties)
+ .flatExtracting(Optional::get)
+ .asList()
+ .containsOnly(MessageProperty.id, MessageProperty.headers);
+ }
+
+ @Test
+ public void processShouldReturnAPreconfiguredObjectMapperFilteringHeaders() throws Exception {
+ MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);
+ Date now = new Date();
+ ByteArrayInputStream message1Content = new ByteArrayInputStream(("From: user@domain.tld\r\n"
+ + "header1: Header1Content\r\n"
+ + "HEADer2: Header2Content\r\n"
+ + "Subject: message 1 subject\r\n\r\nmy message").getBytes(Charsets.UTF_8));
+ long message1Uid = inbox.appendMessage(message1Content, now, session, false, null);
+
+ GetMessagesRequest request = GetMessagesRequest.builder()
+ .ids(new MessageId(ROBERT, inboxPath, message1Uid))
+ .properties(MessageProperty.valueOf("headers.from"), MessageProperty.valueOf("headers.heADER2"))
+ .build();
+
+ GetMessagesMethod<InMemoryId> testee = new GetMessagesMethod<>(mailboxSessionMapperFactory, mailboxSessionMapperFactory);
+ List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
+
+ assertThat(result)
+ .hasSize(1)
+ .extracting(JmapResponse::getFilterProvider)
+ .are(new Condition<>(Optional::isPresent, "present"));
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.setFilterProvider(result.get(0).getFilterProvider().get());
+ String response = objectMapper.writer().writeValueAsString(result.get(0));
+ assertThat(JsonPath.parse(response).<Map<String, String>>read("$.response.list[0].headers")).containsOnly(MapEntry.entry("from", "user@domain.tld"), MapEntry.entry("header2", "Header2Content"));
+ }
}
Added: james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessagePropertyTest.java
URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessagePropertyTest.java?rev=1725240&view=auto
==============================================================================
--- james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessagePropertyTest.java (added)
+++ james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessagePropertyTest.java Mon Jan 18 11:42:07 2016
@@ -0,0 +1,95 @@
+/****************************************************************
+ * 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.jmap.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+public class MessagePropertyTest {
+
+ @Test(expected=NullPointerException.class)
+ public void valueOfShouldThrowWhenNull() {
+ MessageProperty.valueOf(null);
+ }
+
+ @Test
+ public void valueOfThenAsFieldNameShouldReturnLowerCasedProperty() {
+ assertThat(MessageProperty.valueOf("ProP").asFieldName()).isEqualTo("prop");
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void headerValueOfShouldThrowWhenNull() {
+ MessageProperty.headerValueOf(null);
+ }
+
+ @Test
+ public void headerValueOfShouldReturnPrefixedProperty() {
+ assertThat(MessageProperty.headerValueOf("Prop").asFieldName()).isEqualTo("headers.prop");
+ }
+
+ @Test
+ public void isHeaderPropertyShouldReturnFalseWhenNotPrefixed() {
+ assertThat(MessageProperty.valueOf("prop").isHeaderProperty()).isFalse();
+ }
+
+ @Test
+ public void isHeaderPropertyShouldReturnFalseWhenPrefixedBySomethingElse() {
+ assertThat(MessageProperty.valueOf("somethingelse.prop").isHeaderProperty()).isFalse();
+ }
+
+ @Test
+ public void isHeaderPropertyShouldReturnTrueWhenPrefixedByHeaders() {
+ assertThat(MessageProperty.valueOf("headers.prop").isHeaderProperty()).isTrue();
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void selectHeadersPropertiesShouldThrowWhenNull() {
+ MessageProperty.selectHeadersProperties(null);
+ }
+
+ @Test
+ public void selectHeadersPropertiesShouldReturnOnlyHeadersProperties() {
+ Set<MessageProperty> properties = ImmutableSet.of(
+ MessageProperty.from,
+ MessageProperty.valueOf("headers.prop"),
+ MessageProperty.valueOf("headers.prop2"),
+ MessageProperty.valueOf("prop"));
+ assertThat(MessageProperty.selectHeadersProperties(properties)).containsOnly(MessageProperty.headerValueOf("prop"), MessageProperty.headerValueOf("prop2"));
+ }
+
+ @Test
+ public void equalsShouldBeTrueWhenIdenticalProperties() {
+ assertThat(MessageProperty.valueOf("prop")).isEqualTo(MessageProperty.valueOf("prop"));
+ }
+
+ @Test
+ public void equalsShouldBeFalseWhenDifferentProperties() {
+ assertThat(MessageProperty.valueOf("prop")).isNotEqualTo(MessageProperty.valueOf("other"));
+ }
+
+ @Test
+ public void equalsShouldBeTrueWhenDifferentCaseProperties() {
+ assertThat(MessageProperty.valueOf("prOP")).isEqualTo(MessageProperty.valueOf("PRop"));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org