001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.bpmscript.db;
018:
019: import java.sql.SQLException;
020: import java.sql.Timestamp;
021: import java.util.List;
022:
023: import org.bpmscript.BpmScriptException;
024: import org.bpmscript.ExecutorResult;
025: import org.bpmscript.FailedResult;
026: import org.bpmscript.IMarshaler;
027: import org.bpmscript.IPagedResult;
028: import org.bpmscript.IProcess;
029: import org.bpmscript.IProcessInstance;
030: import org.bpmscript.IProcessInstanceCallback;
031: import org.bpmscript.IProcessInstanceManager;
032: import org.bpmscript.IProcessManager;
033: import org.bpmscript.IProcessSource;
034: import org.bpmscript.IQuery;
035: import org.bpmscript.IgnoredResult;
036: import org.bpmscript.PagedResult;
037: import org.bpmscript.PausedResult;
038: import org.bpmscript.ProcessInstance;
039: import org.bpmscript.ProcessState;
040: import org.bpmscript.XStreamMarshaler;
041: import org.hibernate.HibernateException;
042: import org.hibernate.LockMode;
043: import org.hibernate.Query;
044: import org.hibernate.Session;
045: import org.springframework.orm.hibernate3.HibernateCallback;
046: import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
047:
048: public class HibernateProcessInstanceManager extends
049: HibernateDaoSupport implements IProcessInstanceManager {
050:
051: private final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
052: .getLog(HibernateProcessInstanceManager.class);
053:
054: private IMarshaler marshaler = new XStreamMarshaler();
055: private IProcessManager processManager = null;
056:
057: public String createProcessInstance(String parentProcessInstanceId,
058: String processName, String operation)
059: throws BpmScriptException {
060: List list = getHibernateTemplate()
061: .findByNamedParam(
062: "from org.bpmscript.db.DbProcess process where process.name = :processName and process.primaryProcess = true",
063: "processName", processName);
064: if (list.size() == 1) {
065: DbProcess process = (DbProcess) list.get(0);
066: DbProcessInstance processInstance = new DbProcessInstance();
067: processInstance.setCreationDate(new Timestamp(System
068: .currentTimeMillis()));
069: processInstance.setProcess(process);
070: processInstance.setOperation(operation);
071: processInstance
072: .setProcessInstanceState(getProcessInstanceState(ProcessState.CREATED
073: .name()));
074: processInstance
075: .setParentProcessInstanceId(parentProcessInstanceId);
076: getHibernateTemplate().saveOrUpdate(processInstance);
077: return processInstance.getId();
078: } else {
079: throw new BpmScriptException(
080: "wrong number of processes returned " + list.size());
081: }
082: }
083:
084: public DbProcessInstanceState getProcessInstanceState(String name)
085: throws BpmScriptException {
086: List list = getHibernateTemplate()
087: .findByNamedParam(
088: "from org.bpmscript.db.DbProcessInstanceState processState where processState.name = :name",
089: "name", name);
090: if (list.size() == 1) {
091: return (DbProcessInstanceState) list.get(0);
092: } else {
093: throw new BpmScriptException(
094: "wrong number of process states returned "
095: + list.size());
096: }
097: }
098:
099: @SuppressWarnings("unchecked")
100: public IPagedResult<IProcessInstance> getProcessInstances(
101: final IQuery query) {
102:
103: List<IProcessInstance> processInstances = (List<IProcessInstance>) getHibernateTemplate()
104: .execute(new HibernateCallback() {
105: public Object doInHibernate(Session session)
106: throws HibernateException, SQLException {
107: Query hibernateQuery = null;
108: String filter = query.getFilter();
109: if (filter != null) {
110: // TODO: protect against sql injection
111: hibernateQuery = session
112: .createQuery("from org.bpmscript.db.DbProcessInstance instance where instance.process.name like '%"
113: + filter.trim()
114: + "%' order by instance.lastModified desc");
115: } else {
116: hibernateQuery = session
117: .createQuery("from org.bpmscript.db.DbProcessInstance instance order by instance.lastModified desc");
118: }
119: hibernateQuery.setLockMode("instance",
120: LockMode.READ);
121: if (query.getFirstResult() >= 0) {
122: hibernateQuery.setFirstResult(query
123: .getFirstResult());
124: }
125: if (query.getMaxResults() >= 0) {
126: hibernateQuery.setMaxResults(query
127: .getMaxResults() + 1);
128: }
129: List result = hibernateQuery.list();
130: return result;
131: }
132: });
133: boolean more = false;
134: if (query.getMaxResults() >= 0) {
135: if (processInstances.size() > query.getMaxResults()) {
136: processInstances.remove(processInstances.size() - 1);
137: more = true;
138: }
139: }
140: addStackTrace(processInstances);
141: return new PagedResult<IProcessInstance>(processInstances,
142: more, -1);
143: }
144:
145: private void addStackTrace(List<IProcessInstance> processInstances) {
146: if (processInstances != null) {
147: for (IProcessInstance instance : processInstances) {
148: addStackTrace(instance);
149: }
150: }
151: }
152:
153: private void addStackTrace(IProcessInstance instance) {
154: DbProcessInstance dbProcessInstance = ((DbProcessInstance) instance);
155: dbProcessInstance
156: .setStackTraceElements((StackTraceElement[]) marshaler
157: .unmarshal(dbProcessInstance
158: .getSerializedStack()));
159: dbProcessInstance.setThrowable((Throwable) marshaler
160: .unmarshal(dbProcessInstance.getSerializedThrowable()));
161: }
162:
163: @SuppressWarnings("unchecked")
164: public List<IProcess> getPrimaryProcesses() {
165: return getHibernateTemplate()
166: .find(
167: "from org.bpmscript.db.DbProcess process where process.primaryProcess = true");
168: }
169:
170: @SuppressWarnings("unchecked")
171: public List<IProcessSource> getProcessSources(String processId) {
172: return getHibernateTemplate()
173: .findByNamedParam(
174: "from org.bpmscript.db.DbProcessSource source where source.processId = :processId",
175: "processId", processId);
176: }
177:
178: public IProcessInstance getProcessInstance(String processInstanceId)
179: throws BpmScriptException {
180: DbProcessInstance processInstance = (DbProcessInstance) getHibernateTemplate()
181: .load(DbProcessInstance.class, processInstanceId);
182: addStackTrace(processInstance);
183: return new ProcessInstance(processInstance);
184: }
185:
186: @SuppressWarnings("unchecked")
187: public List<IProcessInstance> getChildProcessInstances(
188: String processInstanceId) throws BpmScriptException {
189: List processInstances = getHibernateTemplate()
190: .findByNamedParam(
191: "from org.bpmscript.db.DbProcessInstance instance where instance.parentProcessInstanceId = :parentProcessId",
192: "parentProcessId", processInstanceId);
193: addStackTrace((List<IProcessInstance>) processInstances);
194: return processInstances;
195: }
196:
197: public ExecutorResult doWithProcessInstance(
198: final String processInstanceId,
199: final IProcessInstanceCallback callback) throws Throwable {
200: try {
201: return (ExecutorResult) getHibernateTemplate().execute(
202: new HibernateCallback() {
203: public Object doInHibernate(Session session)
204: throws HibernateException, SQLException {
205: ExecutorResult executorResult = null;
206: try {
207: // TODO: set running and created states
208: DbProcessInstance processInstance = (DbProcessInstance) getHibernateTemplate()
209: .load(DbProcessInstance.class,
210: processInstanceId,
211: LockMode.UPGRADE);
212: log.debug("running "
213: + processInstanceId
214: + " "
215: + processInstance.getProcess()
216: .getName()
217: + " "
218: + processInstance
219: .getOperation());
220: executorResult = callback
221: .execute(processInstance);
222: if (executorResult.getProcessState() == ProcessState.PAUSED) {
223: PausedResult pausedResult = ((PausedResult) executorResult);
224: processInstance
225: .setProcessInstanceState(getProcessInstanceState(ProcessState.PAUSED
226: .name()));
227: processInstance
228: .setContinuation(pausedResult
229: .getContinuation());
230: processInstance
231: .setSerializedStack(marshaler
232: .marshal(pausedResult
233: .getStackTraceElements()));
234: processInstance
235: .setSerializedThrowable(null);
236: getHibernateTemplate().update(
237: processInstance);
238: } else if (executorResult
239: .getProcessState() == ProcessState.COMPLETED) {
240: processInstance
241: .setProcessInstanceState(getProcessInstanceState(ProcessState.COMPLETED
242: .name()));
243: processInstance
244: .setContinuation(null);
245: processInstance
246: .setSerializedStack(null);
247: processInstance
248: .setSerializedThrowable(null);
249: getHibernateTemplate().update(
250: processInstance);
251: } else if (executorResult
252: .getProcessState() == ProcessState.FAILED) {
253: if (executorResult instanceof FailedResult) {
254: FailedResult failedResult = ((FailedResult) executorResult);
255: Throwable throwable = failedResult
256: .getThrowable();
257: processInstance
258: .setProcessInstanceState(getProcessInstanceState(ProcessState.FAILED
259: .name()));
260: processInstance
261: .setSerializedStack(marshaler
262: .marshal(failedResult
263: .getStackTraceElements()));
264: if (throwable != null) {
265: processInstance
266: .setSerializedThrowable(marshaler
267: .marshal(throwable));
268: }
269: getHibernateTemplate().update(
270: processInstance);
271: throw throwable;
272: } else if (executorResult instanceof IgnoredResult) {
273: // possible issue here
274: log.warn("ignoring result");
275: }
276: } else {
277: getHibernateTemplate().update(
278: processInstance);
279: }
280: log.debug("finished running "
281: + processInstanceId
282: + " "
283: + processInstance.getProcess()
284: .getName()
285: + " "
286: + processInstance
287: .getOperation());
288: } catch (Throwable t) {
289: throw new RuntimeException(t);
290: }
291: return executorResult;
292: }
293: });
294:
295: } catch (RuntimeException e) {
296: if (e.getCause() != null) {
297: throw e.getCause();
298: } else {
299: throw e;
300: }
301: }
302: }
303:
304: public IProcessManager getProcessManager() {
305: return processManager;
306: }
307:
308: public void setProcessManager(IProcessManager processManager) {
309: this .processManager = processManager;
310: }
311:
312: @SuppressWarnings("unchecked")
313: public Timestamp getProcessInstanceVersion(String processInstanceId)
314: throws BpmScriptException {
315: List<Timestamp> lastModifiedList = getHibernateTemplate()
316: .findByNamedParam(
317: "select instance.lastModified from org.bpmscript.db.DbProcessInstance instance where instance.id = :processInstanceId",
318: "processInstanceId", processInstanceId);
319: if (lastModifiedList == null || lastModifiedList.size() == 0) {
320: return null;
321: } else {
322: return lastModifiedList.get(0);
323: }
324: }
325:
326: }
|