org.opendaylight.vtn.javaapi.ipc.IpcRequestProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.vtn.javaapi.ipc.IpcRequestProcessor.java

Source

/*
 * Copyright (c) 2012-2014 NEC Corporation
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this
 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.vtn.javaapi.ipc;

import java.lang.reflect.Method;
import java.util.List;

import com.google.gson.JsonObject;
import org.opendaylight.vtn.core.ipc.ClientSession;
import org.opendaylight.vtn.core.ipc.IpcDataUnit;
import org.opendaylight.vtn.core.ipc.IpcException;
import org.opendaylight.vtn.core.ipc.IpcStruct;
import org.opendaylight.vtn.core.ipc.IpcUint32;
import org.opendaylight.vtn.core.util.Logger;
import org.opendaylight.vtn.javaapi.constants.VtnServiceConsts;
import org.opendaylight.vtn.javaapi.constants.VtnServiceJsonConsts;
import org.opendaylight.vtn.javaapi.exception.VtnServiceException;
import org.opendaylight.vtn.javaapi.exception.VtnServiceExceptionHandler;
import org.opendaylight.vtn.javaapi.init.VtnServiceConfiguration;
import org.opendaylight.vtn.javaapi.init.VtnServiceInitManager;
import org.opendaylight.vtn.javaapi.ipc.conversion.IpcDataUnitWrapper;
import org.opendaylight.vtn.javaapi.ipc.enums.IpcRequestPacketEnum;
import org.opendaylight.vtn.javaapi.ipc.enums.UncCommonEnum;
import org.opendaylight.vtn.javaapi.ipc.enums.UncCommonEnum.UncResultCode;
import org.opendaylight.vtn.javaapi.ipc.enums.UncDataType;
import org.opendaylight.vtn.javaapi.ipc.enums.UncErrorBean;
import org.opendaylight.vtn.javaapi.ipc.enums.UncIpcErrorCode;
import org.opendaylight.vtn.javaapi.ipc.enums.UncJavaAPIErrorCode;
import org.opendaylight.vtn.javaapi.ipc.enums.UncKeyTypeEnum;
import org.opendaylight.vtn.javaapi.ipc.enums.UncOperationEnum;
import org.opendaylight.vtn.javaapi.ipc.enums.UncOption2Enum;
import org.opendaylight.vtn.javaapi.ipc.enums.UncStructEnum;
import org.opendaylight.vtn.javaapi.util.VtnServiceUtil;

/**
 * The Class IpcRequestProcessor. Interacts with IPC classes to send the request
 * and receive the response
 */
public class IpcRequestProcessor {

    private static final Logger LOG = Logger.getLogger(IpcRequestProcessor.class.getName());

    private transient final IpcRequestPacket requestPacket;
    private transient final VtnServiceExceptionHandler exceptionHandler;
    private transient IpcStructFactory stuctGenerator;
    private transient final ClientSession session;
    private JsonObject errorJson;
    private boolean noSuchInstanceFlag;
    private String requestPacketEnumName = null;
    private String serviceName = null;
    private int serviceId;

    /**
     * Instantiates a new ipc request processor.
     * 
     * @param session
     *            the session
     * @param sessionId
     *            the session id
     * @param configId
     *            the config id
     * @param exceptionHandler
     *            the exception handler
     */
    public IpcRequestProcessor(final ClientSession session, final long sessionId, final long configId,
            final VtnServiceExceptionHandler exceptionHandler) {
        LOG.trace("Start IpcRequestProcessor#IpcRequestProcessor()");
        noSuchInstanceFlag = false;
        this.session = session;
        this.requestPacket = new IpcRequestPacket();
        this.exceptionHandler = exceptionHandler;
        // set the session id and config id to IPC request packet
        LOG.debug("session id : " + sessionId);
        requestPacket.setSessionId(new IpcUint32(sessionId));
        LOG.debug("config id : " + configId);
        requestPacket.setConfigId(new IpcUint32(configId));
        LOG.trace("Complete IpcRequestProcessor#IpcRequestProcessor()");
    }

