1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.workflow.jcr;
35
36 import info.magnolia.beancoder.MgnlNode;
37 import info.magnolia.cms.core.Content;
38 import info.magnolia.cms.core.HierarchyManager;
39 import info.magnolia.cms.core.ItemType;
40 import info.magnolia.cms.core.search.Query;
41 import info.magnolia.cms.core.search.QueryManager;
42 import info.magnolia.cms.core.search.QueryResult;
43 import info.magnolia.cms.security.AccessDeniedException;
44 import info.magnolia.cms.util.ContentUtil;
45 import info.magnolia.context.LifeTimeJCRSessionUtil;
46 import info.magnolia.context.MgnlContext;
47 import info.magnolia.module.workflow.WorkflowConstants;
48 import info.magnolia.module.workflow.beancoder.OwfeJcrBeanCoder;
49
50 import java.util.ArrayList;
51 import java.util.Iterator;
52 import java.util.List;
53
54 import javax.jcr.RepositoryException;
55 import javax.jcr.ValueFactory;
56
57 import openwfe.org.engine.expressions.FlowExpressionId;
58 import openwfe.org.engine.workitem.InFlowWorkItem;
59 import openwfe.org.engine.workitem.StringAttribute;
60 import openwfe.org.util.beancoder.BeanCoderException;
61 import openwfe.org.worklist.store.StoreException;
62
63 import org.apache.commons.lang.StringUtils;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67
68
69
70
71
72
73
74
75
76 public class JCRWorkItemStore {
77 private final static Logger log = LoggerFactory.getLogger(JCRWorkItemStore.class.getName());
78
79 private static final String BACKUP_REL = "backup";
80 private static final String BACKUP = "/" + BACKUP_REL;
81
82 private boolean shouldBackupWorkItems = false;
83
84 private boolean useLifeTimeJCRSession = true;
85
86 private boolean cleanUp = false;
87
88 public JCRWorkItemStore(boolean useLifeTimeJCRSession, boolean cleanUp,
89 boolean shouldBackupWorkItems) {
90 this.useLifeTimeJCRSession = useLifeTimeJCRSession;
91 this.cleanUp = cleanUp;
92 this.shouldBackupWorkItems = shouldBackupWorkItems;
93 }
94
95 public JCRWorkItemStore() throws Exception {
96 HierarchyManager hm = getHierarchyManager();
97
98 if (shouldBackupWorkItems) {
99
100 if (!hm.isExist(BACKUP)) {
101 ContentUtil.createPath(hm, BACKUP, ItemType.CONTENT);
102 hm.save();
103 log.info("Created " + BACKUP + " in workflow store.");
104 }
105 }
106 }
107
108 protected HierarchyManager getHierarchyManager() {
109 if(useLifeTimeJCRSession){
110 return LifeTimeJCRSessionUtil.getHierarchyManager(WorkflowConstants.WORKSPACE_STORE);
111 }
112 else{
113 return MgnlContext.getSystemContext().getHierarchyManager(WorkflowConstants.WORKSPACE_STORE);
114 }
115 }
116
117
118
119
120 public synchronized void removeWorkItem(FlowExpressionId fei) throws StoreException {
121 try {
122 HierarchyManager hm = getHierarchyManager();
123 Content ct = getWorkItemById(fei);
124 if (ct != null) {
125
126 if (!shouldBackupWorkItems) {
127 ContentUtil.deleteAndRemoveEmptyParents(ct,1);
128 } else {
129 final ValueFactory vf = ct.getJCRNode().getSession().getValueFactory();
130 ct.setNodeData("isBackup", vf.createValue(true));
131 final Content parent = ct.getParent();
132 final String pathInBackup = BACKUP + parent.getHandle();
133 ContentUtil.createPath(hm, pathInBackup, ItemType.WORKITEM);
134 hm.save();
135 hm.moveTo(ct.getHandle(), BACKUP + ct.getHandle());
136
137 }
138
139 hm.save();
140 log.debug("work item removed or moved to /backup");
141 }
142
143 } catch (Exception e) {
144 log.error("exception when unstoring workitem:" + e, e);
145 }
146 }
147
148
149
150
151
152
153
154
155
156 public InFlowWorkItem retrieveWorkItem(final String storeName, final FlowExpressionId fei) throws StoreException {
157 if (log.isDebugEnabled()) {
158 log.debug("starting retrieve work item. this = " + this);
159 log.debug("retrieve work item for ID = " + fei.toParseableString());
160 }
161
162 Content ct = getWorkItemById(fei);
163
164 if (ct == null) {
165 throw new StoreException("cannot find workitem " + fei);
166 }
167
168 try {
169 return loadWorkItem(ct);
170 }
171 catch (Exception e) {
172 throw new StoreException("load work item form xml failed", e);
173 }
174 }
175
176
177
178
179
180
181
182 public InFlowWorkItem loadWorkItem(Content ct) throws Exception {
183 OwfeJcrBeanCoder coder = new OwfeJcrBeanCoder(null, new MgnlNode(ct.getContent(WorkflowConstants.NODEDATA_VALUE)));
184 return (InFlowWorkItem) coder.decode();
185 }
186
187
188
189
190
191 public Content getWorkItemByParticipant(String participant) {
192 String queryString = "//*[@participant=\"" + participant + "\"]";
193 if (log.isDebugEnabled()) {
194 log.debug("xpath query string = " + queryString);
195 }
196 List list = doQuery(queryString);
197 if (list != null && list.size() > 0) {
198 return (Content) list.get(0);
199 }
200
201 return null;
202 }
203
204
205
206
207
208 public Content getWorkItemById(FlowExpressionId fei) {
209 String path = createPathFromId(fei);
210 try {
211 return getHierarchyManager().getContent(path);
212 }
213 catch (Exception e) {
214 log.error("get work item by id failed, path = " + path, e);
215 }
216 return null;
217 }
218
219
220
221
222
223
224 public boolean hasWorkItem(FlowExpressionId fei) throws AccessDeniedException, RepositoryException {
225 String path = createPathFromId(fei);
226 if (StringUtils.isNotEmpty(path) && StringUtils.indexOf(path, "/") != 0) {
227 path = "/" + path;
228 }
229 return getHierarchyManager().isExist(path);
230 }
231
232
233
234
235
236
237 public boolean checkContentWithEID(Content ct, FlowExpressionId eid) {
238 String cid = ct.getNodeData(WorkflowConstants.NODEDATA_ID).getString();
239 if (log.isDebugEnabled()) {
240 log.debug("checkContentWithEID: ID = " + cid);
241 }
242 FlowExpressionId id = FlowExpressionId.fromParseableString(cid);
243 return id.equals(eid);
244 }
245
246
247
248
249
250 public final String convertPath(String id) {
251 return StringUtils.replace(
252 StringUtils.replace(id, WorkflowConstants.BAR, StringUtils.EMPTY),
253 WorkflowConstants.COLON,
254 WorkflowConstants.DOT);
255 }
256
257
258
259
260
261 public String createPathFromId(FlowExpressionId eid) {
262 String wlInstId = eid.getWorkflowInstanceId();
263
264 String groupString = StringUtils.right(StringUtils.substringBefore(wlInstId, "."), 3);
265 int groupNumber = Integer.parseInt(groupString) % 100;
266 StringBuffer buffer = new StringBuffer(eid.getWorkflowDefinitionName());
267 buffer.append(WorkflowConstants.SLASH);
268 buffer.append(eid.getWorkflowDefinitionRevision());
269 buffer.append(WorkflowConstants.SLASH);
270 buffer.append(groupNumber);
271 buffer.append(WorkflowConstants.SLASH);
272 buffer.append(eid.getWorkflowInstanceId());
273 buffer.append(WorkflowConstants.SLASH);
274 buffer.append(eid.getExpressionName());
275 buffer.append(WorkflowConstants.SLASH);
276 buffer.append(eid.getExpressionId());
277
278 return convertPath(buffer.toString());
279 }
280
281
282
283
284
285
286 public synchronized void storeWorkItem(String arg0, InFlowWorkItem wi) throws StoreException {
287 try {
288 HierarchyManager hm = getHierarchyManager();
289
290 if (hasWorkItem(wi.getId())) {
291
292 hm.delete(createPathFromId(wi.getId()));
293 }
294
295
296 String path = createPathFromId(wi.getId());
297 if (log.isDebugEnabled()) {
298 log.debug("storing workitem with path = " + path);
299 }
300
301 Content newc = ContentUtil.createPath(hm,path, ItemType.WORKITEM);
302
303 ValueFactory vf = newc.getJCRNode().getSession().getValueFactory();
304 String sId = wi.getLastExpressionId().toParseableString();
305
306 newc.createNodeData(WorkflowConstants.NODEDATA_ID, vf.createValue(sId));
307 newc.createNodeData(WorkflowConstants.NODEDATA_PARTICIPANT, vf.createValue(wi.getParticipantName()));
308
309 StringAttribute assignTo = (StringAttribute) wi.getAttribute(WorkflowConstants.ATTRIBUTE_ASSIGN_TO);
310 if (assignTo != null) {
311 String s = assignTo.toString();
312 if (s.length() > 0) {
313 newc.createNodeData(WorkflowConstants.ATTRIBUTE_ASSIGN_TO, vf.createValue(s));
314 }
315 }
316
317
318 encodeWorkItemToNode(wi, newc);
319 hm.save();
320
321 if (log.isDebugEnabled()) {
322 log.debug("store work item ok. ");
323 }
324 }
325 catch (Exception e) {
326 log.error("store work item failed", e);
327 throw new StoreException(e.toString());
328 }
329 }
330
331 protected void encodeWorkItemToNode(InFlowWorkItem wi, Content newc) throws BeanCoderException {
332 OwfeJcrBeanCoder coder = new OwfeJcrBeanCoder(null, new MgnlNode(newc), WorkflowConstants.NODEDATA_VALUE);
333 coder.encode(wi);
334 }
335
336
337
338
339 public List doQuery(String queryString) {
340 return doQuery(queryString, Query.XPATH);
341 }
342
343 public List doQuery(String queryString, String language) {
344 ArrayList list = new ArrayList();
345 if (log.isDebugEnabled()) {
346 log.debug("xpath query string: " + queryString);
347 }
348 try {
349 final QueryManager queryManager = MgnlContext.getSystemContext().getQueryManager(
350 WorkflowConstants.WORKSPACE_STORE);
351 final Query q = queryManager.createQuery(queryString, language);
352
353 QueryResult result = q.execute();
354 if (result == null) {
355 log.info("query result was null");
356 return null;
357 }
358
359 Iterator it = result.getContent(WorkflowConstants.NODENAME_WORKITEM).iterator();
360 while (it.hasNext()) {
361 Content ct = (Content) it.next();
362
363
364 try {
365 if (!getHierarchyManager().isExist(ct.getHandle())) {
366 if (log.isDebugEnabled()) {
367 log.debug(ct.getHandle() + " does not exist anymore.");
368 }
369 continue;
370 }
371 }
372 catch (Exception e) {
373 log.error("SKipping strange node");
374 }
375
376 String title = ct.getTitle();
377 String sname = ct.getName();
378
379 if (log.isDebugEnabled()) {
380 log.debug("title=" + title);
381 log.debug("name=" + sname);
382 }
383
384 InFlowWorkItem wi = loadWorkItem(ct);
385 if (wi == null) {
386 log.error("can not load found workitem");
387 continue;
388 }
389 if (log.isDebugEnabled()) {
390 log.debug("added workitem to return list ok");
391 }
392 list.add(wi);
393 }
394 }
395 catch (Exception e) {
396 log.error("query flow failed", e);
397 return null;
398 }
399 return list;
400
401 }
402
403 }