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
109
110
111 protected HierarchyManager getHierarchyManager() {
112 if(useLifeTimeJCRSession){
113 return LifeTimeJCRSessionUtil.getHierarchyManager(WorkflowConstants.WORKSPACE_STORE);
114 }
115 else{
116 return MgnlContext.getSystemContext().getHierarchyManager(WorkflowConstants.WORKSPACE_STORE);
117 }
118 }
119
120
121
122
123 public synchronized void removeWorkItem(FlowExpressionId fei) throws StoreException {
124 try {
125 HierarchyManager hm = getHierarchyManager();
126 Content ct = getWorkItemById(fei);
127 if (ct != null) {
128
129 if (!shouldBackupWorkItems) {
130 ContentUtil.deleteAndRemoveEmptyParents(ct,1);
131 } else {
132 final ValueFactory vf = ct.getJCRNode().getSession().getValueFactory();
133 ct.setNodeData("isBackup", vf.createValue(true));
134 final Content parent = ct.getParent();
135 final String pathInBackup = BACKUP + parent.getHandle();
136 ContentUtil.createPath(hm, pathInBackup, ItemType.WORKITEM);
137 hm.save();
138 hm.moveTo(ct.getHandle(), BACKUP + ct.getHandle());
139
140 }
141
142 hm.save();
143 log.debug("work item removed or moved to /backup");
144 }
145
146 } catch (Exception e) {
147 log.error("exception when unstoring workitem:" + e, e);
148 }
149 }
150
151
152
153
154
155
156
157
158 public InFlowWorkItem retrieveWorkItem(final String storeName, final FlowExpressionId fei) throws StoreException {
159 if (log.isDebugEnabled()) {
160 log.debug("starting retrieve work item. this = " + this);
161 log.debug("retrieve work item for ID = " + fei.toParseableString());
162 }
163
164 Content ct = getWorkItemById(fei);
165
166 if (ct == null) {
167 throw new StoreException("cannot find workitem " + fei);
168 }
169
170 try {
171 return loadWorkItem(ct);
172 }
173 catch (Exception e) {
174 throw new StoreException("load work item form xml failed", e);
175 }
176 }
177
178
179
180
181
182
183
184 public InFlowWorkItem loadWorkItem(Content ct) throws Exception {
185 OwfeJcrBeanCoder coder = new OwfeJcrBeanCoder(null, new MgnlNode(ct.getContent(WorkflowConstants.NODEDATA_VALUE)));
186 return (InFlowWorkItem) coder.decode();
187 }
188
189
190
191
192
193 public Content getWorkItemByParticipant(String participant) {
194 String queryString = "//*[@participant=\"" + participant + "\"]";
195 if (log.isDebugEnabled()) {
196 log.debug("xpath query string = " + queryString);
197 }
198 List list = doQuery(queryString);
199 if (list != null && list.size() > 0) {
200 return (Content) list.get(0);
201 }
202
203 return null;
204 }
205
206
207
208
209
210 public Content getWorkItemById(FlowExpressionId fei) {
211 String path = createPathFromId(fei);
212 try {
213 return getHierarchyManager().getContent(path);
214 }
215 catch (Exception e) {
216 log.error("get work item by id failed, path = " + path, e);
217 }
218 return null;
219 }
220
221
222
223
224
225
226 public boolean hasWorkItem(FlowExpressionId fei) throws AccessDeniedException, RepositoryException {
227 String path = createPathFromId(fei);
228 if (StringUtils.isNotEmpty(path) && StringUtils.indexOf(path, "/") != 0) {
229 path = "/" + path;
230 }
231 return getHierarchyManager().isExist(path);
232 }
233
234
235
236
237
238
239 public boolean checkContentWithEID(Content ct, FlowExpressionId eid) {
240 String cid = ct.getNodeData(WorkflowConstants.NODEDATA_ID).getString();
241 if (log.isDebugEnabled()) {
242 log.debug("checkContentWithEID: ID = " + cid);
243 }
244 FlowExpressionId id = FlowExpressionId.fromParseableString(cid);
245 return id.equals(eid);
246 }
247
248
249
250
251
252 public final String convertPath(String id) {
253 return StringUtils.replace(
254 StringUtils.replace(id, WorkflowConstants.BAR, StringUtils.EMPTY),
255 WorkflowConstants.COLON,
256 WorkflowConstants.DOT);
257 }
258
259
260
261
262
263 public String createPathFromId(FlowExpressionId eid) {
264 String wlInstId = eid.getWorkflowInstanceId();
265
266 String groupString = StringUtils.right(StringUtils.substringBefore(wlInstId, "."), 3);
267 int groupNumber = Integer.parseInt(groupString) % 100;
268 StringBuffer buffer = new StringBuffer(eid.getWorkflowDefinitionName());
269 buffer.append(WorkflowConstants.SLASH);
270 buffer.append(eid.getWorkflowDefinitionRevision());
271 buffer.append(WorkflowConstants.SLASH);
272 buffer.append(groupNumber);
273 buffer.append(WorkflowConstants.SLASH);
274 buffer.append(eid.getWorkflowInstanceId());
275 buffer.append(WorkflowConstants.SLASH);
276 buffer.append(eid.getExpressionName());
277 buffer.append(WorkflowConstants.SLASH);
278 buffer.append(eid.getExpressionId());
279
280 return convertPath(buffer.toString());
281 }
282
283
284
285
286
287 public synchronized void storeWorkItem(String arg0, InFlowWorkItem wi) throws StoreException {
288 try {
289 HierarchyManager hm = getHierarchyManager();
290
291 if (hasWorkItem(wi.getId())) {
292
293 hm.delete(createPathFromId(wi.getId()));
294 }
295
296
297 String path = createPathFromId(wi.getId());
298 if (log.isDebugEnabled()) {
299 log.debug("storing workitem with path = " + path);
300 }
301
302 Content newc = ContentUtil.createPath(hm,path, ItemType.WORKITEM);
303
304 ValueFactory vf = newc.getJCRNode().getSession().getValueFactory();
305 String sId = wi.getLastExpressionId().toParseableString();
306
307 newc.createNodeData(WorkflowConstants.NODEDATA_ID, vf.createValue(sId));
308 newc.createNodeData(WorkflowConstants.NODEDATA_PARTICIPANT, vf.createValue(wi.getParticipantName()));
309
310 StringAttribute assignTo = (StringAttribute) wi.getAttribute(WorkflowConstants.ATTRIBUTE_ASSIGN_TO);
311 if (assignTo != null) {
312 String s = assignTo.toString();
313 if (s.length() > 0) {
314 newc.createNodeData(WorkflowConstants.ATTRIBUTE_ASSIGN_TO, vf.createValue(s));
315 }
316 }
317
318
319 encodeWorkItemToNode(wi, newc);
320 hm.save();
321
322 if (log.isDebugEnabled()) {
323 log.debug("store work item ok. ");
324 }
325 }
326 catch (Exception e) {
327 log.error("store work item failed", e);
328 throw new StoreException(e.toString());
329 }
330 }
331
332 protected void encodeWorkItemToNode(InFlowWorkItem wi, Content newc) throws BeanCoderException {
333 OwfeJcrBeanCoder coder = new OwfeJcrBeanCoder(null, new MgnlNode(newc), WorkflowConstants.NODEDATA_VALUE);
334 coder.encode(wi);
335 }
336
337
338
339
340 public List doQuery(String queryString) {
341 return doQuery(queryString, Query.XPATH);
342 }
343
344 public List doQuery(String queryString, String language) {
345 ArrayList list = new ArrayList();
346 if (log.isDebugEnabled()) {
347 log.debug("xpath query string: " + queryString);
348 }
349 try {
350 final QueryManager queryManager = MgnlContext.getSystemContext().getQueryManager(
351 WorkflowConstants.WORKSPACE_STORE);
352 final Query q = queryManager.createQuery(queryString, language);
353
354 QueryResult result = q.execute();
355 if (result == null) {
356 log.info("query result was null");
357 return null;
358 }
359
360 Iterator it = result.getContent(WorkflowConstants.NODENAME_WORKITEM).iterator();
361 while (it.hasNext()) {
362 Content ct = (Content) it.next();
363
364
365 try {
366 if (!getHierarchyManager().isExist(ct.getHandle())) {
367 if (log.isDebugEnabled()) {
368 log.debug(ct.getHandle() + " does not exist anymore.");
369 }
370 continue;
371 }
372 }
373 catch (Exception e) {
374 log.error("SKipping strange node");
375 }
376
377 String title = ct.getTitle();
378 String sname = ct.getName();
379
380 if (log.isDebugEnabled()) {
381 log.debug("title=" + title);
382 log.debug("name=" + sname);
383 }
384
385 InFlowWorkItem wi = loadWorkItem(ct);
386 if (wi == null) {
387 log.error("can not load found workitem");
388 continue;
389 }
390 if (log.isDebugEnabled()) {
391 log.debug("added workitem to return list ok");
392 }
393 list.add(wi);
394 }
395 }
396 catch (Exception e) {
397 log.error("query flow failed", e);
398 return null;
399 }
400 return list;
401
402 }
403
404 }