    /**
     * Set sessions related service information This interface is required to be
     * invoked, if session reset is required
     * 
     * @return the request packet
     */
    public final void setServiceInfo(final String serviceName, final int serviceId) {
        this.serviceName = serviceName;
        this.serviceId = serviceId;
    }

    /**
     * Gets the request packet.
     * 
     * @return the request packet
     */
    public final IpcRequestPacket getRequestPacket() {
        LOG.trace("Return from IpcRequestProcessor#getRequestPacket()");
        return requestPacket;
    }

    /**
     * Creates the ipc request packet.
     * 
     * @param requestPacketEnum
     *            the request packet enum
     * @param requestBody
     *            the request body
     * @param uriParameters
     *            the uri parameters
     * @throws VtnServiceException
     *             the vtn service exception
     */
    public final void createIpcRequestPacket(final IpcRequestPacketEnum requestPacketEnum,
            final JsonObject requestBody, final List<String> uriParameters) throws VtnServiceException {

        LOG.trace("Start IpcRequestProcessor#createIpcRequestPacket()");

        if (requestPacketEnum != null) {
            // set the values to IPC request packet, that has been received by
            // request packet enum
            requestPacket.setOperation(new IpcUint32(requestPacketEnum.getOperation()));
            // set max repetition as zero
            requestPacket.setMaxRepCount(new IpcUint32(0));
            requestPacket.setOption1(new IpcUint32(requestPacketEnum.getOption1()));
            requestPacket.setOption2(new IpcUint32(requestPacketEnum.getOption2()));
            requestPacket.setDataType(new IpcUint32(requestPacketEnum.getDataType()));
            requestPacket.setKeyType(new IpcUint32(requestPacketEnum.getKeyType()));
            // set the key structure
            requestPacket
                    .setKeyStruct(getIpcStructure(requestPacketEnum.getKeyStruct(), requestBody, uriParameters));
            // set the value structure
            requestPacket
                    .setValStruct(getIpcStructure(requestPacketEnum.getValStruct(), requestBody, uriParameters));

            /*
             * update request packet as per the received json parameters used in
             * read like operations
             */
            if (requestPacketEnum.getOperation() == UncOperationEnum.UNC_OP_READ.ordinal()) {
                setCommonReadParams(requestBody);
            } else {
                LOG.debug("No need to update the parameters of request packet");
            }
            requestPacketEnumName = requestPacketEnum.name();
        } else {
            LOG.warning("Request Packet Enum cannot be null");
        }
        LOG.trace("Complete IpcRequestProcessor#createIpcRequestPacket()");
    }

    /**
     * Update IPC request packet for READ operation according to JSON parameters
     * 
     * @param requestBody
     * @throws VtnServiceException
     */
    private void setCommonReadParams(final JsonObject requestBody) throws VtnServiceException {

        LOG.trace("Start IpcRequestProcessor#setCommonReadParams()");
        /*
         * Update the value of max repetition count, if not received in the
         * request then set the default value from configuration file
         */
        setMaxRepCount(requestBody);

        /*
         * Update the data type value received in the request json
         */
        setDataType(requestBody);

        /*
         * No need to update the OP type in common part Most of the API contains
         * the OP type as normal For exception APIs OP type must set in
         * corresponding resource classes
         */
        setOperationType(requestBody);
        LOG.trace("Complete IpcRequestProcessor#setCommonReadParams()");
    }

