Package org.jbpm.pvm.impl

Source Code of org.jbpm.pvm.impl.ExceptionHandlerImpl$AfterTxCompletionListener

/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jbpm.pvm.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.jbpm.PvmException;
import org.jbpm.client.Command;
import org.jbpm.client.CommandService;
import org.jbpm.env.Environment;
import org.jbpm.env.EnvironmentFactory;
import org.jbpm.env.session.DbSession;
import org.jbpm.pvm.Activity;
import org.jbpm.pvm.ExceptionHandler;
import org.jbpm.pvm.ProcessDefinition;
import org.jbpm.pvm.impl.ExecutionImpl.UserCodeType;
import org.jbpm.tx.Transaction;
import org.jbpm.util.Listener;
import org.jbpm.wire.Descriptor;

/**
* @author Tom Baeyens
*/
public class ExceptionHandlerImpl implements Serializable, ExceptionHandler {

  private static final long serialVersionUID = 1L;
  private static final Logger log = Logger.getLogger(ExceptionHandlerImpl.class.getName());

  protected long dbid;
  protected int dbversion;
  protected String exceptionClassName;
  protected boolean isTransactional;
  protected boolean isRethrowMasked;
  protected List<ObjectReference<Activity>> activityReferences;
  protected String transitionName; // mutually exclusive with nodeName
  protected String nodeName;       // mutually exclusive with transitionName
 
  // construction methods /////////////////////////////////////////////////////
 
  public ObjectReference<Activity> createActivityReference(Activity activity) {
    ObjectReference<Activity> actionReference = createActionReference();
    actionReference.set(activity);
    return actionReference;
  }

  public ObjectReference<Activity> createActivityReference(Descriptor descriptor) {
    ObjectReference<Activity> actionReference = createActionReference();
    actionReference.setDescriptor(descriptor);
    return actionReference;
  }

  public ObjectReference<Activity> createActivityReference(String expression) {
    ObjectReference<Activity> actionReference = createActionReference();
    actionReference.setExpression(expression);
    return actionReference;
  }

  public ObjectReference<Activity> createActionReference() {
    if (activityReferences==null) {
      activityReferences = new ArrayList<ObjectReference<Activity>>();
    }
    ObjectReference<Activity> actionObjectReference = new ObjectReference<Activity>();
    activityReferences.add(actionObjectReference);
    return actionObjectReference;
  }
 
  public List<Activity> getActivities() {
    if (activityReferences==null) {
      return null;
    }
    List<Activity> activities = new ArrayList<Activity>(activityReferences.size());
    for (ObjectReference<Activity> activityReference : activityReferences) {
      Activity activity = activityReference.get();
      activities.add(activity);
    }
    return activities;
  }

  // runtime behaviour methods ////////////////////////////////////////////////
 
  public boolean matches(Exception exception) {
    return matches(exception.getClass());
  }

  public boolean matches(Class<?> exceptionClass) {
    if (exceptionClass==null) {
      return false;
    }
    if ( (exceptionClassName==null)
         || (exceptionClass.getName().equals(exceptionClassName))
       ) {
      return true;
    }
    Class<?> superClass = exceptionClass.getSuperclass();
    if (superClass!=null) {
      return matches(superClass);
    }
    return false;
  }
 
  public void handle(ExecutionImpl execution, Exception exception) {
    if (isTransactional) {
      Environment environment = Environment.getCurrent();
      Transaction transaction = (environment!=null ? environment.getTransaction() : null);
      if (transaction!=null) {
        log.finest("registering exception handler to "+transaction);
        AfterTxCompletionListener afterTxCompletionListener = new AfterTxCompletionListener(
                execution,
                exception,
                environment.getEnvironmentFactory()
        );
        transaction.addListener(afterTxCompletionListener, Transaction.EVENT_AFTERCOMPLETION);
        log.finest("registering exception handler to "+transaction);
        throw new PvmException("transaction exception handler registered handler after transaction completed.  make sure this transaction is rolled back", exception);
      } else {
        throw new PvmException("no transaction present in the environment for transactional exception handler", exception);
      }
    } else {
      executeHandler(execution, exception);
    }
  }
 
