Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for building MDM "wake up" payloads #516

Merged
merged 2 commits into from
Sep 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@

package com.turo.pushy.apns.util;

import java.io.CharArrayWriter;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.CharArrayWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
* <p>A utility class for constructing JSON payloads suitable for inclusion in APNs push notifications. Payload builders
* are reusable, but are <em>not</em> thread-safe.</p>
Expand Down Expand Up @@ -92,11 +89,13 @@ public class ApnsPayloadBuilder {
private static final String ACTION_LOC_KEY = "action-loc-key";
private static final String LAUNCH_IMAGE_KEY = "launch-image";

private static final String MDM_KEY = "mdm";

private final HashMap<String, Object> customProperties = new HashMap<>();

private static final String ABBREVIATION_SUBSTRING = "…";

private static final Gson gson = new GsonBuilder().serializeNulls().disableHtmlEscaping().create();
private static final Gson GSON = new GsonBuilder().serializeNulls().disableHtmlEscaping().create();

/**
* The name of the iOS default push notification sound
Expand Down Expand Up @@ -659,7 +658,7 @@ public String buildWithMaximumLength(final int maximumPayloadSize) {
}

this.buffer.reset();
gson.toJson(payload, this.buffer);
GSON.toJson(payload, this.buffer);

final String payloadString = this.buffer.toString();
final int initialPayloadSize = payloadString.getBytes(StandardCharsets.UTF_8).length;
Expand All @@ -673,7 +672,7 @@ public String buildWithMaximumLength(final int maximumPayloadSize) {
this.replaceMessageBody(payload, "");

this.buffer.reset();
gson.toJson(payload, this.buffer);
GSON.toJson(payload, this.buffer);

final int payloadSizeWithEmptyMessage = this.buffer.toString().getBytes(StandardCharsets.UTF_8).length;

Expand All @@ -690,7 +689,7 @@ public String buildWithMaximumLength(final int maximumPayloadSize) {
this.replaceMessageBody(payload, fittedMessageBody + ABBREVIATION_SUBSTRING);

this.buffer.reset();
gson.toJson(payload, this.buffer);
GSON.toJson(payload, this.buffer);

fittedPayloadString = this.buffer.toString();
} else {
Expand All @@ -703,6 +702,25 @@ public String buildWithMaximumLength(final int maximumPayloadSize) {
return fittedPayloadString;
}

/**
* Returns a JSON representation of a
* <a href="https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/MobileDeviceManagementProtocolRef/1-Introduction/Introduction.html#//apple_ref/doc/uid/TP40017387-CH1-SW1">Mobile
* Device Management</a> "wake up" payload.
*
* @param pushMagicValue the "push magic" string that the device sends to the MDM server in a {@code TokenUpdate}
* message
*
* @return a JSON representation of an MDM "wake up" notification payload
*
* @see <a href="https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/MobileDeviceManagementProtocolRef/3-MDM_Protocol/MDM_Protocol.html#//apple_ref/doc/uid/TP40017387-CH3-SW2">Mobile
* Device Management (MDM) Protocol</a>
*
* @since 0.12
*/
public static String buildMdmPayload(final String pushMagicValue) {
return GSON.toJson(java.util.Collections.singletonMap(MDM_KEY, pushMagicValue));
}

private void replaceMessageBody(final Map<String, Object> payload, final String messageBody) {
@SuppressWarnings("unchecked")
final Map<String, Object> aps = (Map<String, Object>) payload.get(APS_KEY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@

package com.turo.pushy.apns.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.junit.Before;
import org.junit.Test;

import java.lang.reflect.Type;
import java.nio.charset.CharsetEncoder;
Expand All @@ -33,23 +35,17 @@
import java.util.List;
import java.util.Map;

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

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import static org.junit.Assert.*;

public class ApnsPayloadBuilderTest {

private ApnsPayloadBuilder builder;
private Gson gson;

private static Type MAP_OF_STRING_TO_OBJECT = new TypeToken<Map<String, Object>>(){}.getType();
private static final Gson GSON = new GsonBuilder().serializeNulls().disableHtmlEscaping().create();
private static final Type MAP_OF_STRING_TO_OBJECT = new TypeToken<Map<String, Object>>(){}.getType();

@Before
public void setUp() {
this.gson = new GsonBuilder().serializeNulls().disableHtmlEscaping().create();
this.builder = new ApnsPayloadBuilder();
}

Expand Down Expand Up @@ -429,7 +425,7 @@ public void testAddCustomProperty() {
this.builder.addCustomProperty(customKey, customValue);

@SuppressWarnings("unchecked")
final Map<String, Object> payload = this.gson.fromJson(
final Map<String, Object> payload = GSON.fromJson(
this.builder.buildWithDefaultMaximumLength(), MAP_OF_STRING_TO_OBJECT);

assertEquals(customValue, payload.get(customKey));
Expand Down Expand Up @@ -553,7 +549,7 @@ public void testGetSizeOfJsonEscapedUtf8Character() {
if (encoder.canEncode((char) codePoint)) {
// We subtract 2 here for the quotes that will appear on either end of a JSON string
assertEquals("Escaped/encoded lengths should match for code point " + codePoint,
this.gson.toJson(String.valueOf((char) codePoint)).getBytes(StandardCharsets.UTF_8).length - 2,
GSON.toJson(String.valueOf((char) codePoint)).getBytes(StandardCharsets.UTF_8).length - 2,
ApnsPayloadBuilder.getSizeOfJsonEscapedUtf8Character((char) codePoint));
}
}
Expand All @@ -572,9 +568,14 @@ public void testGetLengthOfJsonEscapedUtf8StringFittingSize() {
assertEquals(2, ApnsPayloadBuilder.getLengthOfJsonEscapedUtf8StringFittingSize("\n\tThis string has escaped characters.", 4));
}

@Test
public void testBuildMdmPayload() {
assertEquals("{\"mdm\":\"Magic!\"}", ApnsPayloadBuilder.buildMdmPayload("Magic!"));
}

@SuppressWarnings("unchecked")
private Map<String, Object> extractApsObjectFromPayloadString(final String payloadString) {
final Map<String, Object> payload = this.gson.fromJson(payloadString, MAP_OF_STRING_TO_OBJECT);
final Map<String, Object> payload = GSON.fromJson(payloadString, MAP_OF_STRING_TO_OBJECT);
return (Map<String, Object>) payload.get("aps");
}
}