    /**
     * Update operation type according to "op" parameter's value
     * 
     * @param requestBody
     */
    private void setOperationType(final JsonObject requestBody) {

        LOG.trace("Start IpcRequestProcessor#setOperationType()");
        // check if "op" parameter is received
        if (requestBody.has(VtnServiceJsonConsts.OP)) {
            // get value of "op" parameter
            final String opType = requestBody.getAsJsonPrimitive(VtnServiceJsonConsts.OP).getAsString().trim();
            // set the op type to request packet
            if (opType.equalsIgnoreCase(VtnServiceJsonConsts.COUNT)) {
                /*
                 * No need to update option1 value on the basis of "op"
                 * parameter's value requestPacket.setOption1(new
                 * IpcUint32(UncOption1Enum.UNC_OPT1_COUNT.ordinal()));
                 */
                // operation type is read_sibling_begin_count, if op is count
                requestPacket.setOperation(new IpcUint32(UncOperationEnum.UNC_OP_READ_SIBLING_COUNT.ordinal()));
            } else if (opType.equalsIgnoreCase(VtnServiceJsonConsts.DETAIL)
                    || opType.equalsIgnoreCase(VtnServiceJsonConsts.NORMAL)
                    || opType.equalsIgnoreCase(VtnServiceJsonConsts.INFO)) {
                /*
                 * No need to update option1 value on the basis of "op"
                 * parameter's value requestPacket.setOption1(new
                 * IpcUint32(UncOption1Enum.UNC_OPT1_COUNT.ordinal()));
                 */

                /*
                 * update the operation from read to read_sibling or
                 * read_sinling_index
                 */
                if (requestBody.has(VtnServiceJsonConsts.INDEX)) {
                    requestPacket.setOperation(new IpcUint32(UncOperationEnum.UNC_OP_READ_SIBLING.ordinal()));
                } else {
                    // operation type is read_sibling_begin, if index is null
                    requestPacket.setOperation(new IpcUint32(UncOperationEnum.UNC_OP_READ_SIBLING_BEGIN.ordinal()));
                }
            } else {
                LOG.debug("No need to change the operation type i.e. READ");
            }
        }
        LOG.trace("Complete IpcRequestProcessor#setOperationType()");
    }

    /**
     * Update data type according to "targetdb" parameter's value
     * 
     * @param requestBody
     */
    private void setDataType(final JsonObject requestBody) {

        LOG.trace("Start IpcRequestProcessor#setDataType()");
        // check if "targetdb" parameter is received
        if (requestBody.has(VtnServiceJsonConsts.TARGETDB)) {
            // get value of "targetdb" parameter
            final String dataType = requestBody.getAsJsonPrimitive(VtnServiceJsonConsts.TARGETDB).getAsString()
                    .trim();
            // set the data type to request packet
            if (dataType.equalsIgnoreCase(VtnServiceJsonConsts.STARTUP)) {
                requestPacket.setDataType(new IpcUint32(UncDataType.UNC_DT_STARTUP.ordinal()));
            } else if (dataType.equalsIgnoreCase(VtnServiceJsonConsts.RUNNING)) {
                requestPacket.setDataType(new IpcUint32(UncDataType.UNC_DT_RUNNING.ordinal()));
            } else if (dataType.equalsIgnoreCase(VtnServiceJsonConsts.CANDIDATE)) {
                requestPacket.setDataType(new IpcUint32(UncDataType.UNC_DT_CANDIDATE.ordinal()));
            } else {
                LOG.warning("No need to update data type from state to another one");
            }
        } else {
            LOG.debug("No need to do anything");
        }
        LOG.trace("Complete IpcRequestProcessor#setDataType()");
    }

    /**
     * Update max repetition type according to "max_repetition" parameter's
     * value
     * 
     * @param requestBody
     * @throws VtnServiceException
     */
    private void setMaxRepCount(final JsonObject requestBody) throws VtnServiceException {

        LOG.trace("Start IpcRequestProcessor#setMaxRepCount()");
        // check id "max_repetition" parameter is received
        if (requestBody.has(VtnServiceJsonConsts.MAX) && requestBody.getAsJsonPrimitive(VtnServiceJsonConsts.MAX)
                .getAsLong() < VtnServiceConsts.MAX_REP_COUNT) {
            // set the value of "max_repetition" parameter to IPC request
            // parameter
            requestPacket.setMaxRepCount(
                    new IpcUint32(requestBody.getAsJsonPrimitive(VtnServiceJsonConsts.MAX).getAsString()));
        } else {
            requestPacket.setMaxRepCount(new IpcUint32(VtnServiceConsts.MAX_REP_COUNT));
        }
        LOG.trace("Complete IpcRequestProcessor#setMaxRepCount()");
    }

