session.java

来自「Logica lastest SMPP API」· Java 代码 · 共 1,451 行 · 第 1/4 页

JAVA
1,451
字号
     * the command id says, that the PDU is generic nack.<br>     * If the command id is not generic nack, then we received     * incorrect pdu as the sequence numbers match, so we send generic nack     * back to the smsc.     * if the command id's match, then the <code>pdu</code> is returned.     * @param pdu the received PDU which should be a response     * @param expResponse the response we expected from smsc     * @return either the received PDU or expected response transformed to     *         generic nack.     * @see #send(Request,boolean)     */    private Response checkResponse(PDU pdu, Response expResponse)    throws ValueNotSetException, TimeoutException, IOException    {        Response response = null;        debug.write(DSESS,"checking response if it's what we expected.");        if (pdu.getCommandId() != expResponse.getCommandId()) {            debug.write(DSESS,"Got different response than expected " +                        expResponse.debugString());            if (pdu.getCommandId() == Data.GENERIC_NACK) {                // it's brutal, but it's necessary                // we transform the response object to carry generic nack                debug.write(DSESS,"Got generic nack. What could we do wrong?");                expResponse.setCommandId(Data.GENERIC_NACK);                expResponse.setCommandLength(pdu.getCommandLength());                expResponse.setCommandStatus(pdu.getCommandStatus());                expResponse.setSequenceNumber(pdu.getSequenceNumber());                response = expResponse;            } else {                debug.write(DSESS,"invalid command id - sending gnack");                safeGenericNack(Data.ESME_RINVCMDID,response.getSequenceNumber());                response = null;            }        } else {            // if the commandId is same as of the expected response's command id,            // then the pdu must be Response as well            response = (Response)pdu;        }        return response;    }    /**     * Sends a generic acknowledge with given comand status and sequence number     * and catches andy <code>SmppException</code>.     * @param commandStatus command status to report     * @param sequenceNumber to allow the other party to match the generic ack with     *                       their sent request     * @exception IOException if there is a comms error     */    private void safeGenericNack(int commandStatus, int sequenceNumber)    throws IOException    {        try {            genericNack(commandStatus,sequenceNumber);        } catch (SmppException e) {            debug.write("Ignoring unexpected SmppException caught sending generic nack.");            event.write(e, "Ignoring unexpected exception caught sending generic nack.");        }    }    /**      * Sets the state of the session.     * It's private as it's only for use by the methods of the session.     * @param state the new state of the session     * @see #checkState(int)     * @see #checkState(PDU)     * @see WrongSessionStateException     */    private void setState(int state) { this.state = state; }    /**     * Returns the current state of the session.     * It's public to allow the user to check the state of the session if necessary.     * @return the current state of the session     * @see #checkState(int)     * @see #checkState(PDU)     * @see WrongSessionStateException     */    public int getState() { return state; }    /**     * Enables checking if the session allows certain operation in the current state.     */    public void enableStateChecking() { this.stateChecking = true; }    /**     * Disables checking if the session allows certain operation in the current state.     */    public void disableStateChecking() { this.stateChecking = false; }    /**     * Checks if the session is in the state which is required by the parameter.     * If not, then exception <code>WrongSessionStateException</code> is thrown.     * Note that the states are bit values in integer, so there can be a "set"     * of states required, the session must be in one of the states required.     * The checking can be turned off, see     * <a href="#disableStateChecking()">disableStateChecking</a>.     * @param requestedState the state(s) in which the session is expected to be; if it     *                       is not, then exception is thrown     * @throws WrongSessionStateException if the session is not in the state     *         required     * @see WrongSessionStateException     */    public void checkState(int requestedState)    throws WrongSessionStateException    {        if (stateChecking) {            debug.write(DSESS,                        "checking state current=0x" + Integer.toHexString(state) +                        " requested esme=0x" + Integer.toHexString(requestedState));            if ((state & requestedState) == 0) {                throw new WrongSessionStateException(type,requestedState,state);            }        }    }    /**     * Checks if the session's state allows sending the PDU provided.     * If not, then exception <code>WrongSessionStateException</code> is thrown.     * For each state there is only a subset of PDUs which can be sent over the     * session. For example, if the session is bound as a receiver, it cannot     * submit messages, but it can send enquire link, generic nack etc.     * This method checks the PDU type (command id) aganst matrix of allowed states.     * The checking can be turned off, see     * <a href="#disableStateChecking()">disableStateChecking</a>.     * @param pdu the pdu which has to be checked if it's allowed in the current     *            state     * @throws WrongSessionStateException if the session is not in the state     *         required     * @see #checkState(int)     * @see WrongSessionStateException     */    public void checkState(PDU pdu)    throws WrongSessionStateException    {        if (stateChecking) {            Hashtable pduMatrix = getStateMatrix(type);            Integer commandIdInteger = new Integer(pdu.getCommandId());            Integer requestedStateInteger =                pduMatrix==null ? null : (Integer)pduMatrix.get(commandIdInteger);            if (requestedStateInteger != null) {                checkState(requestedStateInteger.intValue());            } else {                if (disallowUnknownPDU) {                    throw new WrongSessionStateException();                }            }        }    }    /**     * Checks if the session is in the state which is required by the parameter.     * Note that this method doesn't throw an exception rather it returns false     * if the session is not in one of the provided states.     * @param requestedState the state(s) which have to be checked     * @return if the session is in on of the provided states     * @see #checkState(int)     */    public boolean isStateAllowed(int requestedState)    {        boolean stateAllowed = true;        try {            checkState(requestedState);        } catch (WrongSessionStateException e) {            stateAllowed = false;        }        return stateAllowed;    }    /**     * Checks if the pdu provided is allowed in the current session state.     * Note that this method doesn't throw an exception rather it returns false     * if the pdu is not alloewd in the current session state.     * @param pdu the pdu which has to be checked if it's allowed in the current     *            state     * @return if the pdu is allowed to be sent in the current session state     * @see #checkState(PDU)     */    public boolean isPDUAllowed(PDU pdu)    {        boolean pduAllowed = true;        try {            checkState(pdu);        } catch (WrongSessionStateException e) {            pduAllowed = false;        }        return pduAllowed;    }    /**     * Initialises state matrices for checking if PDU is allowed in a certain session     * state.     */    static {        initialiseStateMatrix();    }    /**     * Initialise list containing which operations (PDUs) valid in which state.     * @see #checkState(PDU)     * @see #type     */    private static void initialiseStateMatrix()    {        esmeStateMatrix = new Hashtable();        addValidState(esmeStateMatrix,Data.BIND_TRANSMITTER, STATE_CLOSED);        addValidState(esmeStateMatrix,Data.BIND_TRANSMITTER_RESP, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.BIND_RECEIVER, STATE_CLOSED);        addValidState(esmeStateMatrix,Data.BIND_RECEIVER_RESP, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.BIND_TRANSCEIVER, STATE_CLOSED);        addValidState(esmeStateMatrix,Data.BIND_TRANSCEIVER_RESP, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.OUTBIND, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.UNBIND, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.UNBIND_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.SUBMIT_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.SUBMIT_SM_RESP, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.SUBMIT_MULTI, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.SUBMIT_MULTI_RESP, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.DATA_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.DATA_SM_RESP, STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.DELIVER_SM, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.DELIVER_SM_RESP, STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.QUERY_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.QUERY_SM_RESP, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.CANCEL_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.CANCEL_SM_RESP, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.REPLACE_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(esmeStateMatrix,Data.REPLACE_SM_RESP, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.ENQUIRE_LINK, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS);        addValidState(esmeStateMatrix,Data.ENQUIRE_LINK_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS);        addValidState(esmeStateMatrix,Data.ALERT_NOTIFICATION, STATE_NOT_ALLOWED);        addValidState(esmeStateMatrix,Data.GENERIC_NACK, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS);        mcStateMatrix = new Hashtable();        addValidState(mcStateMatrix,Data.BIND_TRANSMITTER, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.BIND_TRANSMITTER_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_OPENED);        addValidState(mcStateMatrix,Data.BIND_RECEIVER, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.BIND_RECEIVER_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_OPENED);        addValidState(mcStateMatrix,Data.BIND_TRANSCEIVER, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.BIND_TRANSCEIVER_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_OPENED);        addValidState(mcStateMatrix,Data.OUTBIND, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_OPENED);        addValidState(mcStateMatrix,Data.UNBIND, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.UNBIND_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.SUBMIT_SM, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.SUBMIT_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.SUBMIT_MULTI, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.SUBMIT_MULTI_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.DATA_SM, STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.DATA_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.DELIVER_SM, STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.DELIVER_SM_RESP, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.QUERY_SM, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.QUERY_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.CANCEL_SM, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.CANCEL_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.REPLACE_SM, STATE_NOT_ALLOWED);        addValidState(mcStateMatrix,Data.REPLACE_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.ENQUIRE_LINK, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS);        addValidState(mcStateMatrix,Data.ENQUIRE_LINK_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS);        addValidState(mcStateMatrix,Data.ALERT_NOTIFICATION, STATE_RECEIVER | STATE_TRANSCEIVER);        addValidState(mcStateMatrix,Data.GENERIC_NACK, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS);    }    /**     * Adds to the matrix a set of states in which can be sent a PDU with the      * provided command id.     * @param matrix the matrix to add the mapping to     * @param commandId the commandId of the PDU the mapping is created for     * @param state the state(s) in which is the PDU valid     * @see #checkState(PDU)     * @see #isStateAllowed(int)     */    private static void addValidState(Hashtable matrix, int commandId, int state)    {        matrix.put(new Integer(commandId), new Integer(state));    }    /**     * Returns the state matrix for the requested session type.     * @see #type     * @see #TYPE_ESME     * @see #TYPE_MC     * @see #initialiseStateMatrix()     */    private static Hashtable getStateMatrix(int type)    {        switch (type) {        case TYPE_ESME:            return esmeStateMatrix;        case TYPE_MC:            return mcStateMatrix;        default:            return null;        }    }    /**     * God, I would never think that to keep unbind synchronous in     * an asynchronous enviroment would be so funny. Here is the replacement     * listener which encapsulates the original listener and hunts for the      * unbind pdu. Good luck, you source code reader!<br>     * The problem is that we want to return a response from session's unbind()     * even if the session is asynchronous, i.e. all pdus from the smsc     * are passed to an implementation of <code>ServerPDUEventListener</code>     * event responses. We can't simply stop the asynchronicity     * as there can still be some responses expected, so we need a bridge     * which allows us to wait for the unbind response and still serve     * the other pdus from the smsc in asynchronous manner. Thus this     * encapsulating listener, which exactly does the thing.     */    private class UnbindServerPDUEventListener    extends SmppObject    implements ServerPDUEventListener    {        Session session;        ServerPDUEventListener origListener;        Unbind unbindReq;        UnbindResp expectedResp;        UnbindResp unbindResp = null;        public UnbindServerPDUEventListener(Session session,                                            ServerPDUEventListener origListener,                                            Unbind unbindReq)        {            this.session = session;            this.origListener = origListener;            this.unbindReq = unbindReq;            expectedResp = (UnbindResp)unbindReq.getResponse();        }        public void handleEvent(ServerPDUEvent event)        {            PDU pdu = event.getPDU();            if (pdu.equals(unbindReq)) {                synchronized (this) {                    try {                        unbindResp =                            (UnbindResp)(session.checkResponse(pdu,expectedResp));                    } catch (Exception e) {                        debug.write(DSESS,"exception handling unbind "+e);                        super.event.write(e,"exception handling unbind");                    }                    // notify as session waits for the notification                    this.notify();                }            } else {                // all other pdus are processed by the original handler,                // if any                if (origListener != null) {                    origListener.handleEvent(event);                }            }        }        public UnbindResp getUnbindResp() { return unbindResp; }    }    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?