com.turo.pushy.apns.AbstractClientServerTest.java Source code

Java tutorial

Introduction

Here is the source code for com.turo.pushy.apns.AbstractClientServerTest.java

Source

/*
 * Copyright (c) 2013-2018 Turo
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.turo.pushy.apns;

import com.turo.pushy.apns.auth.ApnsSigningKey;
import com.turo.pushy.apns.auth.ApnsVerificationKey;
import com.turo.pushy.apns.auth.KeyPairUtil;
import com.turo.pushy.apns.server.MockApnsServer;
import com.turo.pushy.apns.server.MockApnsServerBuilder;
import com.turo.pushy.apns.server.MockApnsServerListener;
import com.turo.pushy.apns.server.PushNotificationHandlerFactory;
import com.turo.pushy.apns.util.ApnsPayloadBuilder;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.concurrent.Promise;
import io.netty.util.concurrent.PromiseCombiner;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;

import javax.net.ssl.SSLException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyPair;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.util.*;

public class AbstractClientServerTest {

    protected static NioEventLoopGroup CLIENT_EVENT_LOOP_GROUP;
    protected static NioEventLoopGroup SERVER_EVENT_LOOP_GROUP;

    protected static final String CA_CERTIFICATE_FILENAME = "/ca.pem";
    protected static final String SERVER_CERTIFICATES_FILENAME = "/server-certs.pem";
    protected static final String SERVER_KEY_FILENAME = "/server-key.pem";

    protected static final String MULTI_TOPIC_CLIENT_KEYSTORE_FILENAME = "/multi-topic-client.p12";
    protected static final String KEYSTORE_PASSWORD = "pushy-test";

    protected static final String HOST = "localhost";
    protected static final int PORT = 8443;

    protected static final String TEAM_ID = "team-id";
    protected static final String KEY_ID = "key-id";
    protected static final String TOPIC = "com.relayrides.pushy";
    protected static final String DEVICE_TOKEN = generateRandomDeviceToken();
    protected static final String PAYLOAD = generateRandomPayload();

    protected static final Map<String, Set<String>> DEVICE_TOKENS_BY_TOPIC = Collections.singletonMap(TOPIC,
            Collections.singleton(DEVICE_TOKEN));

    protected static final Map<String, Date> EXPIRATION_TIMESTAMPS_BY_DEVICE_TOKEN = Collections.emptyMap();

    protected static final int TOKEN_LENGTH = 32; // bytes

    protected ApnsSigningKey signingKey;
    protected Map<String, ApnsVerificationKey> verificationKeysByKeyId;
    protected Map<ApnsVerificationKey, Set<String>> topicsByVerificationKey;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        CLIENT_EVENT_LOOP_GROUP = new NioEventLoopGroup(2);
        SERVER_EVENT_LOOP_GROUP = new NioEventLoopGroup(2);
    }

    @Before
    public void setUp() throws Exception {
        final KeyPair keyPair = KeyPairUtil.generateKeyPair();

        this.signingKey = new ApnsSigningKey(KEY_ID, TEAM_ID, (ECPrivateKey) keyPair.getPrivate());
        final ApnsVerificationKey verificationKey = new ApnsVerificationKey(KEY_ID, TEAM_ID,
                (ECPublicKey) keyPair.getPublic());

        this.verificationKeysByKeyId = Collections.singletonMap(KEY_ID, verificationKey);
        this.topicsByVerificationKey = Collections.singletonMap(verificationKey, Collections.singleton(TOPIC));
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        final PromiseCombiner combiner = new PromiseCombiner();
        combiner.addAll(CLIENT_EVENT_LOOP_GROUP.shutdownGracefully(), SERVER_EVENT_LOOP_GROUP.shutdownGracefully());

        final Promise<Void> shutdownPromise = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
        combiner.finish(shutdownPromise);
        shutdownPromise.await();
    }

    protected ApnsClient buildTlsAuthenticationClient() throws IOException {
        return this.buildTlsAuthenticationClient(null);
    }

    protected ApnsClient buildTlsAuthenticationClient(final ApnsClientMetricsListener metricsListener)
            throws IOException {
        try (final InputStream p12InputStream = getClass()
                .getResourceAsStream(MULTI_TOPIC_CLIENT_KEYSTORE_FILENAME)) {
            return new ApnsClientBuilder().setApnsServer(HOST, PORT)
                    .setClientCredentials(p12InputStream, KEYSTORE_PASSWORD)
                    .setTrustedServerCertificateChain(getClass().getResourceAsStream(CA_CERTIFICATE_FILENAME))
                    .setEventLoopGroup(CLIENT_EVENT_LOOP_GROUP).setMetricsListener(metricsListener).build();
        }
    }

    protected ApnsClient buildTokenAuthenticationClient() throws SSLException {
        return this.buildTokenAuthenticationClient(null);
    }

    protected ApnsClient buildTokenAuthenticationClient(final ApnsClientMetricsListener metricsListener)
            throws SSLException {
        return new ApnsClientBuilder().setApnsServer(HOST, PORT)
                .setTrustedServerCertificateChain(getClass().getResourceAsStream(CA_CERTIFICATE_FILENAME))
                .setSigningKey(this.signingKey).setEventLoopGroup(CLIENT_EVENT_LOOP_GROUP)
                .setMetricsListener(metricsListener).build();
    }

    protected MockApnsServer buildServer(final PushNotificationHandlerFactory handlerFactory) throws SSLException {
        return this.buildServer(handlerFactory, null);
    }

    protected MockApnsServer buildServer(final PushNotificationHandlerFactory handlerFactory,
            final MockApnsServerListener listener) throws SSLException {
        return new MockApnsServerBuilder()
                .setServerCredentials(getClass().getResourceAsStream(SERVER_CERTIFICATES_FILENAME),
                        getClass().getResourceAsStream(SERVER_KEY_FILENAME), null)
                .setTrustedClientCertificateChain(getClass().getResourceAsStream(CA_CERTIFICATE_FILENAME))
                .setEventLoopGroup(SERVER_EVENT_LOOP_GROUP).setHandlerFactory(handlerFactory).setListener(listener)
                .build();
    }

    protected static String generateRandomDeviceToken() {
        final byte[] tokenBytes = new byte[TOKEN_LENGTH];
        new Random().nextBytes(tokenBytes);

        final StringBuilder builder = new StringBuilder(TOKEN_LENGTH * 2);

        for (final byte b : tokenBytes) {
            builder.append(String.format("%02x", b));
        }

        return builder.toString();
    }

    protected static String generateRandomPayload() {
        final ApnsPayloadBuilder payloadBuilder = new ApnsPayloadBuilder();
        payloadBuilder.setAlertBody(UUID.randomUUID().toString());

        return payloadBuilder.buildWithDefaultMaximumLength();
    }
}