    /**
     * Gets the ipc response packet, after checking the result code
     * 
     * @param methodype
     * 
     * @return the ipc response packet
     * @throws VtnServiceException
     *             the vtn service exception
     */
    public final IpcDataUnit[] getIpcResponsePacket() throws VtnServiceException {

        LOG.trace("Start IpcRequestProcessor#getIpcResponsePacket()");
        IpcDataUnit[] ipcDataUnits = null;
        try {
            // No response required to be retrieve for NO_SUCH_INSTANCE cases
            if (noSuchInstanceFlag) {
                ipcDataUnits = new IpcDataUnit[0];
                noSuchInstanceFlag = false;
                LOG.debug("Response array with size zero");
            } else {
                // in case of result code is success the create response packet
                // with key and value structures
                final int size = session.getResponseCount();
                ipcDataUnits = new IpcDataUnit[size - VtnServiceConsts.IPC_RESUL_CODE_INDEX - 1];
                // iterate response one by one after Result Code
                int index = 0;
                for (int i = VtnServiceConsts.IPC_RESUL_CODE_INDEX + 1; i < size; i++) {
                    ipcDataUnits[index++] = session.getResponse(i);
                    LOG.debug("Response at index " + i + " " + session.getResponse(i));
                }
            }
        } catch (final IpcException e) {
            exceptionHandler.raise(
                    Thread.currentThread().getStackTrace()[1].getClassName() + VtnServiceConsts.HYPHEN
                            + Thread.currentThread().getStackTrace()[1].getMethodName(),
                    UncJavaAPIErrorCode.IPC_OP_ERROR.getErrorCode(),
                    UncJavaAPIErrorCode.IPC_OP_ERROR.getErrorMessage(), e);
        }
        LOG.trace("Complete IpcRequestProcessor#getIpcResponsePacket()");
        return ipcDataUnits;
    }

    /**
     * Create Json error object on the basis of result code if result code is
     * null then do nothing
     * 
     * @param resultCode
     */
    private void createErrorJson(final Integer resultCode) {
        // error code and message required to be update after confirmation
        final JsonObject error = new JsonObject();

        final int keyType = requestPacket.getKeyType().intValue();

        /*
         * Check the error code either for logical or physical APIs
         */
        if (keyType >= UncCommonEnum.MIN_LOGICAL_KEYTYPE && keyType <= UncCommonEnum.MAX_LOGICAL_KEYTYPE) {
            // set the physical error code and error message
            final UncErrorBean errorEnum = UncIpcErrorCode.getLogicalError(resultCode);
            error.addProperty(VtnServiceJsonConsts.CODE, errorEnum.getErrorCode());
            error.addProperty(VtnServiceJsonConsts.MSG, errorEnum.getJavaAPIErrorMessage());
            LOG.error(errorEnum.getErrorCodeKey() + VtnServiceConsts.SPACE + errorEnum.getErrorCode()
                    + VtnServiceConsts.SPACE + errorEnum.getJavaAPIErrorMessage() + VtnServiceConsts.SPACE
                    + errorEnum.getSouthboundErrorMessage());
        } else if (keyType >= UncCommonEnum.MIN_PHYSICAL_KEYTYPE && keyType <= UncCommonEnum.MAX_PHYSICAL_KEYTYPE) {
            // set the logical error code and error message
            final UncErrorBean errorEnum = UncIpcErrorCode.getPhysicalError(resultCode);
            error.addProperty(VtnServiceJsonConsts.CODE, errorEnum.getErrorCode());
            error.addProperty(VtnServiceJsonConsts.MSG, errorEnum.getJavaAPIErrorMessage());
            LOG.error(errorEnum.getErrorCodeKey() + VtnServiceConsts.SPACE + errorEnum.getErrorCode()
                    + VtnServiceConsts.SPACE + errorEnum.getJavaAPIErrorMessage() + VtnServiceConsts.SPACE
                    + errorEnum.getSouthboundErrorMessage());
        } else {
            error.addProperty(VtnServiceJsonConsts.CODE, UncCommonEnum.UncResultCode.UNC_SERVER_ERROR.getValue());
            error.addProperty(VtnServiceJsonConsts.MSG, UncCommonEnum.UncResultCode.UNC_SERVER_ERROR.getMessage());
            LOG.warning("Invalid Error Code Returned from IPC Server!");
        }

        errorJson = new JsonObject();
        errorJson.add(VtnServiceJsonConsts.ERROR, error);
    }

    public final JsonObject getErrorJson() {
        return errorJson;
    }

