Java tutorial
/* * 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(); } }