Skip to content

Commit 15185a6

Browse files
committed
[closes #30] allow downloading of message by it's id
1 parent c3636b8 commit 15185a6

File tree

8 files changed

+241
-24
lines changed

8 files changed

+241
-24
lines changed

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<sl4j.version>1.7.21</sl4j.version>
3131
<log4j.version>1.2.17</log4j.version>
3232

33-
<java.isds.version>1.1.0</java.isds.version>
33+
<java.isds.version>1.1.1</java.isds.version>
3434
</properties>
3535

3636
<scm>

src/main/docs/isds.adoc

+30-4
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ for real BOM in Camel project but `camel-parent` can be used until then.
2525
<dependency>
2626
<groupId>org.apache.camel</groupId>
2727
<artifactId>camel-parent</artifactId>
28-
<version>${camel.version</version>
28+
<version>${camel.version}</version>
2929
<type>pom</type>
3030
<scope>import</scope>
3131
</dependency>
@@ -55,21 +55,45 @@ isds:messages?options
5555

5656
[[ISDS-Operations]]
5757
### Supported operations
58-
Camel ISDS currently supports only `messages` operation for sending and receiving messages.
58+
59+
#### isds:messages
60+
For sending and receiving messages.
61+
62+
#### isds:download
63+
For downloading of specific isds message by it's id.
64+
65+
Important exchange headers
66+
[width="100%", options="header"]
67+
|=======================================================================
68+
| Header | Default value | Description
69+
| isdsId | null | download message with this ID
70+
| isdsType | received | download message you received. You may also download message you "sent"
71+
|=======================================================================
72+
73+
74+
When downloading message by it's id with `isds:download`,
75+
you might see this error:
76+
-------------------------------------------------------
77+
Nemohu stahnout prijatou zpravu. 1222:Zprava dosud nebyla oznacena jako dorucena, proto ji nelze cist.
78+
-------------------------------------------------------
79+
This is caused by security feature of ISDS.
80+
According to this feature it's forbidden to download message which wasn't marked as delivered.
81+
You may use option `isds:download?downloadListMessages=true` get around that.
82+
Component will first call getListOfReceivedMessages API method to trigger "delivered event" and then it should work.
5983

6084
Operations planned for next releases are:
6185

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

6992

7093

94+
7195
// endpoint options: START
72-
The ISDS component supports 15 endpoint options which are listed below:
96+
The ISDS component supports 16 endpoint options which are listed below:
7397

7498
[width="100%",cols="2s,1,1m,1m,5",options="header"]
7599
|=======================================================================
@@ -87,6 +111,7 @@ The ISDS component supports 15 endpoint options which are listed below:
87111
| 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.
88112
| 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.
89113
| 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.
114+
| 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;
90115
| exchangePattern | advanced | InOnly | ExchangePattern | Sets the default exchange pattern when creating an exchange
91116
| synchronous | advanced | false | boolean | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported).
92117
|=======================================================================
@@ -111,6 +136,7 @@ The ISDS component supports 15 endpoint options which are listed below:
111136

112137

113138

139+
114140

115141

116142
[[ISDS-ISDSComponentOptions]]

src/main/java/com/github/czgov/isds/Constants.java

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public class Constants {
1010
public static final String MSG_ID = PREFIX + "Id";
1111
public static final String MSG_FROM = PREFIX + "From";
1212
public static final String MSG_TO = PREFIX + "To";
13+
public static final String MSG_TYPE = PREFIX + "Type";
1314

1415
public static final String DEFAULT_ATTACHMENT_STORE = "camel-isds-attachment-store";
1516
}

src/main/java/com/github/czgov/isds/ISDSEndpoint.java

+19
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ public class ISDSEndpoint extends DefaultEndpoint {
7373
@UriParam(defaultValue = "false")
7474
private boolean realtime = false;
7575

76+
@UriParam(defaultValue = "false", label = "producer")
77+
private boolean downloadListMessages = false;
78+
7679
private Authentication dataBoxAuth;
7780
private DataBoxManager dataBoxManager;
7881

@@ -242,4 +245,20 @@ public boolean isRealtime() {
242245
public void setRealtime(boolean realtime) {
243246
this.realtime = realtime;
244247
}
248+
249+
public boolean isDownloadListMessages() {
250+
return downloadListMessages;
251+
}
252+
253+
/**
254+
* First call getListOfReceivedMessages before downloading message by it's ID.
255+
* See documentation of ISDS, section 1.6.2.2 Novy Stav.
256+
* User must login into ISDS in order to download messages.
257+
* The only API method that causes "user logged in event" is getListOfReceivedMessages.
258+
* ISDS may throw error number 1222 when downloading message if this option is set to false;
259+
* @param downloadListMessages
260+
*/
261+
public void setDownloadListMessages(boolean downloadListMessages) {
262+
this.downloadListMessages = downloadListMessages;
263+
}
245264
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.github.czgov.isds.internal;
2+
3+
import org.apache.camel.Exchange;
4+
import org.apache.camel.util.ObjectHelper;
5+
6+
import com.github.czgov.isds.Constants;
7+
import com.github.czgov.isds.ISDSEndpoint;
8+
import com.github.czgov.isds.ISDSProducer;
9+
10+
import java.util.Date;
11+
12+
import cz.abclinuxu.datoveschranky.common.FileAttachmentStorer;
13+
import cz.abclinuxu.datoveschranky.common.entities.MessageEnvelope;
14+
import cz.abclinuxu.datoveschranky.common.entities.MessageType;
15+
16+
/**
17+
* Created by jludvice on 19.7.17.
18+
*/
19+
public class ISDSDownloadProducer extends ISDSProducer {
20+
public ISDSDownloadProducer(ISDSEndpoint endpoint) {
21+
super(endpoint);
22+
}
23+
24+
@Override
25+
public void process(Exchange exchange) throws Exception {
26+
27+
final String id = exchange.getIn().getHeader(Constants.MSG_ID, String.class);
28+
final MessageType type = exchange.getIn().getHeader(Constants.MSG_TYPE, "received", MessageType.class);
29+
30+
ObjectHelper.notNull(id, "Camel header " + Constants.MSG_ID);
31+
32+
System.out.printf("fetching %s message #%s\n", type, id);
33+
34+
MessageEnvelope env = new MessageEnvelope();
35+
env.setMessageID(id);
36+
env.setType(type);
37+
38+
if (MessageType.RECEIVED.equals(type) && endpoint.isDownloadListMessages()) {
39+
// hack around isds policy which doesn't allow downloading of messages
40+
// which arrived before user logged in (or called getListOfReceivedMessages API method
41+
Date d = new Date();
42+
log.info("Calling getListOfReceivedMessages before downloading message by id {}", id);
43+
// don't care about result, just need ISDS to mark messages as delivered
44+
endpoint.getDataBoxManager()
45+
.getDataBoxMessagesService()
46+
.getListOfReceivedMessages(d, d, null, 1, 1);
47+
}
48+
49+
if (MessageType.SENT.equals(type) || endpoint.isZfo()) {
50+
ISDSMessagesConsumer.downloadZFO(exchange, env, endpoint);
51+
} else {
52+
ISDSMessagesConsumer.downloadMessage(exchange, env, endpoint,
53+
new FileAttachmentStorer(endpoint.getAttachmentStore().toFile()));
54+
}
55+
log.info("probably need TODO :)");
56+
}
57+
}

src/main/java/com/github/czgov/isds/internal/ISDSMessagesConsumer.java

+35-18
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import cz.abclinuxu.datoveschranky.common.entities.Message;
1717
import cz.abclinuxu.datoveschranky.common.entities.MessageEnvelope;
1818
import cz.abclinuxu.datoveschranky.common.entities.content.FileContent;
19+
import cz.abclinuxu.datoveschranky.common.interfaces.AttachmentStorer;
1920

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

5859
if (endpoint.isZfo()) {
59-
log.info("Downloading message {} in binary pkcs signed zfo stream.", env.getMessageID());
60-
// download data to this output stream
61-
OutputStream os = new ByteArrayOutputStream();
62-
endpoint.getDataBoxManager().getDataBoxDownloadService().downloadSignedMessage(env, os);
63-
exchange.getIn().setBody(os);
64-
// assume saving exchange to file and by default fill proper filename header
65-
exchange.getIn().setHeader(Exchange.FILE_NAME, env.getMessageID() + ".zfo");
60+
downloadZFO(exchange, env, endpoint);
6661
} else {
67-
log.info("Downloading message {} in unmarshalled Message instance.", env.getMessageID());
68-
Message m = endpoint.getDataBoxManager()
69-
.getDataBoxDownloadService()
70-
.downloadMessage(env, storer);
71-
exchange.getIn().setBody(m);
72-
// map attachments to camel
73-
for (Attachment a : m.getAttachments()) {
74-
// get attachment file and create data handler from it
75-
FileContent fc = (FileContent) a.getContent();
76-
exchange.getIn().addAttachment(a.getDescription(), createDataHandler(fc.getFile()));
77-
}
62+
downloadMessage(exchange, env, endpoint, storer);
7863
}
7964

8065
if (endpoint.isMarkDownloaded()) {
@@ -103,4 +88,36 @@ public void onComplete(Exchange exchange) {
10388
// number of messages polled
10489
return envelopes.size();
10590
}
91+
92+
static void downloadMessage(Exchange exchange, MessageEnvelope env, ISDSEndpoint endpoint, AttachmentStorer storer) {
93+
log.info("Downloading message {} in unmarshalled Message instance.", env.getMessageID());
94+
Message m = endpoint.getDataBoxManager()
95+
.getDataBoxDownloadService()
96+
.downloadMessage(env, storer);
97+
98+
exchange.getIn().setBody(m);
99+
// map attachments to camel
100+
for (Attachment a : m.getAttachments()) {
101+
// get attachment file and create data handler from it
102+
FileContent fc = (FileContent) a.getContent();
103+
exchange.getIn().addAttachment(a.getDescription(), createDataHandler(fc.getFile()));
104+
}
105+
}
106+
107+
/**
108+
* Download message in zfo format and store it as OutputStream in Exchange body and set Camel file name header.
109+
*
110+
* @param exchange store message to exchange body
111+
* @param env envelope of requested message
112+
* @param endpoint endpoint providing databox manager instance
113+
*/
114+
static void downloadZFO(Exchange exchange, MessageEnvelope env, ISDSEndpoint endpoint) {
115+
log.info("Downloading message {} in binary pkcs signed zfo stream.", env.getMessageID());
116+
// download data to this output stream
117+
OutputStream os = new ByteArrayOutputStream();
118+
endpoint.getDataBoxManager().getDataBoxDownloadService().downloadSignedMessage(env, os);
119+
exchange.getIn().setBody(os);
120+
// assume saving exchange to file and by default fill proper filename header
121+
exchange.getIn().setHeader(Exchange.FILE_NAME, env.getMessageID() + ".zfo");
122+
}
106123
}

src/main/java/com/github/czgov/isds/internal/ISDSOperation.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
* Supported ISDS operations.
1010
*/
1111
public enum ISDSOperation implements ApiName {
12-
MESSAGES("messages", ISDSMessagesConsumer.class, ISDSMessagesProducer.class);
12+
MESSAGES("messages", ISDSMessagesConsumer.class, ISDSMessagesProducer.class),
13+
DOWNLOAD("download", null, ISDSDownloadProducer.class);
1314

1415
private final String name;
1516
private final Class<? extends ISDSConsumer> consumerClass;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.github.czgov.isds;
2+
3+
import org.apache.camel.EndpointInject;
4+
import org.apache.camel.ProducerTemplate;
5+
import org.apache.camel.RoutesBuilder;
6+
import org.apache.camel.builder.RouteBuilder;
7+
8+
import org.junit.Before;
9+
import org.junit.Test;
10+
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
14+
import java.io.IOException;
15+
import java.util.Date;
16+
import java.util.HashMap;
17+
import java.util.Map;
18+
19+
import cz.abclinuxu.datoveschranky.common.ByteArrayAttachmentStorer;
20+
import cz.abclinuxu.datoveschranky.common.entities.Message;
21+
import cz.abclinuxu.datoveschranky.impl.MessageValidator;
22+
23+
/**
24+
* Created by jludvice on 19.7.17.
25+
*/
26+
public class ISDSDownloadTest extends ISDSTestBase {
27+
public static final Logger log = LoggerFactory.getLogger(ISDSDownloadTest.class);
28+
29+
@EndpointInject(uri = "direct:download-sent")
30+
ProducerTemplate start;
31+
32+
private Message fixtureMessage;
33+
34+
@Before
35+
public void sentTestMessage() {
36+
fixtureMessage = createMessage(getOvmId(), "Msg for Download" + new Date());
37+
getManager().getDataBoxUploadService().sendMessage(fixtureMessage);
38+
log.info("Fixture message {}", fixtureMessage);
39+
}
40+
41+
@Test
42+
public void downloadSentMessage() throws IOException, InterruptedException {
43+
44+
Map<String, Object> headers = new HashMap<>();
45+
46+
headers.put(Constants.MSG_ID, fixtureMessage.getEnvelope().getMessageID());
47+
headers.put(Constants.MSG_TYPE, "sent");
48+
49+
byte[] messageBytes = start.requestBodyAndHeaders(
50+
"direct:download-sent", "message body",
51+
headers, byte[].class);
52+
MessageValidator v = new MessageValidator();
53+
Message m = v.createMessage(messageBytes, new ByteArrayAttachmentStorer());
54+
55+
assertEquals("Subject of sent and downloaded message must match",
56+
fixtureMessage.getEnvelope().getAnnotation(),
57+
m.getEnvelope().getAnnotation());
58+
}
59+
60+
@Test
61+
public void downloadReceivedMessage() throws Exception {
62+
63+
Map<String, Object> headers = new HashMap<>();
64+
65+
headers.put(Constants.MSG_ID, fixtureMessage.getEnvelope().getMessageID());
66+
headers.put(Constants.MSG_TYPE, "received");
67+
68+
log.info("downloading message {}", fixtureMessage.getEnvelope().getMessageID());
69+
Message m = start.requestBodyAndHeaders(
70+
"direct:download-received", "message body",
71+
headers, Message.class);
72+
73+
System.out.println(m);
74+
assertEquals("Subject of sent and downloaded message must match",
75+
fixtureMessage.getEnvelope().getAnnotation(),
76+
m.getEnvelope().getAnnotation());
77+
}
78+
79+
@Override
80+
protected RoutesBuilder createRouteBuilder() throws Exception {
81+
return new RouteBuilder() {
82+
@Override
83+
public void configure() throws Exception {
84+
initProperties();
85+
from("direct:download-sent")
86+
.to("isds:download?username={{isds.fo.login}}&password={{isds.fo.password}}&environment=test")
87+
.log("done");
88+
89+
from("direct:download-received")
90+
.to("isds:download?username={{isds.ovm.login}}&password={{isds.ovm.password}}" +
91+
"&environment=test&downloadListMessages=true")
92+
.log("done");
93+
}
94+
};
95+
}
96+
}

0 commit comments

Comments
 (0)