diff --git a/api/src/main/java/com/messagebird/MessageBirdServiceImpl.java b/api/src/main/java/com/messagebird/MessageBirdServiceImpl.java index a5e897d..03fff27 100644 --- a/api/src/main/java/com/messagebird/MessageBirdServiceImpl.java +++ b/api/src/main/java/com/messagebird/MessageBirdServiceImpl.java @@ -251,79 +251,77 @@ public List getJsonDataAsList(final String request, final P payload, f return getJsonDataAsList(request, payload, requestType, new HashMap<>(), elementClass); } - public T getJsonData(final String request, final P payload, final String requestType, final Map headers, final Class clazz) throws UnauthorizedException, GeneralException, NotFoundException { + public

APIResponse executeRequest(final String request, final P payload, final String requestType, final Map headers) + throws UnauthorizedException, GeneralException, NotFoundException { if (request == null) { throw new IllegalArgumentException(REQUEST_VALUE_MUST_BE_SPECIFIED); } - String url = request; - if (!isURLAbsolute(url)) { - url = serviceUrl + url; - } - final APIResponse apiResponse = doRequest(requestType, url, headers, payload); + String url = isURLAbsolute(request) ? request : serviceUrl + request; + return doRequest(requestType, url, headers, payload); + } - final String body = apiResponse.getBody(); - final int status = apiResponse.getStatus(); + private ObjectMapper configureObjectMapper() { + final ObjectMapper mapper = new ObjectMapper(); + // If we as new properties, we don't want the system to fail, we rather want to ignore them + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + // Enable case insensitivity to avoid parsing errors if parameters' case in api response doesn't match sdk's + mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); + mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); + return mapper; + } - if (status == HttpURLConnection.HTTP_OK || status == HttpURLConnection.HTTP_CREATED || status == HttpURLConnection.HTTP_ACCEPTED) { - try { - final ObjectMapper mapper = new ObjectMapper(); - // If we as new properties, we don't want the system to fail, we rather want to ignore them - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - // Enable case insensitivity to avoid parsing errors if parameters' case in api response doesn't match sdk's - mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); - mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); - - // Prevents mismatched exception when clazz is null - return clazz == null - ? null - : this.readValue(mapper, body, clazz); - } catch (IOException ioe) { - throw new GeneralException(ioe); - } - } else if (status == HttpURLConnection.HTTP_NO_CONTENT) { - return null; // no content doesn't mean an error + private void handleResponseStatus(final int status, final String body) throws UnauthorizedException, GeneralException, NotFoundException { + if (status == HttpURLConnection.HTTP_OK || + status == HttpURLConnection.HTTP_CREATED || + status == HttpURLConnection.HTTP_ACCEPTED) { + return; + } + + if (status == HttpURLConnection.HTTP_NO_CONTENT) { + return; // no content doesn't mean an error } + handleHttpFailStatuses(status, body); - return null; } - // todo: need to refactor for duplicated code. - public List getJsonDataAsList(final String request, - final P payload, final String requestType, final Map headers, final Class elementClass) - throws UnauthorizedException, GeneralException, NotFoundException { - if (request == null) { - throw new IllegalArgumentException(REQUEST_VALUE_MUST_BE_SPECIFIED); + public T getJsonData(final String request, final P payload, final String requestType, final Map headers, final Class clazz) + throws UnauthorizedException, GeneralException, NotFoundException { + final APIResponse apiResponse = executeRequest(request, payload, requestType, headers); + final int status = apiResponse.getStatus(); + final String body = apiResponse.getBody(); + + handleResponseStatus(status, body); + + // Prevents mismatched exception when clazz is null + if (clazz == null || status == HttpURLConnection.HTTP_NO_CONTENT) { + return null; } - String url = request; - if (!isURLAbsolute(url)) { - url = serviceUrl + url; + try { + return readValue(configureObjectMapper(), body, clazz); + } catch (IOException ioe) { + throw new GeneralException(ioe); } - final APIResponse apiResponse = doRequest(requestType, url, headers, payload); + } - final String body = apiResponse.getBody(); + public List getJsonDataAsList(final String request, final P payload, final String requestType, final Map headers, final Class elementClass) + throws UnauthorizedException, GeneralException, NotFoundException { + final APIResponse apiResponse = executeRequest(request, payload, requestType, headers); final int status = apiResponse.getStatus(); + final String body = apiResponse.getBody(); - if (status == HttpURLConnection.HTTP_OK || status == HttpURLConnection.HTTP_CREATED || status == HttpURLConnection.HTTP_ACCEPTED) { - try { - final ObjectMapper mapper = new ObjectMapper(); - // If we as new properties, we don't want the system to fail, we rather want to ignore them - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - // Enable case insensitivity to avoid parsing errors if parameters' case in api response doesn't match sdk's - mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); - mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); - - // Prevents mismatched exception when clazz is null - return this.readValueAsList(mapper, body, elementClass); - } catch (IOException ioe) { - throw new GeneralException(ioe); - } - } else if (status == HttpURLConnection.HTTP_NO_CONTENT) { - return Collections.emptyList(); // no content doesn't mean an error + handleResponseStatus(status, body); + + if (status == HttpURLConnection.HTTP_NO_CONTENT) { + return Collections.emptyList(); + } + + try { + return readValueAsList(configureObjectMapper(), body, elementClass); + } catch (IOException ioe) { + throw new GeneralException(ioe); } - handleHttpFailStatuses(status, body); - return Collections.emptyList(); } private T readValue(ObjectMapper mapper, String content, Class clazz) diff --git a/api/src/main/java/com/messagebird/RequestValidator.java b/api/src/main/java/com/messagebird/RequestValidator.java index 24ae634..ec8ecad 100644 --- a/api/src/main/java/com/messagebird/RequestValidator.java +++ b/api/src/main/java/com/messagebird/RequestValidator.java @@ -193,12 +193,15 @@ private static String calculateSha256(byte[] bytes) { } private static String encodeHex(final byte[] data) { - final int l = data.length; - final char[] out = new char[l << 1]; - for (int i = 0, j = 0; i < l; i++) { - out[j++] = HEX_DIGITS[(0xF0 & data[i]) >>> 4]; - out[j++] = HEX_DIGITS[0x0F & data[i]]; + final int length = data.length; + final char[] output = new char[length << 1]; + + for (int byteIndex = 0, charIndex = 0; byteIndex < length; byteIndex++) { + int highNibble = (data[byteIndex] & 0xF0) >>> 4; + int lowNibble = data[byteIndex] & 0x0F; + output[charIndex++] = HEX_DIGITS[highNibble]; + output[charIndex++] = HEX_DIGITS[lowNibble]; } - return new String(out); + return new String(output); } } diff --git a/api/src/main/java/com/messagebird/objects/Hlr.java b/api/src/main/java/com/messagebird/objects/Hlr.java index d6244e5..acaabde 100644 --- a/api/src/main/java/com/messagebird/objects/Hlr.java +++ b/api/src/main/java/com/messagebird/objects/Hlr.java @@ -14,9 +14,9 @@ public class Hlr { private String id; private String href; - protected BigInteger msisdn; + private BigInteger msisdn; private String network; - protected String reference; + private String reference; private String status; private Date createdDatetime; private Date statusDatetime; @@ -60,10 +60,14 @@ public String getHref() { * The telephone number. * @return */ - public BigInteger getMsisdn() { + public BigInteger getPhoneNumber() { return msisdn; } + public void setPhoneNumber(BigInteger msisdn) { + this.msisdn = msisdn; + } + /** * The MCCMNC code of the network provider * @return @@ -80,6 +84,10 @@ public String getReference() { return reference; } + public void setReference(String reference) { + this.reference = reference; + } + /** * The status of the msisdns. Possible values: sent, absent, active, unknown, and failed * @return @@ -107,5 +115,9 @@ public Date getStatusDatetime() { public HlrDetails getDetails() { return details; } + + public void setDetails(HlrDetails details) { + this.details = details; + } } diff --git a/api/src/main/java/com/messagebird/objects/LookupHlr.java b/api/src/main/java/com/messagebird/objects/LookupHlr.java index 98e568a..931848e 100644 --- a/api/src/main/java/com/messagebird/objects/LookupHlr.java +++ b/api/src/main/java/com/messagebird/objects/LookupHlr.java @@ -13,15 +13,18 @@ public void setCountryCode(String countryCode) { this.countryCode = countryCode; } + @Override public BigInteger getPhoneNumber() { - return msisdn; + return super.getPhoneNumber(); } + @Override public void setPhoneNumber(BigInteger phoneNumber) { - this.msisdn = phoneNumber; + super.setPhoneNumber(phoneNumber); } + @Override public void setReference(String reference) { - this.reference = reference; + super.setReference(reference); } -} +} \ No newline at end of file diff --git a/api/src/main/java/com/messagebird/objects/conversations/ConversationMessage.java b/api/src/main/java/com/messagebird/objects/conversations/ConversationMessage.java index 2be027b..c4d7a75 100644 --- a/api/src/main/java/com/messagebird/objects/conversations/ConversationMessage.java +++ b/api/src/main/java/com/messagebird/objects/conversations/ConversationMessage.java @@ -120,6 +120,9 @@ public String getPlatform() { } public void setPlatform(String platform) { + if (!ConversationPlatformConstants.isValidPlatform(platform)) { + throw new IllegalArgumentException("Invalid platform: " + platform); + } this.platform = platform; } diff --git a/api/src/main/java/com/messagebird/objects/conversations/ConversationPlatformConstants.java b/api/src/main/java/com/messagebird/objects/conversations/ConversationPlatformConstants.java index b9c02f4..fd73fca 100644 --- a/api/src/main/java/com/messagebird/objects/conversations/ConversationPlatformConstants.java +++ b/api/src/main/java/com/messagebird/objects/conversations/ConversationPlatformConstants.java @@ -1,33 +1,18 @@ package com.messagebird.objects.conversations; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + /** * Platforms are communication channels that a conversation can communicate through. */ public class ConversationPlatformConstants { - // PlatformSMS identifies the MessageBird SMS platform. - public static final String SMS = "sms"; - - // PlatformWhatsApp identifies the WhatsApp platform. - public static final String WHATSAPP = "whatsapp"; - - // PlatformFacebook identifies the Facebook platform. - public static final String FACEBOOK = "facebook"; - - // PlatformTelegram identifies the Telegram platform. - public static final String TELEGRAM = "telegram"; - - // PlatformLine identifies the LINE platform. - public static final String LINE = "line"; - - // PlatformWeChat identifies the WeChat platform. - public static final String WECHAT = "wechat"; - - // PlatformEmail identifies the Email platform. - public static final String EMAIL = "email"; - - // PlatformEvents identifies the Events platform - public static final String EVENTS = "events"; + private static final Set VALID_PLATFORMS = new HashSet<>(Arrays.asList( + "sms", "whatsapp", "facebook", "telegram", "line", "wechat", "email", "events", "whatsapp_sandbox" + )); - // PlatformWhatsAppSandbox identified the WhatsApp sandbox platform. - public static final String WHATSAPP_SANDBOX = "whatsapp_sandbox"; + public static boolean isValidPlatform(String platform) { + return VALID_PLATFORMS.contains(platform); + } } \ No newline at end of file diff --git a/api/src/main/java/com/messagebird/objects/integrations/HSMComponent.java b/api/src/main/java/com/messagebird/objects/integrations/HSMComponent.java index ed93847..e84a658 100644 --- a/api/src/main/java/com/messagebird/objects/integrations/HSMComponent.java +++ b/api/src/main/java/com/messagebird/objects/integrations/HSMComponent.java @@ -188,9 +188,19 @@ private void checkHeaderText() throws IllegalArgumentException { * @throws IllegalArgumentException Occurs when type is not {@code HEADER} and format is not {@code IMAGE}. */ private void checkHeaderUrl() throws IllegalArgumentException { - if (!(HSMComponentType.HEADER.equals(type) && - (HSMComponentFormat.IMAGE.equals(format) || HSMComponentFormat.VIDEO.equals(format) || HSMComponentFormat.DOCUMENT.equals(format)))) { + if (!isHeaderType() || !isValidFormat()) { throw new IllegalArgumentException("\"header_url\" is available for only HEADER type and IMAGE, VIDEO, or DOCUMENT formats."); } } + + private boolean isHeaderType() { + return HSMComponentType.HEADER.equals(type); + } + + private boolean isValidFormat() { + return HSMComponentFormat.IMAGE.equals(format) || + HSMComponentFormat.VIDEO.equals(format) || + HSMComponentFormat.DOCUMENT.equals(format); + } + } diff --git a/api/src/main/java/com/messagebird/objects/voicecalls/SipResponseCode.java b/api/src/main/java/com/messagebird/objects/voicecalls/SipResponseCode.java index 7061c8f..18d3051 100644 --- a/api/src/main/java/com/messagebird/objects/voicecalls/SipResponseCode.java +++ b/api/src/main/java/com/messagebird/objects/voicecalls/SipResponseCode.java @@ -1,7 +1,7 @@ package com.messagebird.objects.voicecalls; -import com.fasterxml.jackson.annotation.JsonCreator; - +import java.util.HashMap; +import java.util.Map; /** * More details, including additional descriptions and common caused can be found here: https://developers.messagebird.com/api/voice-calling/#sip-status-codes @@ -10,64 +10,55 @@ */ public enum SipResponseCode { //Successful - OK, + OK(200), //The server understood the request, but is refusing to fulfill it. - FORBIDDEN, + FORBIDDEN(403), //The server has definitive information that the user does not exist at the domain specified in the Request-URI. - NOT_FOUND, + NOT_FOUND(404), //Couldn't find the user in time. - REQUEST_TIMEOUT, + REQUEST_TIMEOUT(408), //The user existed once, but is not available here any more. - GONE, + GONE(410), //Callee currently unavailable. - TEMPORARILY_UNAVAILABLE, + TEMPORARILY_UNAVAILABLE(480), //Request-URI incomplete. - ADDRESS_INCOMPLETE, + ADDRESS_INCOMPLETE(484), //Callee is busy. - BUSY_HERE, + BUSY_HERE(486), //Some aspect of the session description or the Request-URI is not acceptable. - NOT_ACCEPTABLE_HERE, + NOT_ACCEPTABLE_HERE(488), //The server could not fulfill the request due to some unexpected condition. - INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR(500), //The server does not have the ability to fulfill the request, such as because it does not recognize the request method. - NOT_IMPLEMENTED, + NOT_IMPLEMENTED(501), //The server is acting as a gateway or proxy, and received an invalid response from a downstream server while attempting to fulfill the request. - BAD_GATEWAY, + BAD_GATEWAY(502), //The server is undergoing maintenance or is temporarily overloaded and so cannot process the request. - SERVICE_UNAVAILABLE; + SERVICE_UNAVAILABLE(503); + + private static final Map codeToResponse = new HashMap<>(); + + static { + for (SipResponseCode responseCode : values()) { + codeToResponse.put(responseCode.value, responseCode); + } + } - @JsonCreator - public static SipResponseCode forValue(Integer value) { - switch (value) { - case 200: - return OK; - case 403: - return FORBIDDEN; - case 404: - return NOT_FOUND; - case 408: - return REQUEST_TIMEOUT; - case 410: - return GONE; - case 480: - return TEMPORARILY_UNAVAILABLE; - case 484: - return ADDRESS_INCOMPLETE; - case 486: - return BUSY_HERE; - case 488: - return NOT_ACCEPTABLE_HERE; - case 500: - return INTERNAL_SERVER_ERROR; - case 501: - return NOT_IMPLEMENTED; - case 502: - return BAD_GATEWAY; - case 503: - return SERVICE_UNAVAILABLE; + private final int value; - default: + SipResponseCode(int value) { + this.value = value; + } + + public static SipResponseCode forValue(int value) { + SipResponseCode responseCode = codeToResponse.get(value); + if (responseCode == null) { throw new IllegalArgumentException("Unknown sip response code: " + value); } + return responseCode; + } + + public int getValue() { + return value; } } \ No newline at end of file