com.clican.pluto.fsm.engine.impl.EventQueue.java Source code

Java tutorial

Introduction

Here is the source code for com.clican.pluto.fsm.engine.impl.EventQueue.java

Source

/**
 * The Clican-Pluto software suit is Copyright 2009, Clican Company and individual contributors, and is licensed under the GNU LGPL.
 *
 * @author wei.zhang
 *
 */
package com.clican.pluto.fsm.engine.impl;

import java.util.List;

import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.IntroductionInterceptor;

import com.clican.pluto.fsm.engine.EngineContext;
import com.clican.pluto.fsm.model.Session;
import com.clican.pluto.fsm.model.State;

/**
 * This class is used to implement the asynchronous event process.
 * <p>
 * It is implement by Spring AOP Framework. In the spring configuration file. We
 * shall configure which kind of interface invocation shall be interpreted by
 * this class. And then this class will use the <code>ThreadPoolExecutor</code>
 * to submit the invocation into a thread pool and return true/false
 * immediately.
 * </p>
 */
public class EventQueue implements IntroductionInterceptor {

    private final static Log log = LogFactory.getLog(EventQueue.class);

    /**
     * ?????sessionId???????
     */
    private final Object[] locks = new Object[] { new Object(), new Object(), new Object(), new Object(),
            new Object(), new Object(), new Object(), new Object(), new Object(), new Object() };

    private EngineContext engineContext;

    public boolean implementsInterface(@SuppressWarnings("rawtypes") Class clazz) {
        return true;
    }

    public void setEngineContext(EngineContext engineContext) {
        this.engineContext = engineContext;
    }

    public Object invoke(final MethodInvocation invocation) throws Throwable {
        if (log.isDebugEnabled()) {
            log.debug("Using the IntroductionInterceptor to interrupt the event ["
                    + invocation.getMethod().getName() + "]");
        }

        Object result = null;
        Object[] args = invocation.getArguments();
        Long sessionId = (Long) args[0];
        Long stateId = (Long) args[1];
        Session session = engineContext.querySession(sessionId);
        State state = engineContext.findStateById(stateId);
        if (session == null) {
            throw new RuntimeException("The session doesn't exist sessionId[" + sessionId + "]");
        }
        if (state == null) {
            throw new RuntimeException("The state doesn't exist stateId[" + stateId + "]");
        } else {
            Object lock = locks[sessionId.intValue() % 10];
            if (log.isDebugEnabled()) {
                log.debug("Using lock for session[" + sessionId + "]");
            }
            synchronized (lock) {
                try {
                    boolean executed = false;
                    List<State> activeStates = engineContext.getActiveAndPendingState(sessionId);
                    for (State activeState : activeStates) {
                        if (activeState.getId().equals(stateId)) {
                            result = invocation.proceed();
                            executed = true;
                            break;
                        }
                    }
                    if (!executed && log.isDebugEnabled()) {
                        log.debug("The event shall be ignore for current active states[" + activeStates + "]");
                    }
                    return result;
                } catch (Throwable e) {
                    throw e;
                } finally {
                    if (log.isDebugEnabled()) {
                        log.debug("Release lock for session[" + sessionId + "]");
                    }
                }
            }
        }

    }

}

// $Id$