    /**
     * Gets the exception handler.
     * 
     * @return the exception handler
     */
    public final VtnServiceExceptionHandler getExceptionHandler() {
        LOG.trace("Return from IpcRequestProcessor#getExceptionHandler()");
        return exceptionHandler;
    }

    /**
     * Gets the ipc structure.
     * 
     * @param structName
     *            the struct name
     * @param requestBody
     *            the request body
     * @param uriParameters
     *            the uri parameters
     * @return the ipc structure
     * @throws VtnServiceException
     *             the vtn service exception
     */
    private IpcStruct getIpcStructure(final String structName, final JsonObject requestBody,
            final List<String> uriParameters) throws VtnServiceException {

        LOG.trace("Start IpcRequestProcessor#getIpcStructure()");
        IpcStruct ipcStruct = null;

        if (VtnServiceUtil.isValidString(structName) && !UncStructEnum.NONE.name().equalsIgnoreCase(structName)) {
            // create one structure generator
            if (stuctGenerator == null) {
                stuctGenerator = new IpcStructFactory();
            }

            try {
                Method method;
                final Class<IpcStructFactory> sourceClass = IpcStructFactory.class;
                // get the method name to get the IpcStruct object for given key
                method = sourceClass.getMethod(
                        VtnServiceConsts.STRUCT_METHOD_PREFIX + structName + VtnServiceConsts.STRUCT_METHOD_POSTFIX,
                        JsonObject.class, List.class);
                // get IpcStruct object
                ipcStruct = (IpcStruct) method.invoke(stuctGenerator, requestBody, uriParameters);
            } catch (final Exception e) {
                exceptionHandler.raise(
                        Thread.currentThread().getStackTrace()[1].getClassName() + VtnServiceConsts.HYPHEN
                                + Thread.currentThread().getStackTrace()[1].getMethodName(),
                        UncJavaAPIErrorCode.INTERNAL_ERROR.getErrorCode(),
                        UncJavaAPIErrorCode.INTERNAL_ERROR.getErrorMessage(), e);
            }
        }
        LOG.trace("Complete IpcRequestProcessor#getIpcStructure()");
        return ipcStruct;
    }

