All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.smartdevicelink.managers.lifecycle.RpcConverter Maven / Gradle / Ivy

/*
 * Copyright (c) 2019 Livio, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 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.
 *
 * Neither the name of the Livio Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
 */
package com.smartdevicelink.managers.lifecycle;

import com.smartdevicelink.marshal.JsonRPCMarshaller;
import com.smartdevicelink.protocol.ProtocolMessage;
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCMessage;
import com.smartdevicelink.proxy.RPCStruct;
import com.smartdevicelink.util.DebugTool;
import com.smartdevicelink.util.Version;

import java.util.Hashtable;
import java.util.Set;

/**
 * Converts a protocol message into an RPC.
 * Built to reduce boiler plate code for each RPC added.
 */
public class RpcConverter {

    private static final String TAG = "RpcConverter";

    private static final String RPC_PACKAGE = "com.smartdevicelink.proxy.rpc.";
    private static final String RESPONSE_KEY = "Response";
    private static final String GENERIC_RESPONSE_STRING = FunctionID.GENERIC_RESPONSE.toString();

    /**
     * Extracts the RPC out of the payload of a given protocol message
     *
     * @param message         protocolMessage that has the RPC in the payload
     * @param protocolVersion RPC spec version that should be used to create RPC
     * @return the extracted RPC
     */
    public static RPCMessage extractRpc(ProtocolMessage message, Version protocolVersion) {
        Hashtable tempTable = convertProtocolMessage(message, protocolVersion);
        if (tempTable != null) {
            try {
                return convertTableToRpc(tempTable);
            } catch (Exception e) {
                DebugTool.logError(TAG, "Error converting RPC", e);
            }
        }
        return null;
    }

    static Hashtable convertProtocolMessage(ProtocolMessage message, Version protocolVersion) {
        Hashtable hash = new Hashtable<>();
        if (protocolVersion != null && protocolVersion.getMajor() > 1) {

            Hashtable hashTemp = new Hashtable<>();
            hashTemp.put(RPCMessage.KEY_CORRELATION_ID, message.getCorrID());
            if (message.getJsonSize() > 0) {
                final Hashtable mHash = JsonRPCMarshaller.unmarshall(message.getData());
                if (mHash != null) {
                    hashTemp.put(RPCMessage.KEY_PARAMETERS, mHash);
                }
            }

            String functionName = FunctionID.getFunctionName(message.getFunctionID());

            if (functionName != null) {
                hashTemp.put(RPCMessage.KEY_FUNCTION_NAME, functionName);
            } else {
                DebugTool.logWarning(TAG, "Dispatch Incoming Message - function name is null unknown RPC.  FunctionId: " + message.getFunctionID());
                return null;
            }

            if (message.getRPCType() == 0x00) {
                hash.put(RPCMessage.KEY_REQUEST, hashTemp);
            } else if (message.getRPCType() == 0x01) {
                hash.put(RPCMessage.KEY_RESPONSE, hashTemp);
            } else if (message.getRPCType() == 0x02) {
                hash.put(RPCMessage.KEY_NOTIFICATION, hashTemp);
            }

            if (message.getBulkData() != null)
                hash.put(RPCStruct.KEY_BULK_DATA, message.getBulkData());
            if (message.getPayloadProtected()) hash.put(RPCStruct.KEY_PROTECTED, true);

            return hash;
        } else {
            return JsonRPCMarshaller.unmarshall(message.getData());
        }
    }


    public static RPCMessage convertTableToRpc(Hashtable rpcHashTable) {

        Hashtable params;
        if (rpcHashTable.containsKey((RPCMessage.KEY_RESPONSE))) {
            params = (Hashtable) rpcHashTable.get((RPCMessage.KEY_RESPONSE));
        } else if (rpcHashTable.containsKey((RPCMessage.KEY_NOTIFICATION))) {
            params = (Hashtable) rpcHashTable.get((RPCMessage.KEY_NOTIFICATION));
        } else if (rpcHashTable.containsKey((RPCMessage.KEY_REQUEST))) {
            params = (Hashtable) rpcHashTable.get((RPCMessage.KEY_REQUEST));
        } else {
            DebugTool.logError(TAG, " Corrupted RPC table.");
            return null;
        }

        if (DebugTool.isDebugEnabled()) {
            if (params != null) {
                Set keySet = params.keySet();
                for (String key : keySet) {
                    DebugTool.logInfo(TAG, key + "  -  " + params.get(key));
                }
            }
        }

        if (params != null && params.containsKey(RPCMessage.KEY_FUNCTION_NAME)) {
            StringBuilder rpcClassName = new StringBuilder();
            String functionName = (String) params.get(RPCMessage.KEY_FUNCTION_NAME);
            if (FunctionID.SHOW_CONSTANT_TBT.toString().equals(functionName)) {
                functionName = "ShowConstantTbt";
            } else if (FunctionID.ON_ENCODED_SYNC_P_DATA.toString().equals(functionName)
                    || FunctionID.ON_SYNC_P_DATA.toString().equals(functionName)) {
                //This will create an OnSystemRequest instance, but the function id in the RPC
                //will remain FunctionID.ON_ENCODED_SYNC_P_DATA or FunctionID.ON_SYNC_P_DATA.
                //This is desired behavior.
                functionName = FunctionID.ON_SYSTEM_REQUEST.toString();
            } else if (FunctionID.ENCODED_SYNC_P_DATA.toString().equals(functionName)
                    || FunctionID.SYNC_P_DATA.toString().equals(functionName)) {
                //This will create an SystemRequest instance, but the function id in the RPC
                //will remain FunctionID.ENCODED_SYNC_P_DATA or FunctionID.SYNC_P_DATA.
                //This is desired behavior.
                functionName = FunctionID.SYSTEM_REQUEST.toString();
            }

            rpcClassName.append(RPC_PACKAGE);
            rpcClassName.append(functionName);

            if (rpcHashTable.containsKey(RPCMessage.KEY_RESPONSE)
                    && !GENERIC_RESPONSE_STRING.equals(functionName)) {
                rpcClassName.append(RESPONSE_KEY);
            }

            DebugTool.logInfo(TAG, " Attempting to create " + rpcClassName.toString());
            try {
                Class rpcClass = Class.forName(rpcClassName.toString());
                if (rpcClass != null) {
                    java.lang.reflect.Constructor rpcConstructor = rpcClass.getConstructor(Hashtable.class);
                    if (rpcConstructor != null) {
                        return (RPCMessage) rpcConstructor.newInstance(rpcHashTable);
                    }
                } else {
                    DebugTool.logError(TAG, " Java class cannot be found for " + rpcClassName.toString());
                }
            } catch (Exception e) {
                DebugTool.logError(TAG, "RPCConverter was unable to process RPC", e);
            }
        } else {
            DebugTool.logError(TAG, " Unable to parse into RPC");
        }

        return null;
    }


}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy