org.sparkbit.jsonrpc.SparkBitServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.sparkbit.jsonrpc.SparkBitServlet.java

Source

/*
 * SparkBit
 *
 * Copyright 2014 Coin Sciences Ltd
 *
 * Licensed under the MIT license (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://opensource.org/licenses/mit-license.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sparkbit.jsonrpc;

import java.io.IOException;

import com.bitmechanic.barrister.*;
import com.bitmechanic.barrister.Contract;
import com.bitmechanic.barrister.Server;
import com.bitmechanic.barrister.JacksonSerializer;
import org.sparkbit.jsonrpc.autogen.*;

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

import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SparkBitServlet extends HttpServlet {

    private static final Logger log = LoggerFactory.getLogger(SparkBitServlet.class);

    private Contract contract;
    private Server server;
    private JacksonSerializer serializer;

    private static long counter = 0;

    public SparkBitServlet() {
        // Serialize requests/responses as JSON using Jackson
        serializer = new JacksonSerializer();
    }

    public void init(ServletConfig config) throws ServletException {
        try {
            // SIMON: EDIT JSON FILE NAME
            // Load the contract from the IDL JSON file
            contract = Contract.load(getClass().getResourceAsStream("/sparkbit_api.json"));
            server = new Server(contract);

            // SIMON: EDIT NAME OF CLASS
            // Register our service implementation
            server.addHandler(sparkbit.class, new SparkBitJSONRPCServiceImpl());
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
        try {
            long requestID = ++counter;
            log.info("----------------------------------------------------");
            log.info("*** Request # " + requestID + " RECEIVED");
            final StopWatch stopwatch = new StopWatch();
            stopwatch.start();

            InputStream is = req.getInputStream();
            OutputStream os = resp.getOutputStream();
            resp.addHeader("Content-Type", "application/json");

            // This will deserialize the request and invoke
            // our ContactServiceImpl code based on the method and params
            // specified in the request. The result, including any
            // RpcException (if thrown), will be serialized to the OutputStream
            //    server.call(serializer, is, os);
            log.info("remote host = " + req.getRemoteHost());
            log.info("request URL = " + req.getRequestURL().toString());
            //       log.info("session ID = " + req.getRequestedSessionId());
            // We use a modified version of the above call so that we can filter 'stop' for localhost
            mycall(req.getRemoteHost(), server, serializer, is, os);

            is.close();
            os.close();

            stopwatch.stop();
            log.info("*** Request # " + requestID + " FINISHED - processing time = " + stopwatch);
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    /**
     * Reads a RpcRequest from the input stream, deserializes it, invokes the
     * matching handler method, serializes the result, and writes it to the
     * output stream.
     *
     * @param remoteHost the host of the caller
     * @param server The jetty server we will pass the call onto
     * @param ser Serializer to use to decode the request from the input stream,
     * and serialize the result to the the output stream
     * @param is InputStream to read the request from
     * @param os OutputStream to write the response to
     * @throws IOException If there is a problem reading or writing to either
     * stream, or if the request cannot be deserialized.
     */
    @SuppressWarnings("unchecked")
    public void mycall(String remoteHost, Server server, Serializer ser, InputStream is, OutputStream os)
            throws IOException {
        Object obj = null;
        try {
            obj = ser.readMapOrList(is);
        } catch (Exception e) {
            String msg = "Unable to deserialize request: " + e.getMessage();
            ser.write(new RpcResponse(null, RpcException.Error.PARSE.exc(msg)).marshal(), os);
            return;
        }
        if (obj instanceof List) {
            List list = (List) obj;
            List respList = new ArrayList();
            for (Object o : list) {
                RpcRequest rpcReq = new RpcRequest((Map) o);
                //      System.out.println(">>>> LIST CAST: (Map) o = " + (Map)o );
                respList.add(server.call(rpcReq).marshal()); // modified
            }
            ser.write(respList, os);
        } else if (obj instanceof Map) {
            // Modified: only allow stop method if remote host is actually localhost 127.0.0.1
            String method = (String) ((Map) obj).get("method");

            //       log.info("method = " + method);
            /*       Map<Object, Object> m = (Map)obj;
                   for (Map.Entry<Object, Object> entrySet : m.entrySet()) {
                  Object key = entrySet.getKey();
                  Object value = entrySet.getValue();
                  log.info(key + " = " + value);      
                   }
            */

            if (method.equals("sparkbit.stop") && !remoteHost.equals("127.0.0.1")) {
                ser.write(
                        new RpcResponse(null,
                                RpcException.Error.INVALID_REQ
                                        .exc("Invalid Request - You can only invoke stop from localhost"))
                                                .marshal(),
                        os);
            } else {
                RpcRequest rpcReq = new RpcRequest((Map) obj);
                ser.write(server.call(rpcReq).marshal(), os); // modified
            }
        } else {
            ser.write(new RpcResponse(null, RpcException.Error.INVALID_REQ.exc("Invalid Request")).marshal(), os);
        }
    }

}