Skip to content

Commit 9c53157

Browse files
authored
Detailed exceptions for teh delivery start failures (#106)
1 parent caf2500 commit 9c53157

File tree

7 files changed

+107
-48
lines changed

7 files changed

+107
-48
lines changed

library/src/main/java/com/fidesmo/fdsm/Field.java

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,41 +21,28 @@
2121
*/
2222
package com.fidesmo.fdsm;
2323

24+
import java.util.Collections;
2425
import java.util.List;
2526
import java.util.Optional;
2627

2728
public class Field {
2829
private final String id;
29-
private final String label;
3030
private final List<String> labels;
3131
private final String type;
32-
private final String format;
32+
private final Optional<String> format;
3333
private String value;
3434

35-
public Field(String id, String label, String type, String format) {
35+
public Field(String id, List<String> labels, String type, Optional<String> format) {
3636
this.id = id;
37-
this.label = label;
37+
this.labels = Collections.unmodifiableList(labels);
3838
this.type = type;
3939
this.format = format;
40-
this.labels = null;
41-
}
42-
43-
public Field(String id, String label, String type, String format, List<String> labels) {
44-
this.id = id;
45-
this.label = label;
46-
this.type = type;
47-
this.format = format;
48-
this.labels = List.copyOf(labels);
4940
}
5041

5142
public String getId() {
5243
return id;
5344
}
5445

55-
public String getLabel() {
56-
return label;
57-
}
58-
5946
public List<String> getLabels() {
6047
return List.copyOf(labels);
6148
}
@@ -73,6 +60,21 @@ public void setValue(String value) {
7360
}
7461

7562
public Optional<String> getFormat() {
76-
return Optional.ofNullable(format);
63+
return format;
64+
}
65+
66+
public String getSingleLabel() {
67+
return labels.isEmpty() ? "" : labels.get(0);
68+
}
69+
70+
@Override
71+
public String toString() {
72+
return "Field{" +
73+
"id='" + id + '\'' +
74+
(labels != null ? ", labels=" + labels : "") +
75+
", type='" + type + '\'' +
76+
", format='" + format + '\'' +
77+
", value='" + value + '\'' +
78+
'}';
7779
}
7880
}

library/src/main/java/com/fidesmo/fdsm/ServiceDeliverySession.java

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
import com.fasterxml.jackson.databind.node.ArrayNode;
3131
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
3232
import com.fasterxml.jackson.databind.node.ObjectNode;
33+
import com.fidesmo.fdsm.exceptions.FDSMException;
34+
import com.fidesmo.fdsm.exceptions.NoAccessToDeviceException;
35+
import com.fidesmo.fdsm.exceptions.ServiceNotAvailableException;
36+
3337
import org.apache.http.client.HttpResponseException;
3438
import org.slf4j.Logger;
3539
import org.slf4j.LoggerFactory;
@@ -115,11 +119,22 @@ public DeliveryResult deliver(BIBO bibo, String appId, String serviceId) throws
115119
int platformVersion = capabilities.get("platformVersion").asInt();
116120

117121
// Query service parameters
118-
JsonNode service = client.rpc(client.getURI(FidesmoApiClient.SERVICE_FOR_CARD_URL, appId, serviceId, HexUtils.bin2hex(card.getCIN())), null);
119-
120-
// We do not support paid services
121-
if (service.has("price")) {
122-
throw new FDSMException("Services requiring payment are not supported by fdsm. Please use the Android app!");
122+
JsonNode service;
123+
try {
124+
service = client.rpc(client.getURI(FidesmoApiClient.SERVICE_FOR_CARD_URL, appId, serviceId, HexUtils.bin2hex(card.getCIN())), null);
125+
} catch (HttpResponseException e) {
126+
switch(e.getStatusCode()) {
127+
case 404:
128+
throw new ServiceNotAvailableException("Unknown service ID: " + serviceId, ServiceNotAvailableException.ErrorCode.UNKNOWN_SERVICE, e);
129+
case 403:
130+
throw new ServiceNotAvailableException("Service is not available for this device", ServiceNotAvailableException.ErrorCode.NOT_AVAILABLE_FOR_DEVICE, e);
131+
case 406:
132+
throw new ServiceNotAvailableException("Service is not available for this client", ServiceNotAvailableException.ErrorCode.NOT_AVAILABLE_FOR_DEVICE, e);
133+
case 412:
134+
throw new ServiceNotAvailableException("Service is not available for the current device state", ServiceNotAvailableException.ErrorCode.NOT_AVAILABLE_IN_CURRENT_STATE, e);
135+
default:
136+
throw e;
137+
}
123138
}
124139

125140
JsonNode description = service.get("description");
@@ -157,9 +172,9 @@ public DeliveryResult deliver(BIBO bibo, String appId, String serviceId) throws
157172
ArrayList<Field> fields = new ArrayList<>(fieldsFromNode(description.get("fieldsRequired")));
158173
// Old style fields hack
159174
if (description.has("emailRequired"))
160-
fields.add(new Field("email", FidesmoApiClient.lamei18n(description.get("emailRequired")), "edit", null));
175+
fields.add(new Field("email", Collections.singletonList(FidesmoApiClient.lamei18n(description.get("emailRequired"))), "edit", Optional.empty()));
161176
if (description.has("msisdnRequired"))
162-
fields.add(new Field("msisdn", FidesmoApiClient.lamei18n(description.get("msisdnRequired")), "edit", null));
177+
fields.add(new Field("msisdn", Collections.singletonList(FidesmoApiClient.lamei18n(description.get("msisdnRequired"))), "edit", Optional.empty()));
163178

164179
Map<String, Field> userInput = formHandler.processForm(fields);
165180
if (description.has("emailRequired"))
@@ -169,7 +184,16 @@ public DeliveryResult deliver(BIBO bibo, String appId, String serviceId) throws
169184

170185
deliveryRequest.set("fields", mapToJsonNode(userInput));
171186

172-
JsonNode delivery = client.rpc(client.getURI(FidesmoApiClient.SERVICE_DELIVER_URL), deliveryRequest);
187+
JsonNode delivery;
188+
189+
try {
190+
delivery = client.rpc(client.getURI(FidesmoApiClient.SERVICE_DELIVER_URL), deliveryRequest);
191+
} catch (HttpResponseException e) {
192+
if (e.getStatusCode() == 403) {
193+
throw new NoAccessToDeviceException("Access to device is denied. Device is owned by another user", e);
194+
} else throw e;
195+
}
196+
173197
String sessionId = delivery.get("sessionId").asText();
174198

175199
logger.info("Delivering: {}", FidesmoApiClient.lamei18n(description.get("title")));
@@ -462,20 +486,25 @@ private List<Field> fieldsFromNode(JsonNode fieldsNode) {
462486

463487
List<Field> fields = new ArrayList<>(fieldsNode.size());
464488

465-
for (JsonNode fieldNode : fieldsNode) {
466-
String label = FidesmoApiClient.lamei18n(fieldNode.get("label"));
467-
List<String> fieldsList = new ArrayList<>();
489+
for (JsonNode fieldNode : fieldsNode) {
490+
List<String> labelsList = new ArrayList<>();
491+
468492
JsonNode labels = fieldNode.get("labels");
469493
if (labels != null && labels.isArray()) {
470494
ArrayNode a = (ArrayNode) labels;
471-
a.elements().forEachRemaining(e -> fieldsList.add(FidesmoApiClient.lamei18n(e)));
495+
a.elements().forEachRemaining(e -> labelsList.add(FidesmoApiClient.lamei18n(e)));
496+
} else {
497+
String label = FidesmoApiClient.lamei18n(fieldNode.get("label"));
498+
499+
if (label != null) {
500+
labelsList.addAll(Arrays.asList(label.split("\n")));
501+
}
472502
}
473503
fields.add(new Field(
474-
fieldNode.get("id").asText(),
475-
label,
476-
fieldNode.get("type").asText(),
477-
Optional.ofNullable(fieldNode.get("format")).map(JsonNode::asText).orElse(null),
478-
fieldsList
504+
fieldNode.get("id").asText(),
505+
labelsList,
506+
fieldNode.get("type").asText(),
507+
Optional.ofNullable(fieldNode.get("format")).map(JsonNode::asText)
479508
));
480509
}
481510

library/src/main/java/com/fidesmo/fdsm/FDSMException.java renamed to library/src/main/java/com/fidesmo/fdsm/exceptions/FDSMException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2020
* THE SOFTWARE.
2121
*/
22-
package com.fidesmo.fdsm;
22+
package com.fidesmo.fdsm.exceptions;
2323

2424
public class FDSMException extends RuntimeException {
2525
public static final long serialVersionUID = -8067674386438803572L;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.fidesmo.fdsm.exceptions;
2+
3+
public class NoAccessToDeviceException extends FDSMException {
4+
5+
public NoAccessToDeviceException(String message) {
6+
super(message);
7+
}
8+
9+
public NoAccessToDeviceException(String message, Throwable cause) {
10+
super(message, cause);
11+
}
12+
13+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.fidesmo.fdsm.exceptions;
2+
3+
public class ServiceNotAvailableException extends FDSMException {
4+
public static enum ErrorCode {
5+
NOT_AVAILABLE_FOR_DEVICE,
6+
NOT_AVAILABLE_FOR_CLIENT,
7+
NOT_AVAILABLE_IN_CURRENT_STATE,
8+
UNKNOWN_SERVICE
9+
}
10+
11+
public ServiceNotAvailableException(String message, ErrorCode errorCode) {
12+
super(message);
13+
}
14+
15+
public ServiceNotAvailableException(String message, ErrorCode errorCode, Throwable cause) {
16+
super(message, cause);
17+
}
18+
19+
}

tool/src/main/java/com/fidesmo/fdsm/CommandLineFormHandler.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public Map<String, Field> processForm(List<Field> form) {
4747
for (Field field : form) {
4848
// Display-only fields
4949
if ("text".equals(field.getType()) || "image".equals(field.getType())) {
50-
System.out.println(field.getLabel());
50+
System.out.println(field.getSingleLabel());
5151
continue;
5252
}
5353
// Value fields
@@ -68,38 +68,32 @@ protected Optional<String> askForField(Field f) {
6868
Optional<String> input;
6969
switch (f.getType()) {
7070
case "checkbox":
71-
System.out.println(f.getLabel() + ":");
71+
System.out.println(f.getSingleLabel() + ":");
7272
do {
7373
System.out.println("Must be \"y\" or \"n\"");
7474
input = Optional.ofNullable(console.readLine("> [y/n] "));
7575
} while (input.isPresent() && !input.get().trim().toLowerCase().matches("^(y|n)$"));
7676
return input.map(i -> i.trim().toLowerCase().equals("y") ? "true" : "false");
7777
case "edit":
78-
System.out.println(f.getLabel() + ":");
78+
System.out.println(f.getSingleLabel() + ":");
7979
return Optional.ofNullable(console.readLine("> "));
8080
case "paymentcard":
81-
System.out.println(f.getLabel() + ":");
81+
System.out.println(f.getSingleLabel() + ":");
8282
do {
8383
System.out.println("Format must be \"PAN;MM/YY;CVV\" or \"PAN;MM/YY\" if no CVC doesn't apply");
8484
input = Optional.ofNullable(console.readLine("> "));
8585
} while (input.isPresent() && !input.get().trim().matches("^[0-9]{13,19};[0-1][0-9]/[0-9]{2}(;[0-9]{3})?$"));
8686
return input;
8787
case "date":
88-
System.out.println(f.getLabel() + ":");
88+
System.out.println(f.getSingleLabel() + ":");
8989
// Validate
9090
do {
9191
System.out.println("Format must be \"YYYY-MM-DD\"");
9292
input = Optional.ofNullable(console.readLine("> [YYYY-MM-DD] "));
9393
} while (input.isPresent() && !input.get().trim().matches("^[0-9]{4}-[0-9]{2}-[0-9]{2}$"));
9494
return input;
9595
case "option":
96-
String[] options;
97-
if (f.getLabels() == null || f.getLabels().isEmpty()) {
98-
//Try to fall back to old format
99-
options = f.getLabel().split("\n");
100-
} else {
101-
options = f.getLabels().toArray(new String[f.getLabels().size()]);
102-
}
96+
String[] options = f.getLabels().toArray(new String[f.getLabels().size()]);
10397
List<String> indexes = IntStream.range(0, options.length).mapToObj(i -> String.valueOf(i)).collect(Collectors.toList());
10498
Set<String> allowed = indexes.stream().collect(Collectors.toSet());
10599
String format = IntStream.range(0, options.length).mapToObj(i -> String.valueOf(i)).collect(Collectors.joining(","));

tool/src/main/java/com/fidesmo/fdsm/Main.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import com.fasterxml.jackson.databind.node.ArrayNode;
3434
import com.fasterxml.jackson.databind.node.ObjectNode;
3535
import com.fidesmo.fdsm.FidesmoCard.ChipPlatform;
36+
import com.fidesmo.fdsm.exceptions.FDSMException;
37+
3638
import jnasmartcardio.Smartcardio;
3739
import org.apache.commons.codec.binary.Hex;
3840
import org.apache.commons.io.FilenameUtils;

0 commit comments

Comments
 (0)