Skip to content

Commit

Permalink
[closes #30] allow downloading of message by it's id
Browse files Browse the repository at this point in the history
  • Loading branch information
jludvice committed Sep 1, 2017
1 parent c3636b8 commit 15185a6
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 24 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<sl4j.version>1.7.21</sl4j.version>
<log4j.version>1.2.17</log4j.version>

<java.isds.version>1.1.0</java.isds.version>
<java.isds.version>1.1.1</java.isds.version>
</properties>

<scm>
Expand Down
34 changes: 30 additions & 4 deletions src/main/docs/isds.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ for real BOM in Camel project but `camel-parent` can be used until then.
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-parent</artifactId>
<version>${camel.version</version>
<version>${camel.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down Expand Up @@ -55,21 +55,45 @@ isds:messages?options

[[ISDS-Operations]]
### Supported operations
Camel ISDS currently supports only `messages` operation for sending and receiving messages.

#### isds:messages
For sending and receiving messages.

#### isds:download
For downloading of specific isds message by it's id.

Important exchange headers
[width="100%", options="header"]
|=======================================================================
| Header | Default value | Description
| isdsId | null | download message with this ID
| isdsType | received | download message you received. You may also download message you "sent"
|=======================================================================


When downloading message by it's id with `isds:download`,
you might see this error:
-------------------------------------------------------
Nemohu stahnout prijatou zpravu. 1222:Zprava dosud nebyla oznacena jako dorucena, proto ji nelze cist.
-------------------------------------------------------
This is caused by security feature of ISDS.
According to this feature it's forbidden to download message which wasn't marked as delivered.
You may use option `isds:download?downloadListMessages=true` get around that.
Component will first call getListOfReceivedMessages API method to trigger "delivered event" and then it should work.

Operations planned for next releases are:

* `search` for searching of databoxes based on given query
* `download` for downloading of specific isds message by it's id
[[ISDS-ISDSEndpointOptions]]
### ISDSEndpoint Options




// endpoint options: START
The ISDS component supports 15 endpoint options which are listed below:
The ISDS component supports 16 endpoint options which are listed below:

[width="100%",cols="2s,1,1m,1m,5",options="header"]
|=======================================================================
Expand All @@ -87,6 +111,7 @@ The ISDS component supports 15 endpoint options which are listed below:
| exceptionHandler | consumer (advanced) | | ExceptionHandler | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this options is not in use. By default the consumer will deal with exceptions that will be logged at WARN/ERROR level and ignored.
| from | consumer (advanced) | 0L | Date | Download only messages received after this date. If using the URI the pattern expected is: code yyyy-MM-dd HH:mm:ss or code yyyy-MM-dd'T'HH:mm:ss.
| to | consumer (advanced) | Long.MAX_VALUE | Date | Download only messages received before this date. If using the URI the pattern expected is: code yyyy-MM-dd HH:mm:ss or code yyyy-MM-dd'T'HH:mm:ss.
| downloadListMessages | producer | false | boolean | First call getListOfReceivedMessages before downloading message by it's ID. See documentation of ISDS section 1.6.2.2 Novy Stav. User must login into ISDS in order to download messages. The only API method that causes user logged in event is getListOfReceivedMessages. ISDS may throw error number 1222 when downloading message if this option is set to false;
| exchangePattern | advanced | InOnly | ExchangePattern | Sets the default exchange pattern when creating an exchange
| synchronous | advanced | false | boolean | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported).
|=======================================================================
Expand All @@ -111,6 +136,7 @@ The ISDS component supports 15 endpoint options which are listed below:






[[ISDS-ISDSComponentOptions]]
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/github/czgov/isds/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class Constants {
public static final String MSG_ID = PREFIX + "Id";
public static final String MSG_FROM = PREFIX + "From";
public static final String MSG_TO = PREFIX + "To";
public static final String MSG_TYPE = PREFIX + "Type";

public static final String DEFAULT_ATTACHMENT_STORE = "camel-isds-attachment-store";
}
19 changes: 19 additions & 0 deletions src/main/java/com/github/czgov/isds/ISDSEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ public class ISDSEndpoint extends DefaultEndpoint {
@UriParam(defaultValue = "false")
private boolean realtime = false;

@UriParam(defaultValue = "false", label = "producer")
private boolean downloadListMessages = false;

private Authentication dataBoxAuth;
private DataBoxManager dataBoxManager;

Expand Down Expand Up @@ -242,4 +245,20 @@ public boolean isRealtime() {
public void setRealtime(boolean realtime) {
this.realtime = realtime;
}

public boolean isDownloadListMessages() {
return downloadListMessages;
}

/**
* First call getListOfReceivedMessages before downloading message by it's ID.
* See documentation of ISDS, section 1.6.2.2 Novy Stav.
* User must login into ISDS in order to download messages.
* The only API method that causes "user logged in event" is getListOfReceivedMessages.
* ISDS may throw error number 1222 when downloading message if this option is set to false;
* @param downloadListMessages
*/
public void setDownloadListMessages(boolean downloadListMessages) {
this.downloadListMessages = downloadListMessages;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.github.czgov.isds.internal;

import org.apache.camel.Exchange;
import org.apache.camel.util.ObjectHelper;

import com.github.czgov.isds.Constants;
import com.github.czgov.isds.ISDSEndpoint;
import com.github.czgov.isds.ISDSProducer;

import java.util.Date;

import cz.abclinuxu.datoveschranky.common.FileAttachmentStorer;
import cz.abclinuxu.datoveschranky.common.entities.MessageEnvelope;
import cz.abclinuxu.datoveschranky.common.entities.MessageType;

/**
* Created by jludvice on 19.7.17.
*/
public class ISDSDownloadProducer extends ISDSProducer {
public ISDSDownloadProducer(ISDSEndpoint endpoint) {
super(endpoint);
}

@Override
public void process(Exchange exchange) throws Exception {

final String id = exchange.getIn().getHeader(Constants.MSG_ID, String.class);
final MessageType type = exchange.getIn().getHeader(Constants.MSG_TYPE, "received", MessageType.class);

ObjectHelper.notNull(id, "Camel header " + Constants.MSG_ID);

System.out.printf("fetching %s message #%s\n", type, id);

MessageEnvelope env = new MessageEnvelope();
env.setMessageID(id);
env.setType(type);

if (MessageType.RECEIVED.equals(type) && endpoint.isDownloadListMessages()) {
// hack around isds policy which doesn't allow downloading of messages
// which arrived before user logged in (or called getListOfReceivedMessages API method
Date d = new Date();
log.info("Calling getListOfReceivedMessages before downloading message by id {}", id);
// don't care about result, just need ISDS to mark messages as delivered
endpoint.getDataBoxManager()
.getDataBoxMessagesService()
.getListOfReceivedMessages(d, d, null, 1, 1);
}

if (MessageType.SENT.equals(type) || endpoint.isZfo()) {
ISDSMessagesConsumer.downloadZFO(exchange, env, endpoint);
} else {
ISDSMessagesConsumer.downloadMessage(exchange, env, endpoint,
new FileAttachmentStorer(endpoint.getAttachmentStore().toFile()));
}
log.info("probably need TODO :)");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import cz.abclinuxu.datoveschranky.common.entities.Message;
import cz.abclinuxu.datoveschranky.common.entities.MessageEnvelope;
import cz.abclinuxu.datoveschranky.common.entities.content.FileContent;
import cz.abclinuxu.datoveschranky.common.interfaces.AttachmentStorer;

/**
* Created by jludvice on 17.2.17.
Expand Down Expand Up @@ -56,25 +57,9 @@ protected int poll() throws Exception {
exchange.getIn().setHeaders(getMessageHeaders(env));

if (endpoint.isZfo()) {
log.info("Downloading message {} in binary pkcs signed zfo stream.", env.getMessageID());
// download data to this output stream
OutputStream os = new ByteArrayOutputStream();
endpoint.getDataBoxManager().getDataBoxDownloadService().downloadSignedMessage(env, os);
exchange.getIn().setBody(os);
// assume saving exchange to file and by default fill proper filename header
exchange.getIn().setHeader(Exchange.FILE_NAME, env.getMessageID() + ".zfo");
downloadZFO(exchange, env, endpoint);
} else {
log.info("Downloading message {} in unmarshalled Message instance.", env.getMessageID());
Message m = endpoint.getDataBoxManager()
.getDataBoxDownloadService()
.downloadMessage(env, storer);
exchange.getIn().setBody(m);
// map attachments to camel
for (Attachment a : m.getAttachments()) {
// get attachment file and create data handler from it
FileContent fc = (FileContent) a.getContent();
exchange.getIn().addAttachment(a.getDescription(), createDataHandler(fc.getFile()));
}
downloadMessage(exchange, env, endpoint, storer);
}

if (endpoint.isMarkDownloaded()) {
Expand Down Expand Up @@ -103,4 +88,36 @@ public void onComplete(Exchange exchange) {
// number of messages polled
return envelopes.size();
}

static void downloadMessage(Exchange exchange, MessageEnvelope env, ISDSEndpoint endpoint, AttachmentStorer storer) {
log.info("Downloading message {} in unmarshalled Message instance.", env.getMessageID());
Message m = endpoint.getDataBoxManager()
.getDataBoxDownloadService()
.downloadMessage(env, storer);

exchange.getIn().setBody(m);
// map attachments to camel
for (Attachment a : m.getAttachments()) {
// get attachment file and create data handler from it
FileContent fc = (FileContent) a.getContent();
exchange.getIn().addAttachment(a.getDescription(), createDataHandler(fc.getFile()));
}
}

/**
* Download message in zfo format and store it as OutputStream in Exchange body and set Camel file name header.
*
* @param exchange store message to exchange body
* @param env envelope of requested message
* @param endpoint endpoint providing databox manager instance
*/
static void downloadZFO(Exchange exchange, MessageEnvelope env, ISDSEndpoint endpoint) {
log.info("Downloading message {} in binary pkcs signed zfo stream.", env.getMessageID());
// download data to this output stream
OutputStream os = new ByteArrayOutputStream();
endpoint.getDataBoxManager().getDataBoxDownloadService().downloadSignedMessage(env, os);
exchange.getIn().setBody(os);
// assume saving exchange to file and by default fill proper filename header
exchange.getIn().setHeader(Exchange.FILE_NAME, env.getMessageID() + ".zfo");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
* Supported ISDS operations.
*/
public enum ISDSOperation implements ApiName {
MESSAGES("messages", ISDSMessagesConsumer.class, ISDSMessagesProducer.class);
MESSAGES("messages", ISDSMessagesConsumer.class, ISDSMessagesProducer.class),
DOWNLOAD("download", null, ISDSDownloadProducer.class);

private final String name;
private final Class<? extends ISDSConsumer> consumerClass;
Expand Down
96 changes: 96 additions & 0 deletions src/test/java/com/github/czgov/isds/ISDSDownloadTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.github.czgov.isds;

import org.apache.camel.EndpointInject;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.RouteBuilder;

import org.junit.Before;
import org.junit.Test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import cz.abclinuxu.datoveschranky.common.ByteArrayAttachmentStorer;
import cz.abclinuxu.datoveschranky.common.entities.Message;
import cz.abclinuxu.datoveschranky.impl.MessageValidator;

/**
* Created by jludvice on 19.7.17.
*/
public class ISDSDownloadTest extends ISDSTestBase {
public static final Logger log = LoggerFactory.getLogger(ISDSDownloadTest.class);

@EndpointInject(uri = "direct:download-sent")
ProducerTemplate start;

private Message fixtureMessage;

@Before
public void sentTestMessage() {
fixtureMessage = createMessage(getOvmId(), "Msg for Download" + new Date());
getManager().getDataBoxUploadService().sendMessage(fixtureMessage);
log.info("Fixture message {}", fixtureMessage);
}

@Test
public void downloadSentMessage() throws IOException, InterruptedException {

Map<String, Object> headers = new HashMap<>();

headers.put(Constants.MSG_ID, fixtureMessage.getEnvelope().getMessageID());
headers.put(Constants.MSG_TYPE, "sent");

byte[] messageBytes = start.requestBodyAndHeaders(
"direct:download-sent", "message body",
headers, byte[].class);
MessageValidator v = new MessageValidator();
Message m = v.createMessage(messageBytes, new ByteArrayAttachmentStorer());

assertEquals("Subject of sent and downloaded message must match",
fixtureMessage.getEnvelope().getAnnotation(),
m.getEnvelope().getAnnotation());
}

@Test
public void downloadReceivedMessage() throws Exception {

Map<String, Object> headers = new HashMap<>();

headers.put(Constants.MSG_ID, fixtureMessage.getEnvelope().getMessageID());
headers.put(Constants.MSG_TYPE, "received");

log.info("downloading message {}", fixtureMessage.getEnvelope().getMessageID());
Message m = start.requestBodyAndHeaders(
"direct:download-received", "message body",
headers, Message.class);

System.out.println(m);
assertEquals("Subject of sent and downloaded message must match",
fixtureMessage.getEnvelope().getAnnotation(),
m.getEnvelope().getAnnotation());
}

@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
initProperties();
from("direct:download-sent")
.to("isds:download?username={{isds.fo.login}}&password={{isds.fo.password}}&environment=test")
.log("done");

from("direct:download-received")
.to("isds:download?username={{isds.ovm.login}}&password={{isds.ovm.password}}" +
"&environment=test&downloadListMessages=true")
.log("done");
}
};
}
}

0 comments on commit 15185a6

Please sign in to comment.