  private void executeHandler(ExecutionImpl execution, Exception exception) {
    if (activityReferences!=null) {
      for (ObjectReference<Activity> actionReference: activityReferences) {
       
        Activity activity = actionReference.get();
       
        log.finest("executing "+activity+" for "+this);
        try {
          execution.userCodeType = UserCodeType.EXCEPTION_HANDLER;
          activity.execute(execution);
        } catch (RuntimeException e) {
          throw e;
        } catch (Exception e) {
          throw new PvmException("couldn't execute "+activity, e);
        } finally {
          execution.userCodeType = null;
        }
      }
    }
   
    if (transitionName!=null) {
      NodeImpl node = execution.getNode();
      if (node==null) {
        // If the execution is not positioned in a node, it must be
        // positioned in a transition.  In that case we check if the
        // transition is present on the enclosing node.
       
        // The weird way of getting checking and fetching the parent node
        // is because hibernate doesn't support instanceof.  The transition-->parent
        // relation is mapped as a ProcessElementImpl.  So we can't cast it to
        // a NodeImpl.  Ouch.
        // The workaround is to check if the parent is equal to the
        // process definition.  If that is not the case, we can be sure
        // that the parent is a node.  In that case we look up the node
        // from the process definition by name.  OuchOuchSquare :-)
       
        TransitionImpl transition = execution.getTransition();
        log.finest("no current node.  searching for transition from parent of "+transition);
        if (transition!=null) {
          ProcessDefinition processDefinition = transition.getProcessDefinition();
          ObservableElementImpl transitionParent = transition.getParent();
         
          if ( (transitionParent!=null)
               && (! transitionParent.equals(processDefinition))
             ) {
            node = (NodeImpl) processDefinition.findNode(transitionParent.getName());
          }
        }
      }
     
      if (node!=null) {
        TransitionImpl transition = node.findOutgoingTransition(transitionName);
        if (transition!=null) {
          log.finest(toString()+" takes transition "+transitionName);
          execution.setTransition(transition);
          execution.performAtomicOperationSync(ExecutionImpl.TAKE_TRANSITION);
        } else {
          log.warning(toString()+" couldn't find transition "+transitionName+" on "+node);
        }
      } else {
        log.warning(toString()+" couldn't find current node to take transition "+transitionName);
      }

    } else if (nodeName!=null) {
      // execute child node
      NodeImpl node = execution.getNode();
      NodeImpl childNode = ( node!=null ? node.getNode(nodeName) : null );
      if (childNode!=null) {
        log.finest(toString()+" takes transition "+transitionName);
        execution.performAtomicOperationSync(new MoveToChildNodeOp(childNode));
      } else {
        log.warning(toString()+" couldn't find child node "+nodeName);
      }
    }
  }

  private class AfterTxCompletionListener implements Listener, Command {

    private static final long serialVersionUID = 1L;
   
    protected ExecutionImpl execution;
    protected Exception exception;
    protected EnvironmentFactory environmentFactory;

    public AfterTxCompletionListener(ExecutionImpl execution, Exception exception, EnvironmentFactory environmentFactory) {
      this.execution = execution;
      this.exception = exception;
      this.environmentFactory = environmentFactory;
    }

    public void event(Object source, String eventName, Object info) {
      Transaction transaction = (Transaction) source;
      if (! transaction.isRolledBack()) {
        log.warning("no rollback after transactional exception handler. did you forget to rollback the transaction ?");
      }
      CommandService commandService = environmentFactory.get(CommandService.class);
      if (commandService==null) {
        throw new PvmException("environment factory doesn't have a command service");
      }
      commandService.execute(this);
    }
    public Object execute(Environment environment) {
      // reload the execution
      DbSession dbSession = environment.get(DbSession.class);
      if (dbSession==null) {
        throw new PvmException("no "+DbSession.class.getName()+" available in the environment for reloading the execution");
      }
      execution = dbSession.get(ExecutionImpl.class, execution.getDbid());
      executeHandler(execution, exception);
      return null;
    }
  }

  public static void rethrow(Exception exception, String prefixMessage) {
    log.finest("rethrowing "+exception);
    if (exception instanceof RuntimeException) {
      throw (RuntimeException) exception;
    } else {
      throw new PvmException(prefixMessage+": "+exception.getMessage(), exception);
    }
  }

  public String toString() {
    return (exceptionClassName!=null ? "exception-handler("+exceptionClassName+")" : "exception-handler");
  }

  // getters and setters //////////////////////////////////////////////////////

  public long getDbid() {
    return dbid;
  }
  public String getExceptionClassName() {
    return exceptionClassName;
  }
  public void setExceptionClassName(String exceptionClassName) {
    this.exceptionClassName = exceptionClassName;
  }
  public boolean isTransactional() {
    return isTransactional;
  }
  public void setTransactional(boolean isTransactional) {
    this.isTransactional = isTransactional;
  }
  public String getTransitionName() {
    return transitionName;
  }
  public void setTransitionName(String transitionName) {
    this.transitionName = transitionName;
  }
  public String getNodeName() {
    return nodeName;
  }
  public void setNodeName(String nodeName) {
    this.nodeName = nodeName;
  }
  public boolean isRethrowMasked() {
    return isRethrowMasked;
  }
  public void setRethrowMasked(boolean isRethrowMasked) {
    this.isRethrowMasked = isRethrowMasked;
  }
  public List<ObjectReference<Activity>> getActivityReferences() {
    return activityReferences;
  }
  public void setActivityReferences(List<ObjectReference<Activity>> activityReferences) {
    this.activityReferences = activityReferences;
  }
}
TOP

Related Classes of org.jbpm.pvm.impl.ExceptionHandlerImpl$AfterTxCompletionListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.