Package org.aperteworkflow.ext.activiti

Source Code of org.aperteworkflow.ext.activiti.ActivitiContextFactoryImpl

package org.aperteworkflow.ext.activiti;

import com.thoughtworks.xstream.XStream;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.impl.db.IbatisVariableTypeHandler;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.util.IoUtil;
import org.activiti.engine.impl.util.ReflectUtil;
import org.activiti.engine.impl.variable.VariableType;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.aperteworkflow.ext.activiti.wrappers.DataSourceWrapper;
import org.hibernate.Session;
import pl.net.bluesoft.rnd.processtool.ProcessToolContext;
import pl.net.bluesoft.rnd.processtool.ProcessToolContextCallback;
import pl.net.bluesoft.rnd.processtool.ProcessToolContextFactory;
import pl.net.bluesoft.rnd.processtool.ReturningProcessToolContextCallback;
import pl.net.bluesoft.rnd.processtool.bpm.ProcessToolBpmSession;
import pl.net.bluesoft.rnd.processtool.dao.ProcessDefinitionDAO;
import pl.net.bluesoft.rnd.processtool.model.UserData;
import pl.net.bluesoft.rnd.processtool.model.config.ProcessDefinitionConfig;
import pl.net.bluesoft.rnd.processtool.model.config.ProcessQueueConfig;
import pl.net.bluesoft.rnd.processtool.plugins.ProcessToolRegistry;
import pl.net.bluesoft.util.io.IOUtils;

import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import java.io.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* @author tlipski@bluesoft.net.pl
*/
//TODO introduce abstract common ContextFactory for common methods
public class ActivitiContextFactoryImpl implements ProcessToolContextFactory {
    private static Logger logger = Logger.getLogger(ActivitiContextFactoryImpl.class.getName());
    private ProcessToolRegistry registry;

    public ActivitiContextFactoryImpl(ProcessToolRegistry registry) {
        this.registry = registry;

    }

    @Override
    public <T> T withExistingOrNewContext(ReturningProcessToolContextCallback<T> callback) {
        ProcessToolContext ctx = ProcessToolContext.Util.getThreadProcessToolContext();
        return ctx != null && ctx.isActive() ? callback.processWithContext(ctx) : withProcessToolContext(callback);
    }

    @Override
    public <T> T withProcessToolContext(ReturningProcessToolContextCallback<T> callback) {
        if (registry.isJta()) {
            return withProcessToolContextJta(callback);
        } else {
            return withProcessToolContextNonJta(callback);
        }
    }

