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/07/01 15:30:35 UTC
[1/4] james-project git commit: JAMES-1777 Retrieve attachment name
in GetMessages JMAP method
Repository: james-project
Updated Branches:
refs/heads/master bc5afa0c8 -> b6e967de7
JAMES-1777 Retrieve attachment name in GetMessages JMAP method
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/b6e967de
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/b6e967de
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/b6e967de
Branch: refs/heads/master
Commit: b6e967de70012b32186d5d9120274453dc5afa3c
Parents: 8b7cdb2
Author: Antoine Duprat <ad...@linagora.com>
Authored: Fri Jun 24 08:50:03 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 1 16:32:41 2016 +0200
----------------------------------------------------------------------
.../src/main/java/org/apache/james/jmap/model/MessageFactory.java | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/b6e967de/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
index 8a5a277..b31f403 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
@@ -160,6 +160,7 @@ public class MessageFactory {
return Attachment.builder()
.blobId(attachment.getAttachmentId().getId())
.type(attachment.getType())
+ .name(attachment.getName().orNull())
.size(attachment.getSize())
.build();
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[3/4] james-project git commit: JAMES-1777 Parse attachment file name
Posted by ad...@apache.org.
JAMES-1777 Parse attachment file name
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/8b7cdb2a
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8b7cdb2a
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8b7cdb2a
Branch: refs/heads/master
Commit: 8b7cdb2acac03a85525e8cb5208579b4ab2f7e92
Parents: 9d0b3b4
Author: Antoine Duprat <ad...@linagora.com>
Authored: Thu Jun 23 22:17:09 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 1 16:32:41 2016 +0200
----------------------------------------------------------------------
.../store/mail/model/impl/MessageParser.java | 56 ++++++++++++--------
.../AbstractMailboxManagerAttachmentTest.java | 14 +++++
.../mail/model/impl/MessageParserTest.java | 19 +++++++
.../resources/eml/oneAttachmentWithoutName.eml | 38 +++++++++++++
4 files changed, 105 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/8b7cdb2a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
index be342d8..56099ff 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
@@ -31,21 +31,19 @@ import org.apache.james.mime4j.dom.Entity;
import org.apache.james.mime4j.dom.MessageWriter;
import org.apache.james.mime4j.dom.Multipart;
import org.apache.james.mime4j.dom.field.ContentDispositionField;
+import org.apache.james.mime4j.dom.field.ContentTypeField;
import org.apache.james.mime4j.message.DefaultMessageBuilder;
import org.apache.james.mime4j.message.DefaultMessageWriter;
import org.apache.james.mime4j.stream.Field;
+import com.google.common.base.Function;
import com.google.common.base.Optional;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
public class MessageParser {
private static final String CONTENT_TYPE = "Content-Type";
private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
- private static final String HEADER_SEPARATOR = ";";
public List<Attachment> retrieveAttachments(InputStream fullContent) throws MimeException, IOException {
Body body = new DefaultMessageBuilder()
@@ -67,38 +65,52 @@ public class MessageParser {
MessageWriter messageWriter = new DefaultMessageWriter();
for (Entity entity : multipart.getBodyParts()) {
if (isAttachment(entity)) {
- Optional<String> contentType = contentType(entity.getHeader().getField(CONTENT_TYPE));
- attachments.add(createAttachment(messageWriter, entity.getBody(), contentType.or(DEFAULT_CONTENT_TYPE)));
+ Optional<ContentTypeField> contentTypeField = contentTypeField(entity.getHeader().getField(CONTENT_TYPE));
+ Optional<String> contentType = contentType(contentTypeField);
+ Optional<String> name = name(contentTypeField);
+
+ attachments.add(Attachment.builder()
+ .bytes(getBytes(messageWriter, entity.getBody()))
+ .type(contentType.or(DEFAULT_CONTENT_TYPE))
+ .name(name)
+ .build());
}
}
return attachments.build();
}
- private Optional<String> contentType(Field contentType) {
- if (contentType == null) {
- return Optional.absent();
- }
- String body = contentType.getBody();
- if (Strings.isNullOrEmpty(body)) {
+ private Optional<String> contentType(Optional<ContentTypeField> contentTypeField) {
+ return contentTypeField.transform(new Function<ContentTypeField, Optional<String>>() {
+ @Override
+ public Optional<String> apply(ContentTypeField field) {
+ return Optional.fromNullable(field.getMimeType());
+ }
+ }).or(Optional.<String> absent());
+ }
+
+ private Optional<String> name(Optional<ContentTypeField> contentTypeField) {
+ return contentTypeField.transform(new Function<ContentTypeField, Optional<String>>() {
+ @Override
+ public Optional<String> apply(ContentTypeField field) {
+ return Optional.fromNullable(field.getParameter("name"));
+ }
+ }).or(Optional.<String> absent());
+ }
+
+ private Optional<ContentTypeField> contentTypeField(Field contentType) {
+ if (contentType == null || !(contentType instanceof ContentTypeField)) {
return Optional.absent();
}
- if (body.contains(HEADER_SEPARATOR)) {
- return Optional.of(Iterables.get(Splitter.on(HEADER_SEPARATOR).split(body), 0));
- }
- return Optional.of(body);
+ return Optional.of((ContentTypeField) contentType);
}
private boolean isAttachment(Entity part) {
return ContentDispositionField.DISPOSITION_TYPE_ATTACHMENT.equalsIgnoreCase(part.getDispositionType());
}
- private Attachment createAttachment(MessageWriter messageWriter, Body body, String contentType) throws IOException {
+ private byte[] getBytes(MessageWriter messageWriter, Body body) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
messageWriter.writeBody(body, out);
- byte[] bytes = out.toByteArray();
- return Attachment.builder()
- .bytes(bytes)
- .type(contentType)
- .build();
+ return out.toByteArray();
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/8b7cdb2a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
index bde8984..5f14fda 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
@@ -48,6 +48,8 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import com.google.common.base.Optional;
+
public abstract class AbstractMailboxManagerAttachmentTest {
private static final String USERNAME = "user@domain.tld";
private static final Date SUN_SEP_9TH_2001 = new Date(1000000000000L);
@@ -108,6 +110,18 @@ public abstract class AbstractMailboxManagerAttachmentTest {
}
@Test
+ public void appendMessageShouldStoreAttachmentNameWhenMailWithOneAttachment() throws Exception {
+ InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml");
+ inboxMessageManager.appendMessage(mailInputStream, SUN_SEP_9TH_2001, mailboxSession, true, new Flags(Flags.Flag.RECENT));
+
+ Optional<String> expectedName = Optional.of("exploits_of_a_mom.png");
+
+ Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
+ List<AttachmentId> attachmentsIds = messages.next().getAttachmentsIds();
+ assertThat(attachmentMapper.getAttachment(attachmentsIds.get(0)).getName()).isEqualTo(expectedName);
+ }
+
+ @Test
public void appendMessageShouldStoreARetrievableAttachmentWhenMailWithOneAttachment() throws Exception {
InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml");
inboxMessageManager.appendMessage(mailInputStream, SUN_SEP_9TH_2001, mailboxSession, true, new Flags(Flags.Flag.RECENT));
http://git-wip-us.apache.org/repos/asf/james-project/blob/8b7cdb2a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
index ab8b88b..ca6847d 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
@@ -27,6 +27,8 @@ import org.apache.james.mailbox.store.mail.model.Attachment;
import org.junit.Before;
import org.junit.Test;
+import com.google.common.base.Optional;
+
public class MessageParserTest {
private MessageParser testee;
@@ -51,6 +53,23 @@ public class MessageParserTest {
}
@Test
+ public void getAttachmentsShouldRetrieveAttachmentNameWhenOne() throws Exception {
+ List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
+
+ assertThat(attachments).hasSize(1);
+ Optional<String> expectedName = Optional.of("exploits_of_a_mom.png");
+ assertThat(attachments.get(0).getName()).isEqualTo(expectedName);
+ }
+
+ @Test
+ public void getAttachmentsShouldRetrieveEmptyNameWhenNone() throws Exception {
+ List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithoutName.eml"));
+
+ assertThat(attachments).hasSize(1);
+ assertThat(attachments.get(0).getName()).isEqualTo(Optional.absent());
+ }
+
+ @Test
public void getAttachmentsShouldNotFailWhenContentTypeIsNotHere() throws Exception {
List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithoutContentType.eml"));
http://git-wip-us.apache.org/repos/asf/james-project/blob/8b7cdb2a/mailbox/store/src/test/resources/eml/oneAttachmentWithoutName.eml
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/resources/eml/oneAttachmentWithoutName.eml b/mailbox/store/src/test/resources/eml/oneAttachmentWithoutName.eml
new file mode 100644
index 0000000..b5a9aa2
--- /dev/null
+++ b/mailbox/store/src/test/resources/eml/oneAttachmentWithoutName.eml
@@ -0,0 +1,38 @@
+Mail content:
+To: "=?utf-8?B?UmFuaSBBc3NhZg==?=" <ra...@jri.obm.lng.org>
+Subject: =?utf-8?B?VHIuIDogUGhvdG9zICE=?=
+Importance: Normal
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="----=_Part_0_1330682067197"
+
+------=_Part_0_1330682067197
+Content-Type: multipart/alternative;
+ boundary="----=_Part_2_1330682067197"
+
+------=_Part_2_1330682067197
+Content-Type: text/plain;
+ charset= utf-8
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+Content of part 1-1
+------=_Part_2_1330682067197
+Content-Type: text/html;
+ charset= utf-8
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+<b>Content of part 1-2</b>
+------=_Part_2_1330682067197--
+
+------=_Part_0_1330682067197
+Content-Type: application/octet-stream;
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+ filename="gimp.png"
+
+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
+
+------=_Part_0_1330682067197--
+
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[2/4] james-project git commit: JAMES-1777 Add name in Attachment
table
Posted by ad...@apache.org.
JAMES-1777 Add name in Attachment table
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/9d0b3b41
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/9d0b3b41
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/9d0b3b41
Branch: refs/heads/master
Commit: 9d0b3b41954f08831e9feab6a0028adda1e98bb6
Parents: f643c18
Author: Antoine Duprat <ad...@linagora.com>
Authored: Thu Jun 23 21:47:28 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 1 16:32:41 2016 +0200
----------------------------------------------------------------------
.../mail/CassandraAttachmentMapper.java | 5 +-
.../modules/CassandraAttachmentModule.java | 1 +
.../table/CassandraAttachmentTable.java | 3 +-
.../mailbox/store/mail/model/Attachment.java | 47 +++++++++++------
.../store/mail/model/impl/MessageParser.java | 5 +-
.../store/mail/model/AttachmentMapperTest.java | 18 +++++--
.../store/mail/model/AttachmentTest.java | 54 ++++++++++++++------
.../james/jmap/model/MailboxMessageTest.java | 1 -
8 files changed, 94 insertions(+), 40 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/9d0b3b41/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
index c36d824..fcbfec8 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
@@ -24,6 +24,7 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.FIELDS;
import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.ID;
+import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.NAME;
import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.PAYLOAD;
import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.SIZE;
import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.TABLE_NAME;
@@ -46,6 +47,7 @@ import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.github.fge.lambdas.Throwing;
import com.github.fge.lambdas.ThrownByLambdaException;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
public class CassandraAttachmentMapper implements AttachmentMapper {
@@ -82,7 +84,7 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
.attachmentId(AttachmentId.from(row.getString(ID)))
.bytes(row.getBytes(PAYLOAD).array())
.type(row.getString(TYPE))
- .size(row.getLong(SIZE))
+ .name(Optional.fromNullable(row.getString(NAME)))
.build();
}
@@ -101,6 +103,7 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
.value(ID, attachment.getAttachmentId().getId())
.value(PAYLOAD, ByteBuffer.wrap(IOUtils.toByteArray(attachment.getStream())))
.value(TYPE, attachment.getType())
+ .value(NAME, attachment.getName().orNull())
.value(SIZE, attachment.getSize())
);
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/9d0b3b41/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java
index 0108161..b26fe71 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java
@@ -48,6 +48,7 @@ public class CassandraAttachmentModule implements CassandraModule {
.addPartitionKey(CassandraAttachmentTable.ID, text())
.addColumn(CassandraAttachmentTable.PAYLOAD, blob())
.addColumn(CassandraAttachmentTable.TYPE, text())
+ .addColumn(CassandraAttachmentTable.NAME, text())
.addColumn(CassandraAttachmentTable.SIZE, bigint())));
index = Collections.emptyList();
types = Collections.emptyList();
http://git-wip-us.apache.org/repos/asf/james-project/blob/9d0b3b41/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java
index a7115eb..17158d1 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java
@@ -25,7 +25,8 @@ public interface CassandraAttachmentTable {
String ID = "id";
String PAYLOAD = "payload";
String TYPE = "type";
+ String NAME = "name";
String SIZE = "size";
- String[] FIELDS = { ID, PAYLOAD, TYPE, SIZE };
+ String[] FIELDS = { ID, PAYLOAD, TYPE, NAME, SIZE };
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/9d0b3b41/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
index 5af2b28..6205647 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
@@ -35,23 +36,15 @@ public class Attachment {
return new Builder();
}
- public static Attachment from(byte[] bytes, String type) {
- return builder()
- .attachmentId(AttachmentId.forPayload(bytes))
- .bytes(bytes)
- .type(type)
- .size(bytes.length)
- .build();
- }
-
public static class Builder {
private AttachmentId attachmentId;
private byte[] bytes;
private String type;
- private Long size;
+ private Optional<String> name;
private Builder() {
+ name = Optional.absent();
}
public Builder attachmentId(AttachmentId attachmentId) {
@@ -72,29 +65,43 @@ public class Attachment {
return this;
}
- public Builder size(long size) {
- this.size = size;
+ public Builder name(Optional<String> name) {
+ Preconditions.checkArgument(name != null);
+ this.name = name;
return this;
}
public Attachment build() {
- Preconditions.checkState(attachmentId != null, "'attachmentId' is mandatory");
Preconditions.checkState(bytes != null, "'bytes' is mandatory");
+ AttachmentId builtAttachmentId = attachmentId();
+ Preconditions.checkState(builtAttachmentId != null, "'attachmentId' is mandatory");
Preconditions.checkState(type != null, "'type' is mandatory");
- Preconditions.checkState(size != null, "'size' is mandatory");
- return new Attachment(bytes, attachmentId, type, size);
+ return new Attachment(bytes, builtAttachmentId, type, name, size());
+ }
+
+ private AttachmentId attachmentId() {
+ if (attachmentId != null) {
+ return attachmentId;
+ }
+ return AttachmentId.forPayload(bytes);
+ }
+
+ private long size() {
+ return bytes.length;
}
}
private final byte[] bytes;
private final AttachmentId attachmentId;
private final String type;
+ private final Optional<String> name;
private final long size;
- private Attachment(byte[] bytes, AttachmentId attachmentId, String type, long size) {
+ private Attachment(byte[] bytes, AttachmentId attachmentId, String type, Optional<String> name, long size) {
this.bytes = bytes;
this.attachmentId = attachmentId;
this.type = type;
+ this.name = name;
this.size = size;
}
@@ -106,6 +113,10 @@ public class Attachment {
return type;
}
+ public Optional<String> getName() {
+ return name;
+ }
+
public long getSize() {
return size;
}
@@ -121,6 +132,7 @@ public class Attachment {
return Objects.equal(attachmentId, other.attachmentId)
&& Arrays.equals(bytes, other.bytes)
&& Objects.equal(type, other.type)
+ && Objects.equal(name, other.name)
&& Objects.equal(size, other.size);
}
return false;
@@ -128,7 +140,7 @@ public class Attachment {
@Override
public int hashCode() {
- return Objects.hashCode(attachmentId, bytes, type, size);
+ return Objects.hashCode(attachmentId, bytes, type, name, size);
}
@Override
@@ -138,6 +150,7 @@ public class Attachment {
.add("attachmentId", attachmentId)
.add("bytes", bytes)
.add("type", type)
+ .add("name", name)
.add("size", size)
.toString();
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/9d0b3b41/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
index c784474..be342d8 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
@@ -96,6 +96,9 @@ public class MessageParser {
ByteArrayOutputStream out = new ByteArrayOutputStream();
messageWriter.writeBody(body, out);
byte[] bytes = out.toByteArray();
- return Attachment.from(bytes, contentType);
+ return Attachment.builder()
+ .bytes(bytes)
+ .type(contentType)
+ .build();
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/9d0b3b41/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java
index 0fbfe1a..39b26e6 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java
@@ -31,6 +31,7 @@ import org.xenei.junit.contract.Contract;
import org.xenei.junit.contract.ContractTest;
import org.xenei.junit.contract.IProducer;
+import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
@Contract(MapperProvider.class)
@@ -62,13 +63,16 @@ public class AttachmentMapperTest<T extends MapperProvider> {
@ContractTest
public void getAttachmentShouldThrowWhenNonReferencedAttachmentId() throws Exception {
expected.expect(AttachmentNotFoundException.class);
- attachmentMapper.getAttachment(AttachmentId.forPayload("unknown".getBytes()));
+ attachmentMapper.getAttachment(AttachmentId.forPayload("unknown".getBytes(Charsets.UTF_8)));
}
@ContractTest
public void getAttachmentShouldReturnTheAttachmentWhenReferenced() throws Exception {
//Given
- Attachment expected = Attachment.from("payload".getBytes(), "content");
+ Attachment expected = Attachment.builder()
+ .bytes("payload".getBytes(Charsets.UTF_8))
+ .type("content")
+ .build();
AttachmentId attachmentId = expected.getAttachmentId();
attachmentMapper.storeAttachment(expected);
//When
@@ -80,8 +84,14 @@ public class AttachmentMapperTest<T extends MapperProvider> {
@ContractTest
public void getAttachmentShouldReturnTheAttachmentsWhenMultipleStored() throws Exception {
//Given
- Attachment expected1 = Attachment.from("payload1".getBytes(), "content1");
- Attachment expected2 = Attachment.from("payload2".getBytes(), "content2");
+ Attachment expected1 = Attachment.builder()
+ .bytes("payload1".getBytes(Charsets.UTF_8))
+ .type("content1")
+ .build();
+ Attachment expected2 = Attachment.builder()
+ .bytes("payload2".getBytes(Charsets.UTF_8))
+ .type("content2")
+ .build();
AttachmentId attachmentId1 = expected1.getAttachmentId();
AttachmentId attachmentId2 = expected2.getAttachmentId();
//When
http://git-wip-us.apache.org/repos/asf/james-project/blob/9d0b3b41/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
index 5e96c7d..f3505f4 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
@@ -27,12 +27,17 @@ import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
+import com.google.common.base.Optional;
+
public class AttachmentTest {
@Test
public void streamShouldBeConsumedOneTime() throws Exception {
String input = "mystream";
- Attachment attachment = Attachment.from(input.getBytes(), "content");
+ Attachment attachment = Attachment.builder()
+ .bytes(input.getBytes())
+ .type("content")
+ .build();
InputStream stream = attachment.getStream();
assertThat(stream).isNotNull();
@@ -42,7 +47,10 @@ public class AttachmentTest {
@Test
public void streamShouldBeConsumedMoreThanOneTime() throws Exception {
String input = "mystream";
- Attachment attachment = Attachment.from(input.getBytes(), "content");
+ Attachment attachment = Attachment.builder()
+ .bytes(input.getBytes())
+ .type("content")
+ .build();
attachment.getStream();
InputStream stream = attachment.getStream();
@@ -74,6 +82,12 @@ public class AttachmentTest {
.type("");
}
+ @Test (expected = IllegalArgumentException.class)
+ public void builderShouldThrowWhenNameIsNull() {
+ Attachment.builder()
+ .name(null);
+ }
+
@Test (expected = IllegalStateException.class)
public void buildShouldThrowWhenAttachmentIdIsNotProvided() {
Attachment.builder().build();
@@ -94,29 +108,39 @@ public class AttachmentTest {
.build();
}
- @Test (expected = IllegalStateException.class)
- public void buildShouldThrowWhenSizeIsNotProvided() {
- Attachment.builder()
- .attachmentId(AttachmentId.forPayload("mystream".getBytes()))
- .bytes("mystream".getBytes())
- .type("content")
- .build();
- }
-
@Test
- public void fromShouldSetTheAttachmentId() throws Exception {
+ public void buildShouldSetTheAttachmentId() throws Exception {
byte[] bytes = "mystream".getBytes();
- Attachment attachment = Attachment.from(bytes, "content");
+ Attachment attachment = Attachment.builder()
+ .bytes(bytes)
+ .type("content")
+ .build();
AttachmentId expected = AttachmentId.forPayload(bytes);
assertThat(attachment.getAttachmentId()).isEqualTo(expected);
}
@Test
- public void fromShouldSetTheSize() throws Exception {
+ public void buildShouldSetTheSize() throws Exception {
String input = "mystream";
- Attachment attachment = Attachment.from(input.getBytes(), "content");
+ Attachment attachment = Attachment.builder()
+ .bytes(input.getBytes())
+ .type("content")
+ .build();
assertThat(attachment.getSize()).isEqualTo(input.getBytes().length);
}
+
+ @Test
+ public void buildShouldSetTheName() throws Exception {
+ String input = "mystream";
+ Optional<String> expectedName = Optional.of("myName");
+ Attachment attachment = Attachment.builder()
+ .bytes(input.getBytes())
+ .type("content")
+ .name(expectedName)
+ .build();
+
+ assertThat(attachment.getName()).isEqualTo(expectedName);
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/9d0b3b41/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
index f356460..eae0c49 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
@@ -422,7 +422,6 @@ public class MailboxMessageTest {
.attachmentId(AttachmentId.from(blodId))
.bytes(payload.getBytes())
.type(type)
- .size(payload.length())
.build()),
x -> MessageId.of("user|box|" + x));
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[4/4] james-project git commit: JAMES-1777 Add name variable in
download endpoint
Posted by ad...@apache.org.
JAMES-1777 Add name variable in download endpoint
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/f643c184
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/f643c184
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/f643c184
Branch: refs/heads/master
Commit: f643c184bfba52c003d70265063063aec5995b9d
Parents: bc5afa0
Author: Antoine Duprat <ad...@linagora.com>
Authored: Thu Jun 23 14:26:01 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 1 16:32:41 2016 +0200
----------------------------------------------------------------------
.../integration/cucumber/DownloadStepdefs.java | 30 +++++--
.../test/resources/cucumber/DownloadGet.feature | 6 ++
.../org/apache/james/jmap/DownloadServlet.java | 35 ++++----
.../apache/james/jmap/utils/DownloadPath.java | 65 +++++++++++++++
.../apache/james/jmap/DownloadServletTest.java | 13 +--
.../james/jmap/utils/DownloadPathTest.java | 84 ++++++++++++++++++++
6 files changed, 202 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/f643c184/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java
index 74b2d49..e675d10 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java
@@ -38,6 +38,7 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.response.Response;
+import com.jayway.restassured.response.ValidatableResponse;
import com.jayway.restassured.specification.RequestSpecification;
import cucumber.api.java.en.Given;
@@ -53,6 +54,7 @@ public class DownloadStepdefs {
private Response response;
private Multimap<String, String> attachmentsByMessageId;
private Map<String, String> blobIdByAttachmentId;
+ private ValidatableResponse validatableResponse;
@Inject
private DownloadStepdefs(MainStepdefs mainStepdefs, UserStepdefs userStepdefs) {
@@ -125,33 +127,44 @@ public class DownloadStepdefs {
.post("/download/" + blobId);
}
+ @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with \"([^\"]*)\" name$")
+ public void downloadsWithName(String username, String attachmentId, String name) {
+ String blobId = blobIdByAttachmentId.get(attachmentId);
+ AccessToken accessToken = userStepdefs.tokenByUser.get(username);
+ RequestSpecification with = with();
+ if (accessToken != null) {
+ with.header("Authorization", accessToken.serialize());
+ }
+ response = with.get("/download/" + blobId + "/" + name);
+ }
+
@Then("^the user should be authorized$")
- public void httpStatusDifferentFromUnauthorized() throws Exception {
+ public void httpStatusDifferentFromUnauthorized() {
response.then()
.statusCode(not(401));
}
@Then("^the user should not be authorized$")
- public void httpUnauthorizedStatus() throws Exception {
+ public void httpUnauthorizedStatus() {
response.then()
.statusCode(401);
}
@Then("^the user should receive a bad request response$")
- public void httpBadRequestStatus() throws Throwable {
+ public void httpBadRequestStatus() {
response.then()
.statusCode(400);
}
@Then("^the user should receive that attachment$")
- public void httpOkStatusAndExpectedContent() throws Throwable {
- response.then()
+ public void httpOkStatusAndExpectedContent() {
+ validatableResponse = response.then()
.statusCode(200)
.content(notNullValue());
}
@Then("^the user should receive a not found response$")
- public void httpNotFoundStatus() throws Throwable {
+ public void httpNotFoundStatus() {
response.then()
.statusCode(404);
}
@@ -163,4 +176,9 @@ public class DownloadStepdefs {
.contentType(ContentType.TEXT)
.content(notNullValue());
}
+
+ @Then("^the attachment is named \"([^\"]*)\"$")
+ public void assertContentDisposition(String name) {
+ validatableResponse.header("Content-Disposition", name);
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/f643c184/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature
index 7b02ee8..bf3d21a 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature
@@ -15,3 +15,9 @@ Feature: Download GET
Scenario: Getting an attachment with an unknown blobId
When "username@domain.tld" downloads "123"
Then the user should receive a not found response
+
+ Scenario: Getting an attachment previously stored with a desired name
+ Given "username@domain.tld" mailbox "inbox" contains a message "1" with an attachment "2"
+ When "username@domain.tld" downloads "2" with "myFileName.txt" name
+ Then the user should receive that attachment
+ And the attachment is named "myFileName.txt"
http://git-wip-us.apache.org/repos/asf/james-project/blob/f643c184/server/protocols/jmap/src/main/java/org/apache/james/jmap/DownloadServlet.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/DownloadServlet.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/DownloadServlet.java
index ccd8d86..49d0c79 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/DownloadServlet.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/DownloadServlet.java
@@ -24,6 +24,7 @@ import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import java.io.IOException;
+import java.util.Optional;
import javax.inject.Inject;
import javax.servlet.ServletException;
@@ -33,6 +34,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.james.jmap.api.SimpleTokenFactory;
+import org.apache.james.jmap.utils.DownloadPath;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.exception.AttachmentNotFoundException;
import org.apache.james.mailbox.exception.MailboxException;
@@ -44,11 +46,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Strings;
public class DownloadServlet extends HttpServlet {
- private static final String ROOT_URL = "/";
private static final Logger LOGGER = LoggerFactory.getLogger(DownloadServlet.class);
private static final String TEXT_PLAIN_CONTENT_TYPE = "text/plain";
@@ -64,14 +64,16 @@ public class DownloadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
String pathInfo = req.getPathInfo();
- if (Strings.isNullOrEmpty(pathInfo) || pathInfo.equals(ROOT_URL)) {
+ try {
+ respondAttachmentAccessToken(getMailboxSession(req), DownloadPath.from(pathInfo), resp);
+ } catch (IllegalArgumentException e) {
+ LOGGER.error(String.format("Error while generating attachment access token '%s'", pathInfo), e);
resp.setStatus(SC_BAD_REQUEST);
- } else {
- respondAttachmentAccessToken(getMailboxSession(req), blobIdFrom(pathInfo), resp);
}
}
- private void respondAttachmentAccessToken(MailboxSession mailboxSession, String blobId, HttpServletResponse resp) {
+ private void respondAttachmentAccessToken(MailboxSession mailboxSession, DownloadPath downloadPath, HttpServletResponse resp) {
+ String blobId = downloadPath.getBlobId();
try {
if (! attachmentExists(mailboxSession, blobId)) {
resp.setStatus(SC_NOT_FOUND);
@@ -99,22 +101,23 @@ public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
String pathInfo = req.getPathInfo();
- if (Strings.isNullOrEmpty(pathInfo) || pathInfo.equals(ROOT_URL)) {
+ try {
+ download(getMailboxSession(req), DownloadPath.from(pathInfo), resp);
+ } catch (IllegalArgumentException e) {
+ LOGGER.error(String.format("Error while downloading '%s'", pathInfo), e);
resp.setStatus(SC_BAD_REQUEST);
- } else {
- download(getMailboxSession(req), blobIdFrom(pathInfo), resp);
}
}
- @VisibleForTesting String blobIdFrom(String pathInfo) {
- return pathInfo.substring(1);
- }
-
- @VisibleForTesting void download(MailboxSession mailboxSession, String blobId, HttpServletResponse resp) {
+ @VisibleForTesting void download(MailboxSession mailboxSession, DownloadPath downloadPath, HttpServletResponse resp) {
+ String blobId = downloadPath.getBlobId();
try {
+ addContentDispositionHeader(downloadPath.getName(), resp);
+
AttachmentMapper attachmentMapper = mailboxSessionMapperFactory.createAttachmentMapper(mailboxSession);
Attachment attachment = attachmentMapper.getAttachment(AttachmentId.from(blobId));
IOUtils.copy(attachment.getStream(), resp.getOutputStream());
+
resp.setStatus(SC_OK);
} catch (AttachmentNotFoundException e) {
LOGGER.info(String.format("Attachment '%s' not found", blobId), e);
@@ -125,6 +128,10 @@ public class DownloadServlet extends HttpServlet {
}
}
+ private void addContentDispositionHeader(Optional<String> optionalName, HttpServletResponse resp) {
+ optionalName.ifPresent(name -> resp.addHeader("Content-Disposition", name));
+ }
+
private MailboxSession getMailboxSession(HttpServletRequest req) {
return (MailboxSession) req.getAttribute(AuthenticationFilter.MAILBOX_SESSION);
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/f643c184/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/DownloadPath.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/DownloadPath.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/DownloadPath.java
new file mode 100644
index 0000000..3755e8a
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/DownloadPath.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.jmap.utils;
+
+import java.util.List;
+import java.util.Optional;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+
+public class DownloadPath {
+
+ public static DownloadPath from(String path) {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(path), "'path' is mandatory");
+
+ // path = /blobId/name
+ // idx = 0 1 2
+ List<String> pathVariables = Splitter.on('/').splitToList(path);
+ Preconditions.checkArgument(pathVariables.size() >= 1 && pathVariables.size() <= 3, "'blobId' is mandatory");
+
+ String blobId = Iterables.get(pathVariables, 1, null);
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(blobId), "'blobId' is mandatory");
+
+ return new DownloadPath(blobId, name(pathVariables));
+ }
+
+ private static Optional<String> name(List<String> pathVariables) {
+ return Optional.ofNullable(Strings.emptyToNull(Iterables.get(pathVariables, 2, null)));
+ }
+
+ private final String blobId;
+ private final Optional<String> name;
+
+ private DownloadPath(String blobId, Optional<String> name) {
+ this.blobId = blobId;
+ this.name = name;
+ }
+
+ public String getBlobId() {
+ return blobId;
+ }
+
+ public Optional<String> getName() {
+ return name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/f643c184/server/protocols/jmap/src/test/java/org/apache/james/jmap/DownloadServletTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/DownloadServletTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/DownloadServletTest.java
index de9058b..79302b7 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/DownloadServletTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/DownloadServletTest.java
@@ -19,7 +19,6 @@
package org.apache.james.jmap;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,6 +26,7 @@ import static org.mockito.Mockito.when;
import javax.servlet.http.HttpServletResponse;
import org.apache.james.jmap.api.SimpleTokenFactory;
+import org.apache.james.jmap.utils.DownloadPath;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
@@ -35,14 +35,6 @@ import org.junit.Test;
public class DownloadServletTest {
@Test
- public void blobIdFromShouldSkipTheFirstCharacter() {
- MailboxSessionMapperFactory nullMailboxSessionMapperFactory = null;
- SimpleTokenFactory nullSimpleTokenFactory = null;
- String blobId = new DownloadServlet(nullMailboxSessionMapperFactory, nullSimpleTokenFactory).blobIdFrom("1234");
- assertThat(blobId).isEqualTo("234");
- }
-
- @Test
public void downloadMayFailWhenUnableToCreateAttachmentMapper() throws Exception {
MailboxSession mailboxSession = mock(MailboxSession.class);
MailboxSessionMapperFactory mailboxSessionMapperFactory = mock(MailboxSessionMapperFactory.class);
@@ -52,9 +44,8 @@ public class DownloadServletTest {
DownloadServlet testee = new DownloadServlet(mailboxSessionMapperFactory, nullSimpleTokenFactory);
- String blobId = null;
HttpServletResponse resp = mock(HttpServletResponse.class);
- testee.download(mailboxSession, blobId, resp);
+ testee.download(mailboxSession, DownloadPath.from("/blobId"), resp);
verify(resp).setStatus(500);
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/f643c184/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/DownloadPathTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/DownloadPathTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/DownloadPathTest.java
new file mode 100644
index 0000000..53eff13
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/DownloadPathTest.java
@@ -0,0 +1,84 @@
+/****************************************************************
+ * 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.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.Test;
+
+public class DownloadPathTest {
+
+ @Test
+ public void fromShouldThrowWhenPathIsNull() {
+ assertThatThrownBy(()-> DownloadPath.from(null)).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void fromShouldThrowWhenPathIsEmpty() {
+ assertThatThrownBy(()-> DownloadPath.from("")).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void fromShouldThrowWhenNoBlobId() {
+ assertThatThrownBy(()-> DownloadPath.from("/")).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void fromShouldThrowWhenBlobIdIsEmpty() {
+ assertThatThrownBy(()-> DownloadPath.from("//")).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void fromShouldParseWhenBlobId() {
+ String expectedBlobId = "123456789";
+ DownloadPath downloadPath = DownloadPath.from("/" + expectedBlobId);
+ assertThat(downloadPath.getBlobId()).isEqualTo(expectedBlobId);
+ }
+
+ @Test
+ public void nameShouldBeEmptyWhenNone() {
+ DownloadPath downloadPath = DownloadPath.from("/123456789");
+ assertThat(downloadPath.getName()).isEmpty();
+ }
+
+ @Test
+ public void nameShouldBeEmptyWhenNoneButSlash() {
+ DownloadPath downloadPath = DownloadPath.from("/123456789/");
+ assertThat(downloadPath.getName()).isEmpty();
+ }
+
+ @Test
+ public void nameShouldBePresentWhenGiven() {
+ String expectedName = "myName";
+ DownloadPath downloadPath = DownloadPath.from("/123456789/" + expectedName);
+ assertThat(downloadPath.getName()).hasValue(expectedName);
+ }
+
+ @Test
+ public void fromShouldThrowWhenExtraPathVariables() {
+ assertThatThrownBy(()-> DownloadPath.from("/123456789/myName/132/456/789")).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void fromShouldThrowWhenExtraPathSeparator() {
+ assertThatThrownBy(()-> DownloadPath.from("/123456789//myName")).isInstanceOf(IllegalArgumentException.class);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org