1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.flowable.support;
20
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Objects;
25 import javax.annotation.PreDestroy;
26 import javax.sql.DataSource;
27 import org.apache.syncope.core.persistence.api.DomainHolder;
28 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
29 import org.flowable.common.engine.impl.cfg.SpringBeanFactoryProxyMap;
30 import org.flowable.engine.ProcessEngine;
31 import org.flowable.engine.impl.el.ProcessExpressionManager;
32 import org.flowable.engine.impl.util.EngineServiceUtil;
33 import org.flowable.idm.spring.SpringIdmEngineConfiguration;
34 import org.flowable.spring.SpringProcessEngineConfiguration;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.springframework.beans.factory.FactoryBean;
38 import org.springframework.context.ApplicationContext;
39 import org.springframework.transaction.PlatformTransactionManager;
40
41
42
43
44
45 public class DomainProcessEngineFactoryBean implements FactoryBean<DomainProcessEngine>, SyncopeCoreLoader {
46
47 private static final Logger LOG = LoggerFactory.getLogger(DomainProcessEngineFactoryBean.class);
48
49 private final ApplicationContext ctx;
50
51 private DomainProcessEngine engine;
52
53 public DomainProcessEngineFactoryBean(final ApplicationContext ctx) {
54 this.ctx = ctx;
55 }
56
57 @Override
58 public int getOrder() {
59 return 300;
60 }
61
62 private ProcessEngine build(final String domain, final DataSource datasource) {
63 PlatformTransactionManager transactionManager = ctx.getBean(
64 domain + "TransactionManager", PlatformTransactionManager.class);
65 Object entityManagerFactory = ctx.getBean(domain + "EntityManagerFactory");
66
67 SpringProcessEngineConfiguration conf = ctx.getBean(SpringProcessEngineConfiguration.class);
68 conf.setDataSource(datasource);
69 conf.setTransactionManager(transactionManager);
70 conf.setTransactionsExternallyManaged(true);
71 conf.setJpaEntityManagerFactory(entityManagerFactory);
72 if (conf.getBeans() == null) {
73 conf.setBeans(new SpringBeanFactoryProxyMap(ctx));
74 }
75 if (conf.getExpressionManager() == null) {
76 conf.setExpressionManager(new ProcessExpressionManager(conf.getBeans()));
77 }
78 if (EngineServiceUtil.getIdmEngineConfiguration(conf) == null) {
79 SpringIdmEngineConfiguration spiec = ctx.getBean(SpringIdmEngineConfiguration.class);
80 conf.addEngineConfiguration(spiec.getEngineCfgKey(), spiec.getEngineScopeType(), spiec);
81 }
82 conf.setEnableSafeBpmnXml(true);
83 conf.setCustomFormTypes(List.of(new DropdownFormType(null), new PasswordFormType()));
84 conf.setDisableEventRegistry(true);
85
86 return conf.buildProcessEngine();
87 }
88
89 @Override
90 public void load(final String domain, final DataSource datasource) {
91 try {
92 Objects.requireNonNull(getObject()).getEngines().put(domain, build(domain, datasource));
93 } catch (Exception e) {
94 LOG.error("Could not setup Flowable for {}", domain, e);
95 }
96 }
97
98 @Override
99 public DomainProcessEngine getObject() throws Exception {
100 if (engine == null) {
101 Map<String, ProcessEngine> engines = new HashMap<>();
102
103 ctx.getBean(DomainHolder.class).getDomains().forEach(
104 (domain, datasource) -> engines.put(domain, build(domain, datasource)));
105
106 engine = new DomainProcessEngine(engines);
107 }
108
109 return engine;
110 }
111
112 @Override
113 public Class<DomainProcessEngine> getObjectType() {
114 return DomainProcessEngine.class;
115 }
116
117 @Override
118 public boolean isSingleton() {
119 return true;
120 }
121
122 @PreDestroy
123 public void preDestroy() {
124 if (engine != null) {
125 engine.close();
126 }
127 }
128 }