    public <T> T withProcessToolContextNonJta(ReturningProcessToolContextCallback<T> callback) {
        Session session = registry.getSessionFactory().openSession();
        try {
            CustomStandaloneProcessEngineConfiguration processEngineConfiguration = getProcessEngineConfiguration(session);
            ProcessEngine pi = getProcessEngine(processEngineConfiguration);
            try {
                org.hibernate.Transaction tx = session.beginTransaction();
                T res;
                try {
                    ActivitiContextImpl ctx = new ActivitiContextImpl(session, this, pi, processEngineConfiguration);
                    res = callback.processWithContext(ctx);
                } catch (RuntimeException e) {
                    logger.log(Level.SEVERE, e.getMessage(), e);
                    try {
                        tx.rollback();
                    } catch (Exception e1) {
                        logger.log(Level.WARNING, e1.getMessage(), e1);
                    }
                    throw e;
                }
                tx.commit();
                return res;
            } finally {
                pi.close();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            session.close();
        }
    }

    public <T> T withProcessToolContextJta(ReturningProcessToolContextCallback<T> callback) {
        try {
            UserTransaction ut;
            try {
                ut = (UserTransaction) new InitialContext().lookup("java:comp/UserTransaction");
            } catch (Exception e) {
                //it should work on jboss regardless. But it does not..
                logger.warning("java:comp/UserTransaction not found, looking for UserTransaction");
                ut = (UserTransaction) new InitialContext().lookup("UserTransaction");
            }

            logger.fine("ut.getStatus() = " + ut.getStatus());
            if (ut.getStatus() == Status.STATUS_MARKED_ROLLBACK) {
                ut.rollback();
            }
            if (ut.getStatus() != Status.STATUS_ACTIVE)
                ut.begin();
            Session session = registry.getSessionFactory().getCurrentSession();
            T res;
            try {
                //init activiti
                CustomStandaloneProcessEngineConfiguration processEngineConfiguration = getProcessEngineConfiguration(session);
                ProcessEngine processEngine = getProcessEngine(processEngineConfiguration);
                try {
                    try {
                        ActivitiContextImpl ctx = new ActivitiContextImpl(session, this, processEngine, processEngineConfiguration);
                        res = callback.processWithContext(ctx);
                    } catch (Exception e) {
                        logger.log(Level.SEVERE, e.getMessage(), e);
                        try {
                            ut.rollback();
                        } catch (Exception e1) {
                            logger.log(Level.WARNING, e1.getMessage(), e1);
                        }
                        throw e;
                    }
                } finally {
                    processEngine.close();
                }
            } finally {
                session.flush();
            }
            ut.commit();
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * We need to alter activiti mappings a little,
     * since Activiti does not provide any other way to add custom mappings
     * (was the abandonment of Hibernate a right decision?)
     */
    public class CustomStandaloneProcessEngineConfiguration extends StandaloneProcessEngineConfiguration {

        @Override
        protected void initSqlSessionFactory() {
            if (sqlSessionFactory == null) {
                InputStream inputStream = null;
                try {
                    inputStream = ReflectUtil.getResourceAsStream("org/aperteworkflow/ext/activiti/mybatis/mappings-enhanced.xml");

                    // update the jdbc parameters to the configured ones...
                    Environment environment = new Environment("default", transactionFactory, dataSource);
                    Reader reader = new InputStreamReader(inputStream);
                    XMLConfigBuilder parser = new XMLConfigBuilder(reader);
                    Configuration configuration = parser.getConfiguration();
                    configuration.setEnvironment(environment);
                    configuration.getTypeHandlerRegistry().register(VariableType.class, JdbcType.VARCHAR,
                            new IbatisVariableTypeHandler());
                    configuration = parser.parse();

                    sqlSessionFactory = new DefaultSqlSessionFactory(configuration);

                } catch (Exception e) {
                    throw new ActivitiException("Error while building ibatis SqlSessionFactory: " + e.getMessage(), e);
                } finally {
                    IoUtil.closeSilently(inputStream);
                }
            }
        }
    }

    public CustomStandaloneProcessEngineConfiguration getProcessEngineConfiguration(Session sess) {
        CustomStandaloneProcessEngineConfiguration customStandaloneProcessEngineConfiguration = new CustomStandaloneProcessEngineConfiguration();
                customStandaloneProcessEngineConfiguration
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
                .setDataSource(getDataSourceWrapper(sess))
                .setHistory(ProcessEngineConfiguration.HISTORY_FULL)
                .setTransactionsExternallyManaged(true);
        return customStandaloneProcessEngineConfiguration;
    }

    public ProcessEngine getProcessEngine(CustomStandaloneProcessEngineConfiguration customStandaloneProcessEngineConfiguration) {
        return customStandaloneProcessEngineConfiguration.buildProcessEngine();
    }

    private DataSource getDataSourceWrapper(Session sess) {
        return new DataSourceWrapper(sess);
    }

    @Override
    public ProcessToolRegistry getRegistry() {
        return registry;
    }

    @Override
    public void deployOrUpdateProcessDefinition(final InputStream bpmStream,
                                                final ProcessDefinitionConfig cfg,
                                                final ProcessQueueConfig[] queues,
                                                final InputStream imageStream,
                                                InputStream logoStream) {
        withProcessToolContext(new ProcessToolContextCallback() {
            @Override
            public void withContext(ProcessToolContext processToolContext) {

                ProcessToolContext.Util.setThreadProcessToolContext(processToolContext);
                try {
                    boolean skipBpm = false;
                    InputStream is = bpmStream;
                    ProcessToolBpmSession session = processToolContext.getProcessToolSessionFactory().createSession(
                            new UserData("admin", "admin@aperteworkflow.org", "Admin"), Arrays.asList("ADMIN"));
                    byte[] oldDefinition = session.getProcessLatestDefinition(cfg.getBpmDefinitionKey(), cfg.getProcessName());
                    if (oldDefinition != null) {
                        byte[] newDefinition = IOUtils.slurp(is);
                        is = new ByteArrayInputStream(newDefinition);
                        if (Arrays.equals(newDefinition, oldDefinition)) {
                            logger.log(Level.WARNING, "bpm definition for " + cfg.getProcessName() +
                                    " is the same as in BPM, therefore not updating BPM process definition");
                            skipBpm = true;
                        }
                    }

                    if (!skipBpm) {
                        String deploymentId = session.deployProcessDefinition(cfg.getProcessName(), is, imageStream);
                        logger.log(Level.INFO, "deployed new BPM Engine definition with id: " + deploymentId);
                    }

                    ProcessDefinitionDAO processDefinitionDAO = processToolContext.getProcessDefinitionDAO();
                    processDefinitionDAO.updateOrCreateProcessDefinitionConfig(cfg);
                    logger.log(Level.INFO, "created  definition with id: " + cfg.getId());
                    if (queues != null && queues.length > 0) {
                        processDefinitionDAO.updateOrCreateQueueConfigs(Arrays.asList(queues));
                        logger.log(Level.INFO, "created/updated " + queues.length + " queues");
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } finally {
                    ProcessToolContext.Util.removeThreadProcessToolContext();
                }
            }
        });
    }

    @Override
    public void deployOrUpdateProcessDefinition(InputStream jpdlStream,
                                                InputStream processToolConfigStream,
                                                InputStream queueConfigStream,
                                                InputStream imageStream,
                                                InputStream logoStream) {


        if (jpdlStream == null || processToolConfigStream == null || queueConfigStream == null) {
            throw new IllegalArgumentException("at least one of the streams is null");
        }
        XStream xstream = new XStream();
        xstream.aliasPackage("config", ProcessDefinitionConfig.class.getPackage().getName());
        xstream.useAttributeFor(String.class);
        xstream.useAttributeFor(Boolean.class);
        xstream.useAttributeFor(Integer.class);

        ProcessDefinitionConfig config = (ProcessDefinitionConfig) xstream.fromXML(processToolConfigStream);

        if (logoStream != null) {
            byte[] logoBytes;
            try {
                logoBytes = IOUtils.slurp(logoStream);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            if (logoBytes.length > 0) {
                config.setProcessLogo(logoBytes);
            }
        }
        Collection<ProcessQueueConfig> qConfigs = (Collection<ProcessQueueConfig>) xstream.fromXML(queueConfigStream);
        deployOrUpdateProcessDefinition(jpdlStream,
                config,
                qConfigs.toArray(new ProcessQueueConfig[qConfigs.size()]),
                imageStream,
                logoStream);
    }

    @Override
    public void updateSessionFactory(org.hibernate.SessionFactory sf) {
        //nothing
    }
}
TOP

Related Classes of org.aperteworkflow.ext.activiti.ActivitiContextFactoryImpl

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.