PageRenderTime 64ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/ojc-core/bpelse/bpelcore/src/com/sun/jbi/engine/bpel/core/bpel/model/runtime/impl/ForEachUnitSerialImpl.java

https://bitbucket.org/openesb/openesb-components
Java | 506 lines | 325 code | 50 blank | 131 comment | 59 complexity | 775889b4538c08ca89a60eb529106a3a MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * BEGIN_HEADER - DO NOT EDIT
  3. *
  4. * The contents of this file are subject to the terms
  5. * of the Common Development and Distribution License
  6. * (the "License"). You may not use this file except
  7. * in compliance with the License.
  8. *
  9. * You can obtain a copy of the license at
  10. * https://open-jbi-components.dev.java.net/public/CDDLv1.0.html.
  11. * See the License for the specific language governing
  12. * permissions and limitations under the License.
  13. *
  14. * When distributing Covered Code, include this CDDL
  15. * HEADER in each file and include the License file at
  16. * https://open-jbi-components.dev.java.net/public/CDDLv1.0.html.
  17. * If applicable add the following below this CDDL HEADER,
  18. * with the fields enclosed by brackets "[]" replaced with
  19. * your own identifying information: Portions Copyright
  20. * [year] [name of copyright owner]
  21. */
  22. /*
  23. * @(#)ForEachUnitSerialImpl.java
  24. *
  25. * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
  26. *
  27. * END_HEADER - DO NOT EDIT
  28. */
  29. package com.sun.jbi.engine.bpel.core.bpel.model.runtime.impl;
  30. import java.util.ArrayList;
  31. import java.util.HashMap;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.logging.Level;
  35. import java.util.logging.Logger;
  36. import org.apache.commons.jxpath.JXPathContext;
  37. import org.apache.commons.jxpath.JXPathException;
  38. import com.sun.bpel.model.BPELElement;
  39. import com.sun.bpel.model.Branches;
  40. import com.sun.bpel.model.ForEach;
  41. import com.sun.bpel.model.meta.RActivity;
  42. import com.sun.bpel.model.meta.RActivityHolder;
  43. import com.sun.bpel.model.meta.RVariable;
  44. import com.sun.jbi.engine.bpel.core.bpel.engine.BusinessProcessInstanceThread;
  45. import com.sun.jbi.engine.bpel.core.bpel.engine.Engine;
  46. import com.sun.jbi.engine.bpel.core.bpel.engine.ICallFrame;
  47. import com.sun.jbi.engine.bpel.core.bpel.engine.impl.BPELInterpreter;
  48. import com.sun.jbi.engine.bpel.core.bpel.event.Variable;
  49. import com.sun.jbi.engine.bpel.core.bpel.event.VariableEvent;
  50. import com.sun.jbi.engine.bpel.core.bpel.event.VariableEvent.VariableType;
  51. import com.sun.jbi.engine.bpel.core.bpel.event.impl.VariableImpl;
  52. import com.sun.jbi.engine.bpel.core.bpel.exception.StandardException;
  53. import com.sun.jbi.engine.bpel.core.bpel.model.runtime.ActivityUnit;
  54. import com.sun.jbi.engine.bpel.core.bpel.model.runtime.ActivityUnitFactory;
  55. import com.sun.jbi.engine.bpel.core.bpel.model.runtime.Context;
  56. import com.sun.jbi.engine.bpel.core.bpel.model.runtime.RequiredObjects;
  57. import com.sun.jbi.engine.bpel.core.bpel.model.runtime.RuntimeVariable;
  58. import com.sun.jbi.engine.bpel.core.bpel.model.runtime.Unit;
  59. import com.sun.jbi.engine.bpel.core.bpel.persist.MutableState;
  60. import com.sun.jbi.engine.bpel.core.bpel.trace.BPELTraceManager;
  61. import com.sun.jbi.engine.bpel.core.bpel.util.I18n;
  62. import com.sun.jbi.engine.bpel.core.bpel.util.Utility;
  63. /**
  64. * Implementation of ForEach unit when parallel="no"
  65. *
  66. * @author Sun Microsystems
  67. *
  68. */
  69. public class ForEachUnitSerialImpl extends StructuredActivityUnitImpl {
  70. private static final Logger LOGGER = Logger.getLogger(ForEachUnitSerialImpl.class.getName());
  71. private int mStartCounter;
  72. private int mFinalCounter;
  73. private int mCounter;
  74. private int mSucceededCount;
  75. private int mBranches;
  76. private boolean mHasCompleteCondition;
  77. private boolean mCountCompletedBranches;
  78. private int mTotalCount;
  79. /**
  80. * Constructor for a serial ForEach
  81. *
  82. * @param parentActUnit Parent ActivityUnit
  83. * @param act RActivity
  84. * @param branchId BranchID
  85. */
  86. public ForEachUnitSerialImpl(Context context, Unit parentActUnit,
  87. RActivity act, long branchId) {
  88. super(context, parentActUnit, act, branchId);
  89. }
  90. // TODO TEMPORARY UNTIL REFACTORING CAN OCCUR
  91. public void initUponRecovery(int counter, int successes,
  92. int startCount, int finalCount,
  93. int conditionCount) {
  94. // set values from DB
  95. mCounter = counter;
  96. mSucceededCount = successes;
  97. mStartCounter = startCount;
  98. mFinalCounter = finalCount;
  99. mTotalCount = mFinalCounter - mStartCounter + 1;
  100. mBranches = conditionCount;
  101. // parse model to initialize completion condition
  102. initCompletionCondition();
  103. }
  104. /**
  105. * Returns the enclosed activity, it is always a scope
  106. */
  107. protected RActivity getChildActivity() {
  108. return ((RActivityHolder) mAct).getChildActivity();
  109. }
  110. /**
  111. * Continues the execution. This is called when the enclosed Scope runs to complete when the
  112. * last event is received
  113. */
  114. protected boolean doResumeAction(ActivityUnit childActUnit, ICallFrame frame,
  115. BusinessProcessInstanceThread bpit, RequiredObjects rObjs) throws Exception {
  116. frame.setProgramCounter(this);
  117. //Either the child was complete or was terminated. We check if this
  118. //activity is being terminated, if yes we pass control to parent (which
  119. //will also do this check).
  120. if (mContext.getFaultHandlingContext().isBeingTerminated()) {
  121. frame.onActivityTerminate(this);
  122. return super.doPassControlToParent(frame, bpit, rObjs);
  123. }
  124. //This means the current iteration is done
  125. boolean childScopeCompletedNormally = ((ScopeUnitImpl) childActUnit).hasCompletedNormally();
  126. if (childScopeCompletedNormally) {
  127. mSucceededCount++;
  128. }
  129. mCounter++;
  130. if (!isPossible()) {
  131. frame.onActivityComplete(this);
  132. frame.getProcessInstance().getMonitorMgr().postActivityFaultedEvent(this);
  133. throw new StandardException(StandardException.Fault.CompletionConditionFailure);
  134. }
  135. if (isDone()) {
  136. specificUpdateState(rObjs, true);
  137. frame.onActivityComplete(this);
  138. frame.getProcessInstance().getMonitorMgr().postActivityCompleteEvent(this);
  139. return super.doPassControlToParent(frame, bpit, rObjs);
  140. }
  141. boolean loopCompleted = doForEach(frame, bpit, rObjs);
  142. if (loopCompleted) {
  143. //Check whether foreach was terminated (true could be returned when the
  144. //foreach is completed or when the foreach was terminated, so we need to
  145. //check again).
  146. if (mContext.getFaultHandlingContext().isBeingTerminated()) {
  147. //frame.onActivityTerminate(this) was already called in doForEach
  148. return super.doPassControlToParent(frame, bpit, rObjs);
  149. } else {
  150. specificUpdateState(rObjs, true);
  151. frame.onActivityComplete(this);
  152. frame.getProcessInstance().getMonitorMgr().postActivityCompleteEvent(this);
  153. return super.doPassControlToParent(frame, bpit, rObjs);
  154. }
  155. } else {
  156. //forEach not completed yet.
  157. return false;
  158. }
  159. }
  160. /**
  161. * Execute ForEach The first entry of ForEach does the following:
  162. * 1. Initialize 2. calls doForEach
  163. *
  164. * @param frame The Callframe
  165. * @param bpit The BusinessProcessInstance
  166. * @param rObjs The RequiredObjects
  167. */
  168. public boolean doAction(ICallFrame frame,
  169. BusinessProcessInstanceThread bpit,
  170. RequiredObjects rObjs) throws Exception {
  171. frame.setProgramCounter(this);
  172. frame.getProcessInstance().getMonitorMgr().postActivityStartEvent(this);
  173. BPELTraceManager.getInstance().doTraceOnStart(mAct, mContext, frame.getProcessInstance());
  174. //Check whether we need to terminate this activity
  175. if (mContext.getFaultHandlingContext().isBeingTerminated()) {
  176. frame.onActivityTerminate(this);
  177. return true;
  178. }
  179. boolean shouldProceed = initialize(frame, rObjs);
  180. if (!shouldProceed) {
  181. return true;
  182. }
  183. specificUpdateState(rObjs, false);
  184. boolean loopCompleted = doForEach(frame, bpit, rObjs);
  185. if(loopCompleted) {
  186. //Check whether foreach was terminated (true could be returned when the
  187. //foreach is completed or when the foreach was terminated, so we need to
  188. //check again).
  189. if (mContext.getFaultHandlingContext().isBeingTerminated()) {
  190. //frame.onActivityTerminate(this) was already called in doForEach
  191. return true;
  192. } else {
  193. specificUpdateState(rObjs, true);
  194. BPELTraceManager.getInstance().doTraceOnComplete(mAct, mContext, frame.getProcessInstance());
  195. frame.onActivityComplete(this);
  196. frame.getProcessInstance().getMonitorMgr().postActivityCompleteEvent(this);
  197. return true;
  198. }
  199. } else {
  200. return false;
  201. }
  202. }
  203. /**
  204. * Do each iteration
  205. *
  206. * @param frame
  207. * @param bpit
  208. * @param rObjs
  209. * @return
  210. * @throws Exception
  211. */
  212. private boolean doForEach(ICallFrame frame, BusinessProcessInstanceThread bpit,
  213. RequiredObjects rObjs) throws Exception {
  214. frame.onLineChange(this);
  215. // begin loop
  216. for (int i = mCounter; mCounter < mTotalCount; i++) {
  217. frame.onLineChange(this);
  218. updateCounterState(rObjs, frame);
  219. ScopeUnitImpl childScopeUnit = (ScopeUnitImpl) ActivityUnitFactory.getInstance()
  220. .createActivityUnit(mContext, this, getChildActivity(), getBranchId());
  221. //Add variable to the child scope unit.
  222. addVariable(childScopeUnit, mCounter + mStartCounter, rObjs, frame);
  223. boolean childScopeCompleted = executeChildActivities(frame, bpit, rObjs, childScopeUnit);
  224. if (childScopeCompleted == false) {
  225. return false;
  226. } else {
  227. frame.setProgramCounter(this);
  228. //Child activity completed or was terminated, check if the forEach is being
  229. //terminated, before we do the next iteration.
  230. if (mContext.getFaultHandlingContext().isBeingTerminated()) {
  231. frame.onActivityTerminate(this);
  232. return true;
  233. }
  234. }
  235. if(rObjs.getEngine().getState() == Engine.STOPPED){
  236. return false; // Engine is stopped return from here no more processing.
  237. }
  238. boolean childScopeCompletedNormally = childScopeUnit.hasCompletedNormally();
  239. if (childScopeCompletedNormally) {
  240. mSucceededCount++;
  241. }
  242. mCounter++;
  243. if (!isPossible()) {
  244. throw new StandardException(StandardException.Fault.CompletionConditionFailure);
  245. }
  246. if (isDone()) {
  247. return true;
  248. }
  249. }
  250. return true;
  251. }
  252. private void specificUpdateState(RequiredObjects rObjs, boolean isUnitDone) {
  253. if (rObjs.getBPELProcessManager().isPersistenceEnabled()) {
  254. long branchId = getBranchId();
  255. MutableState state = mContext.getStateContext().getState();
  256. if (isUnitDone) {
  257. state.endForEach(mAct.getUniqueId(), branchId);
  258. } else {
  259. state.addForEach(mAct.getUniqueId(), branchId, mStartCounter,
  260. mFinalCounter, mBranches);
  261. state.startForEach(mAct.getUniqueId(), branchId);
  262. }
  263. }
  264. }
  265. /* Notifies state the loop has begun. */
  266. private void updateCounterState(RequiredObjects rObjs, ICallFrame frame) {
  267. if (rObjs.getBPELProcessManager().isPersistenceEnabled()) {
  268. MutableState state = mContext.getStateContext().getState();
  269. state.updateForEach(mAct.getUniqueId(), getBranchId(), mCounter,
  270. mSucceededCount);
  271. }
  272. }
  273. /**
  274. * Evaluate the N out M complete condition
  275. * @return whether it is done
  276. */
  277. protected boolean isDone () {
  278. if (mHasCompleteCondition) {
  279. if (mCountCompletedBranches) {
  280. if (mSucceededCount >= mBranches) {
  281. return true;
  282. }
  283. }
  284. else if (mCounter >= mBranches) {
  285. return true;
  286. }
  287. }
  288. return false;
  289. }
  290. /**
  291. * Checks whether it is still possible to proceed
  292. *
  293. * @return
  294. */
  295. protected boolean isPossible() {
  296. if (!mHasCompleteCondition) {
  297. return true;
  298. }
  299. if (mCountCompletedBranches &&
  300. (mSucceededCount + mTotalCount - mCounter < mBranches)) {
  301. return false;
  302. }
  303. return true;
  304. }
  305. /**
  306. * Initialize the counter values and decide whether to proceed
  307. *
  308. * @param frame The callFrame
  309. * @param rObjs The RequiredObjects
  310. * @return true, proceed, false, no need to proceed further. false when final counter value
  311. * is less than the start counter value
  312. */
  313. private boolean initialize(ICallFrame frame, RequiredObjects rObjs) {
  314. ForEach lForEach = (ForEach) mAct;
  315. String startCounterString = lForEach.getIterator().getStartCounterValue().getValue();
  316. String finalCounterString = lForEach.getIterator().getFinalCounterValue().getValue();
  317. String branchesString = null;
  318. if (lForEach.getCompletionCondition() != null) {
  319. Branches lbranches = lForEach.getCompletionCondition().getBranches();
  320. branchesString = lbranches.getValue();
  321. String cntCBs = lbranches.getCountCompletedBranchesOnly();
  322. mCountCompletedBranches = (cntCBs != null && cntCBs.equals("yes"));
  323. mHasCompleteCondition = true;
  324. }
  325. try {
  326. mStartCounter = evaluateCounter(rObjs.getInterp(),
  327. frame,
  328. mAct,
  329. startCounterString, /* lenient= */
  330. "false",
  331. "startCounterValue");
  332. if (mStartCounter < 0) {
  333. throw new NumberFormatException(
  334. I18n.loc("BPCOR-6051: ForEach start counter :{0} shouldn't be negative", startCounterString));
  335. }
  336. mFinalCounter = evaluateCounter(rObjs.getInterp(),
  337. frame,
  338. mAct,
  339. finalCounterString, /* lenient= */
  340. "false",
  341. "finalCounterValue");
  342. if (mFinalCounter < 0) {
  343. throw new NumberFormatException(
  344. I18n.loc("BPCOR-6150: ForEach final counter :{0} shouldn't be negative", finalCounterString));
  345. }
  346. if (branchesString != null) {
  347. mBranches = evaluateCounter(rObjs.getInterp(),
  348. frame,
  349. mAct,
  350. branchesString, /* lenient= */
  351. "false",
  352. "branches");
  353. }
  354. if (mBranches < 0) {
  355. throw new NumberFormatException(
  356. I18n.loc("BPCOR-6138: ForEach completion condition :{0} shouldn't be negative", branchesString));
  357. }
  358. } catch (NumberFormatException e) {
  359. if (LOGGER.isLoggable(Level.FINE)) {
  360. LOGGER.log(Level.FINE, I18n.loc("BPCOR-3001: associated forEach block is: {0}", frame.getPC()), e);
  361. }
  362. throw new StandardException(StandardException.Fault.InvalidExpressionValue, e);
  363. }
  364. if (mFinalCounter < mStartCounter) {
  365. return false;
  366. }
  367. mTotalCount = mFinalCounter - mStartCounter + 1;
  368. if (mHasCompleteCondition && (mBranches > mTotalCount)) {
  369. throw new StandardException(StandardException.Fault.InvalidBranchCondition);
  370. }
  371. // If impossible to fulfill the complete condition
  372. if (!isPossible()) {
  373. throw new StandardException(StandardException.Fault.CompletionConditionFailure);
  374. }
  375. return true;
  376. }
  377. /**
  378. * Initialize the completion condition during recovery.
  379. *
  380. * @param frame The callFrame
  381. * @param rObjs The RequiredObjects
  382. * @return true, proceed, false, no need to proceed further
  383. */
  384. private void initCompletionCondition() {
  385. ForEach lForEach = (ForEach) mAct;
  386. if (lForEach.getCompletionCondition() != null) {
  387. Branches lbranches = lForEach.getCompletionCondition().getBranches();
  388. String cntCBs = lbranches.getCountCompletedBranchesOnly();
  389. mCountCompletedBranches = (cntCBs != null && cntCBs.equals("yes"));
  390. mHasCompleteCondition = true;
  391. }
  392. }
  393. /* Adds variable to scope. This variable is also added on to the state object for persistence. */
  394. private void addVariable(ScopeUnitImpl scopeUnit, int counter,
  395. RequiredObjects rObjs, ICallFrame frame) {
  396. ForEach lForEach = (ForEach) mAct;
  397. RVariable var = (RVariable) lForEach.getCounterVariable();
  398. // ForEach counter variable belongs to the child scope of the ForEach construct.
  399. // and hence is not delegated to the scopeUnit to create the variable.
  400. // The variable is created with the child scope unit id as its scope id.
  401. RuntimeVariable counterVar = new RuntimeVariableImpl(var,
  402. scopeUnit.getProcessInstance(), scopeUnit.getScopeGuid());
  403. counterVar.setXSDVariableData(new Integer(counter));
  404. postVarEvent((RVariable) ((ForEach) mAct).getCounterVariable(), counterVar.getXSDVariableData(), rObjs, frame);
  405. scopeUnit.addVariable(counterVar);
  406. }
  407. /**
  408. * Evaluate a boolean XPath expression in the context of the current thread
  409. *
  410. * @param frame
  411. * The current thread
  412. * @param xpath
  413. * expression
  414. * @param lenient
  415. * xpath leniency
  416. *
  417. * @return Result of evaluation
  418. *
  419. * @throws RuntimeException
  420. * DOCUMENT ME!
  421. */
  422. private int evaluateCounter(BPELInterpreter iter, ICallFrame frame, BPELElement element,
  423. String xpath, String lenient, String varName) {
  424. int returnVal = 0;
  425. Object result;
  426. try {
  427. JXPathContext jxpathContext = Utility.newJXPathContext(element, mContext, null);
  428. result = jxpathContext.getValue(xpath);
  429. } catch (JXPathException ex) {
  430. String msg = I18n.loc("BPCOR-6052: Exception while evaluating the xpath {0} " +
  431. "in BPEL({1}) \n at line number {2} " +
  432. "Associated BPEL artifact is: {3}", ex.getMessage(), frame.getProcess().getBPELId(),
  433. element.getLocator().getLineNumber(), element);
  434. LOGGER.log(Level.WARNING, msg);
  435. throw new RuntimeException(msg);
  436. }
  437. if (result instanceof String) {
  438. returnVal = Integer.parseInt((String) result);
  439. } else if (result instanceof Number) {
  440. returnVal = ((Number) result).intValue();
  441. } else {
  442. throw new NumberFormatException(I18n.loc("BPCOR-6055: ForEach counter :{0} is not valid", varName));
  443. }
  444. return returnVal;
  445. }
  446. private void postVarEvent(RVariable variable, Object content, RequiredObjects objs, ICallFrame frame) {
  447. if (frame.getProcessInstance().getMonitorMgr().generateEventsForVariable(variable.getUniqueId())) {
  448. Variable var = new VariableImpl(variable, content, mContext);
  449. Map<VariableEvent.VariableType, List<Variable>> variableMap = new HashMap<VariableType, List<Variable>>();
  450. variableMap.put(VariableEvent.VariableType.COUNTER,
  451. new ArrayList<Variable>());
  452. variableMap.get(VariableEvent.VariableType.COUNTER).add(var);
  453. frame.getProcessInstance().getMonitorMgr().postVariableEvent(this, variableMap, false, null, null);
  454. }
  455. }
  456. }