org.xjava.gsonrpc.GsonRPC.java Source code

Java tutorial

Introduction

Here is the source code for org.xjava.gsonrpc.GsonRPC.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 xjava.org
 *
 * 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 org.xjava.gsonrpc;

import com.google.gson.*;
import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import org.xjava.gsonrpc.gson.*;
import org.xjava.gsonrpc.message.*;
import java.util.ArrayList;
import java.util.List;

/**
 * A Gson based Java library for creating and/or processing JSON-RPC 2.0 requests following the specification at
 * http://jsonrpc.org/specification
 *
 * @version 1.0
 * @author Adam Lowman
 *
 */
public class GsonRPC {
    public static final String VERSION = "2.0";

    private final Gson gson;
    private final JsonParser parser = new JsonParser();
    private final JsonRPCMessageFactory messageFactory;
    private final JsonRPCProxyFactory proxyFactory;
    private final JsonRPCRequestHandler requestHandler;

    /**
     * Constructs an instance of GsonRPC without a supplied GsonBuilder.
     */
    public GsonRPC() {
        this(new GsonBuilder());
    }

    /**
     * Constructs an instance of GsonRPC using a supplied GsonBuilder. This allows you to register any custom Gson
     * serializers/deserializers you will need (all other GsonBuilder options may be overwritten).
     *
     * <p>To initialize GsonRPC with a GsonBuilder use the following code:</p>
     *
     * <pre>{@code
     * GsonBuilder gsonBuilder = new GsonBuilder();
     * gsonBuilder.registerTypeAdapter(CustomType.class, new CustomTypeSerializer()); //OPTIONAL
     * gsonBuilder.registerTypeAdapter(CustomType.class, new CustomTypeDeserializer()); //OPTIONAL
     * GsonRPC gsonRPC = new GsonRPC(gsonBuilder);
     * }</pre>
     *
     * <p>NOTE: Be sure to use gsonBuilder.registerTypeAdapter(type, typeAdapter) to register any custom
     * serializers/deserializers you will need before passing gsonBuilder to GsonRPC.</p>
     *
     * @param gsonBuilder The GsonBuilder
     */
    public GsonRPC(GsonBuilder gsonBuilder) {
        gson = gsonBuilder.serializeNulls()
                .registerTypeAdapter(JsonRPCMessage.class, new JsonRPCMessageDeserializer())
                .registerTypeAdapter(JsonRPCRequest.class, new JsonRPCRequestSerializer())
                .registerTypeAdapter(JsonRPCResponse.class, new JsonRPCResponseSerializer())
                .registerTypeAdapter(JsonRPCErrorResponse.class, new JsonRPCErrorResponseSerializer()).create();

        messageFactory = new JsonRPCMessageFactory(gson);
        proxyFactory = new JsonRPCProxyFactory(this);
        requestHandler = new JsonRPCRequestHandler(gson, messageFactory);
    }

    /**
     * Converts a JsonRPCMessage to a JSON encoded String. An empty String will be returned if the message is null.
     *
     * @param message The JsonRPCMessage
     * @return The JSON encoded String
     */
    @NotNull
    public String toJson(@Nullable JsonRPCMessage message) {
        if (message == null)
            return "";

        return gson.toJson(message);
    }

    /**
     * Converts a JsonRPCMessage to a JsonElement. A null will be returned if the message is null.
     *
     * @param message The JsonRPCMessage
     * @return The JsonElement
     */
    @Nullable
    public JsonElement toJsonTree(@Nullable JsonRPCMessage message) {
        if (message == null)
            return null;

        return gson.toJsonTree(message);
    }

    /**
     * Converts a List of JsonRPCMessage objects to a JSON encoded String. An empty String will be returned if the List is empty is null.
     *
     * @param messages The List of JsonRPCMessage objects
     * @return The JSON encoded String
     */
    @NotNull
    public String toJson(@Nullable List<JsonRPCMessage> messages) {
        JsonElement messagesJson = toJsonTree(messages);

        if (messagesJson == null)
            return "";

        return messagesJson.toString();
    }

    /**
     * Converts a List of JsonRPCMessage objects to a JsonElement. A null will be returned if the List is empty is null.
     *
     * @param messages The List of JsonRPCMessage objects
     * @return The JsonElement
     */
    @Nullable
    public JsonElement toJsonTree(@Nullable List<JsonRPCMessage> messages) {
        if (messages.size() > 1)
            return gson.toJsonTree(messages);
        else if (messages.size() == 1)
            return gson.toJsonTree(messages.get(0));
        else
            return null;
    }

