public void processEvent(StateMachineImpl statemachine,
                             String event, Object object)
            throws ReentrantTransitionNotAllowed, StateMachineDefinitionException
    {
        StateMachineDefinitionImpl stateMachineDefinition = (StateMachineDefinitionImpl) statemachine.getDefinition();
        if (!stateMachineDefinition.isEvent(event))
            throw new EventNotDefinedException("Event " + event + " not defined");
        
        try {
            // More fair approach when locking resources than
            // the normal tryLock one
            lock.tryLock(0, TimeUnit.SECONDS); 
            
            if (!allowsReentrantTransitions) {
                if (inTransition) {
                    throw new ReentrantTransitionNotAllowed("Reentrance from the same thread is not allowed");
                } else {
                    inTransition = true;
                }    
            } 
        
            String source = statemachine.getCurrentState();
            String target = stateMachineDefinition.getTargetState(source, event);
            TransitionInfo tEvent = new TransitionInfo(source, event, target, object);
            
            ExitStateController exitController = stateMachineDefinition.getExitStateController(source);
            EnterStateController enterController = stateMachineDefinition.getEnterStateController(target);
            TransitionController transitionController = stateMachineDefinition.getTransitionController(source, event);
            
            if (exitController != null) {
                if (!exitController.execute(tEvent)) {
                    l.debug("The controller cancelled the event propagation");
                    return;
                }
            } 
            
            if (transitionController != null) {
                transitionController.execute(tEvent);
            }
            statemachine.setCurrentState(target);
            EventInfo result = null;
            if (enterController != null) {
                result = enterController.execute(tEvent);
            }
            
            if (result != null) {
                l.debug("#processEvent: Redirecting forced by controller to event " + result.getEvent());
                inTransition = false; 
                
                this.processEvent(statemachine, 
                                  result.getEvent(), 
                                  result.getObject());
            }
        } catch (InterruptedException ie) {
            l.warn("#processEvent: interrupted exception might not happen");
        } finally {
            inTransition = false;
            lock.unlock();
        }
    }