com.mobicage.rogerthat.CallbackApiServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.mobicage.rogerthat.CallbackApiServlet.java

Source

/*
 * Copyright (c) 2011-2014, MOBICAGE NV
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 * This product includes software developed by Mobicage NV.
 * 4. Neither the name of the Mobicage NV nor the
 * names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY MOBICAGE NV ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL MOBICAGE NV BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @@license_version:1.7@@
 */

package com.mobicage.rogerthat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import com.mobicage.rogerthat.callbacks.RequestContext;

public abstract class CallbackApiServlet extends HttpServlet implements CallbackApiReceiver {

    private static final long serialVersionUID = -7107888583422392210L;
    private static final Logger log = Logger.getLogger(CallbackApiServlet.class.getName());

    private CallbackProcessor processor = new CallbackProcessor();
    private String sikKey;
    private boolean logTraffic = false;
    private CallbackDedup callbackDedup;

    /**
     * Sets the Rogerthat Service Identity Key for which this service shall only accept incoming requests.
     * 
     * @param sikKey
     */
    public void setSikKey(String sikKey) {
        this.sikKey = sikKey;
    }

    /**
     * Sets whether traffic to and from Rogerthat should be logged.
     * 
     * @param logTraffic
     */
    public void setLogTraffic(boolean logTraffic) {
        this.logTraffic = logTraffic;
    }

    /**
     * Set a callback de-duplicator
     * 
     * @param callbackDedup
     */
    public void setCallbackDedup(CallbackDedup callbackDedup) {
        this.callbackDedup = callbackDedup;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.test.TestHandler handler) {
        processor.testTestHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.messaging.UpdateHandler handler) {
        processor.messagingUpdateHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.messaging.PokeHandler handler) {
        processor.messagingPokeHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.messaging.FormUpdateHandler handler) {
        processor.messagingFormUpdateHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.messaging.FlowMemberResultHandler handler) {
        processor.messagingFlowMemberResultHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.friend.InviteResultHandler handler) {
        processor.friendInviteResultHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.friend.InvitedHandler handler) {
        processor.friendInvitedHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.friend.BrokeUpHandler handler) {
        processor.friendBrokeUpHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.friend.InReachHandler handler) {
        processor.friendInReachHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.friend.OutOfReachHandler handler) {
        processor.friendOutOfReachHandler = handler;
    }

    public void subscribe(com.mobicage.rogerthat.callbacks.system.ApiCallHandler handler) {
        processor.systemApiCallHandler = handler;
    }

    /**
     * Validates whether a request should be served depending on the supplied Rogerthat Service Identifier Key. Override
     * this method to support handling multiple Rogerthat services with different Service Identifier Keys.
     * 
     * @param sikKey
     * @return whether the request shoud be served or not.
     */
    protected boolean validateSIK(String sikKey) {
        if (this.sikKey == null)
            return false;
        else
            return this.sikKey.equals(sikKey);
    }

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json-rpc; charset=utf-8");

        // Validate incomming request
        final String contentType = req.getHeader("Content-type");
        if (contentType == null || !contentType.startsWith("application/json-rpc")) {
            resp.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
            return;
        }
        final String sikKey = req.getHeader("X-Nuntiuz-Service-Key");
        if (!validateSIK(sikKey)) {
            resp.setStatus(HttpURLConnection.HTTP_UNAUTHORIZED);
            return;
        }

        // Parse
        final InputStream is = req.getInputStream();
        final JSONObject request;
        try {
            request = (JSONObject) JSONValue.parse(new BufferedReader(new InputStreamReader(is, "UTF-8")));
        } finally {
            is.close();
        }

        if (logTraffic)
            log.info(String.format("Incoming Rogerthat API Callback.\nSIK: %s\n\n%s", sikKey,
                    request.toJSONString()));

        final String id = (String) request.get("id");

        if (callbackDedup != null) {
            byte[] response = callbackDedup.getResponse(id);
            if (response != null) {
                ServletOutputStream outputStream = resp.getOutputStream();
                outputStream.write(response);
                outputStream.flush();
                return;
            }
        }

        final JSONObject result = new JSONObject();
        final RequestContext requestContext = new RequestContext(id, sikKey);
        try {
            processor.process(request, result, requestContext);
        } finally {
            String jsonString = result.toJSONString();
            if (logTraffic)
                log.info("Returning result:\n" + jsonString);

            byte[] response = jsonString.getBytes("UTF-8");
            if (callbackDedup != null) {
                callbackDedup.storeResponse(id, response);
            }

            ServletOutputStream outputStream = resp.getOutputStream();
            outputStream.write(response);
            outputStream.flush();
        }
    }

    protected void validateServletConfiguration() throws ServletException {
        if (sikKey == null)
            throw new ServletException("Servlet is not initialized. Need a callbackApi and sikKey");
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        validateServletConfiguration();
    }
}