    /**
     * Process ipc request.
     * 
     * @return the int
     * @throws VtnServiceException
     *             the vtn service exception
     */
    public final int processIpcRequest() throws VtnServiceException {

        LOG.trace("Start IpcRequestProcessor#processIpcRequest()");
        int status = ClientSession.RESP_FATAL;
        /*
         * set IPC data to session object
         */
        try {
            if (serviceName != null) {
                LOG.debug("session reset execution");
                session.reset(serviceName, serviceId);
            }
            // add IPC request packet values to session for the further
            // processing at lower layer
            LOG.debug("Session id : " + requestPacket.getSessionId());
            session.addOutput(requestPacket.getSessionId());
            LOG.debug("Config id : " + requestPacket.getConfigId());
            session.addOutput(requestPacket.getConfigId());
            LOG.debug("Operation : " + requestPacket.getOperation());
            session.addOutput(requestPacket.getOperation());
            LOG.debug("Max. Repetition Count : " + requestPacket.getMaxRepCount());
            session.addOutput(requestPacket.getMaxRepCount());
            LOG.debug("Option1 : " + requestPacket.getOption1());
            session.addOutput(requestPacket.getOption1());
            LOG.debug("Option2 : " + requestPacket.getOption2());
            session.addOutput(requestPacket.getOption2());
            LOG.debug("Data Type : " + requestPacket.getDataType());
            session.addOutput(requestPacket.getDataType());
            LOG.debug("Key Type : " + requestPacket.getKeyType());
            session.addOutput(requestPacket.getKeyType());
            LOG.debug("Key Structure : " + requestPacket.getKeyStruct());
            session.addOutput(requestPacket.getKeyStruct());

            // add value structure, if required
            if (requestPacket.getValStruct() != null) {
                LOG.debug("Value Structure: " + requestPacket.getValStruct());
                session.addOutput(requestPacket.getValStruct());
            }

            /*
             * For exceptional cases, IpcDataUnit data will be set before
             * invoking the request
             */
            if (requestPacket.getExtraDataUnits() != null && requestPacket.getExtraDataUnits().length != 0) {
                for (final IpcDataUnit ipcDataUnit : requestPacket.getExtraDataUnits()) {
                    LOG.debug("extra units : " + ipcDataUnit);
                    session.addOutput(ipcDataUnit);
                }
            }

            // execute the operation
            status = session.invoke();
            if (status == ClientSession.RESP_FATAL) {
                throw new IpcException("Server Response Failure");
            } else {
                final String resultCode = IpcDataUnitWrapper
                        .getIpcDataUnitValue(session.getResponse(VtnServiceConsts.IPC_RESUL_CODE_INDEX));
                LOG.debug("Result code received: " + resultCode);
                final int keyType = requestPacket.getKeyType().intValue();

                if (requestPacket.getOperation().intValue() == UncOperationEnum.UNC_OP_READ_SIBLING_BEGIN.ordinal()
                        || requestPacket.getOperation().intValue() == UncOperationEnum.UNC_OP_READ_SIBLING.ordinal()
                        || requestPacket.getOperation().intValue() == UncOperationEnum.UNC_OP_READ_SIBLING_COUNT
                                .ordinal()
                        || VtnServiceInitManager.getReadAsList().contains(requestPacketEnumName)
                        || VtnServiceInitManager.getMultiCallList().contains(requestPacketEnumName)) {
                    if (keyType >= UncCommonEnum.MIN_LOGICAL_KEYTYPE && keyType <= UncCommonEnum.MAX_LOGICAL_KEYTYPE
                            && Integer.parseInt(resultCode) == VtnServiceConsts.UPLL_RC_ERR_NO_SUCH_INSTANCE) {
                        noSuchInstanceFlag = true;
                        LOG.debug("No such instance case for UPLL");
                    } else if (keyType >= UncCommonEnum.MIN_PHYSICAL_KEYTYPE
                            && keyType <= UncCommonEnum.MAX_PHYSICAL_KEYTYPE
                            && Integer.parseInt(resultCode) == VtnServiceConsts.UPPL_RC_ERR_NO_SUCH_INSTANCE) {
                        noSuchInstanceFlag = true;
                        LOG.debug("No such instance case for UPPL");
                    } else {
                        LOG.debug(" Either Key Type does not exists or operation is not success");
                    }

                    if (VtnServiceInitManager.getMultiCallList().contains(requestPacketEnumName)
                            && requestPacket.getOperation().intValue() == UncOperationEnum.UNC_OP_READ.ordinal()) {
                        if (requestPacket.getOption2().compareTo(IpcDataUnitWrapper
                                .setIpcUint32Value((UncOption2Enum.UNC_OPT2_NEIGHBOR.ordinal()))) != 0) {
                            noSuchInstanceFlag = false;
                        }
                    }
                } else if (keyType == UncKeyTypeEnum.UNC_KT_PORT.getValue()
                        && Integer.parseInt(resultCode) == VtnServiceConsts.UPPL_RC_ERR_NO_SUCH_INSTANCE) {
                    noSuchInstanceFlag = true;
                }

                // if return code is not success, then create the error Json for
                // received result code
                if (null == resultCode || UncIpcErrorCode.RC_SUCCESS != Integer.parseInt(resultCode)) {
                    if (noSuchInstanceFlag) {
                        status = UncResultCode.UNC_SUCCESS.getValue();
                    } else {
                        createErrorJson(Integer.parseInt(resultCode));
                        throw new IpcException("Server Response Failure");
                    }
                } else {
                    status = UncResultCode.UNC_SUCCESS.getValue();
                }
            }
        } catch (final IpcException e) {
            exceptionHandler.raise(
                    Thread.currentThread().getStackTrace()[1].getClassName() + VtnServiceConsts.HYPHEN
                            + Thread.currentThread().getStackTrace()[1].getMethodName(),
                    UncJavaAPIErrorCode.IPC_OP_ERROR.getErrorCode(),
                    UncJavaAPIErrorCode.IPC_OP_ERROR.getErrorMessage(), e);
        }
        LOG.trace("Complete IpcRequestProcessor#processIpcRequest()");
        return status;
    }
}