    /**
     * Gets the result of a JsonRPCResponse as an Object.
     *
     * @param response The JsonRPCResponse
     * @param resultClass The Class of the result
     * @return The result
     */
    @Nullable
    public <T> T getResult(JsonRPCResponse response, Class<T> resultClass) {
        return response.getResult(gson, resultClass);
    }

    /**
     * Gets the data of a JsonRPCErrorResponse as an Object.
     *
     * @param errorResponse The JsonRPCErrorResponse
     * @param dataClass The Class of the data
     * @return The data
     */
    @Nullable
    public <T> T getData(JsonRPCErrorResponse errorResponse, Class<T> dataClass) {
        return errorResponse.getData(gson, dataClass);
    }

    /**
     * Gets the JsonRPCMessageFactory.
     *
     * @return The JsonRPCMessageFactory
     */
    @NotNull
    public JsonRPCMessageFactory getMessageFactory() {
        return messageFactory;
    }

    /**
     * Gets the JsonRPCProxyFactory.
     *
     * @return The JsonRPCProxyFactory
     */
    @NotNull
    public JsonRPCProxyFactory getProxyFactory() {
        return proxyFactory;
    }

    /**
     * Gets the JsonRPCRequestHandler.
     *
     * @return The JsonRPCRequestHandler
     */
    @NotNull
    public JsonRPCRequestHandler getRequestHandler() {
        return requestHandler;
    }

    /**
     * Parses a JSON encoded String of GsonRPC messages.
     *
     * @param messagesString The JSON encoded String of GsonRPC messages
     * @return A List of JsonRPCMessage objects
     * @throws JsonSyntaxException A JsonSyntaxException may be thrown if Gson encounters an issue parsing messagesString
     */
    @NotNull
    public List<JsonRPCMessage> parseMessages(@Nullable String messagesString) throws JsonSyntaxException {
        return parseMessages(parser.parse(messagesString));
    }

    /**
     * Parses a JsonElement containing GsonRPC messages.
     *
     * @param messagesJson The JsonElement containing GsonRPC messages
     * @return A List of JsonRPCMessage objects
     */
    @NotNull
    public List<JsonRPCMessage> parseMessages(@Nullable JsonElement messagesJson) {
        List<JsonRPCMessage> messages = new ArrayList<>();

        if (messagesJson == null || messagesJson.isJsonNull())
            messages.add(new JsonRPCMalformedMessage());
        else {
            try {
                if (messagesJson.isJsonArray())
                    messagesJson.getAsJsonArray()
                            .forEach(messageJson -> messages.add(gson.fromJson(messageJson, JsonRPCMessage.class)));
                else
                    messages.add(gson.fromJson(messagesJson, JsonRPCMessage.class));
            } catch (Exception e) {
                messages.add(new JsonRPCMalformedMessage());
            }
        }

        return messages;
    }

    /**
     * Processes the requests contained in a JSON encoded String of GsonRPC messages.
     *
     * @param messagesString The JSON encoded String of GsonRPC messages
     * @return A List of JsonRPCMessage responses
     */
    @NotNull
    public List<JsonRPCMessage> processRequests(@Nullable String messagesString) {
        List<JsonRPCMessage> messages;

        try {
            messages = parseMessages(messagesString);
        } catch (Exception e) {
            List<JsonRPCMessage> responses = new ArrayList<>();
            responses.add(messageFactory.newErrorResponse(null, JsonRPCError.PARSE_ERROR));
            return responses;
        }

        return processRequests(messages);
    }

    /**
     * Processes the requests contained in a JsonElement.
     *
     * @param messagesJson The JsonElement
     * @return A List of JsonRPCMessage responses
     */
    @NotNull
    public List<JsonRPCMessage> processRequests(@Nullable JsonElement messagesJson) {
        return processRequests(parseMessages(messagesJson));
    }

    /**
     * Processes the requests contained in a List of JsonRPCMessage objects.
     *
     * @param messages The List of JsonRPCMessage objects
     * @return A List of JsonRPCMessage responses
     */
    @NotNull
    public List<JsonRPCMessage> processRequests(@Nullable List<JsonRPCMessage> messages) {
        List<JsonRPCMessage> responses = new ArrayList<>();

        if (messages != null) {
            messages.forEach(message -> {
                if (message.isMalformedMessage())
                    responses.add(messageFactory.newErrorResponse(message.getId(), JsonRPCError.INVALID_REQUEST));
                else if (message.isRequest()) {
                    JsonRPCRequest request = message.getAsRequest();
                    JsonRPCMessage response = requestHandler.handleRequest(request);

                    if (!request.isNotification())
                        responses.add(response);
                }
            });
        }

        return responses;
    }
}