PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/core/kernel-api/org/spicefactory/parsley/core/messaging/impl/DefaultMessageProcessor.as

https://github.com/wukongiii/Parsley-Core
ActionScript | 336 lines | 219 code | 49 blank | 68 comment | 36 complexity | 7e1a217401ae2e0a215622a36c2375bb MD5 | raw file
  1. /*
  2. * Copyright 2008-2011 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.spicefactory.parsley.core.messaging.impl {
  17. import org.spicefactory.lib.errors.IllegalStateError;
  18. import org.spicefactory.lib.logging.LogContext;
  19. import org.spicefactory.lib.logging.LogUtil;
  20. import org.spicefactory.lib.logging.Logger;
  21. import org.spicefactory.parsley.core.messaging.ErrorPolicy;
  22. import org.spicefactory.parsley.core.messaging.Message;
  23. import org.spicefactory.parsley.core.messaging.MessageProcessor;
  24. import org.spicefactory.parsley.core.messaging.MessageReceiverCache;
  25. import org.spicefactory.parsley.core.messaging.MessageReceiverKind;
  26. import org.spicefactory.parsley.core.messaging.MessageSettings;
  27. import org.spicefactory.parsley.core.messaging.MessageState;
  28. import org.spicefactory.parsley.core.messaging.receiver.MessageErrorHandler;
  29. import org.spicefactory.parsley.core.messaging.receiver.MessageTarget;
  30. /**
  31. * Default implementation of the MessageProcessor interface.
  32. *
  33. * @author Jens Halm
  34. */
  35. public class DefaultMessageProcessor implements MessageProcessor {
  36. private static const log:Logger = LogContext.getLogger(DefaultMessageProcessor);
  37. private var _cache:MessageReceiverCache;
  38. private var remainingProcessors:Array;
  39. private var currentProcessor:Processor;
  40. private var currentError:Error;
  41. private var receiverHandler:Function;
  42. private var _message:Message;
  43. private var _state:MessageState;
  44. private var settings:MessageSettings;
  45. /**
  46. * Creates a new instance.
  47. *
  48. * @param message the message and its settings
  49. * @param cache the receiver selection cache corresponding to the messageType
  50. * @param settings the settings for this processor
  51. * @param receiverHandler the function to invoke for each processed receiver
  52. */
  53. function DefaultMessageProcessor (message:Message, cache:MessageReceiverCache,
  54. settings:MessageSettings, receiverHandler:Function = null) {
  55. this._message = message;
  56. this._cache = cache;
  57. this.settings = settings;
  58. this.receiverHandler = (receiverHandler != null) ? receiverHandler : invokeTarget;
  59. }
  60. /**
  61. * Return a string that can be used to describe the message handled by this processor.
  62. *
  63. * @param action a string describing the action that will be logged, like 'Dispatch', 'Resume' or 'Cancel'
  64. * @param receiverCount the number of remaining receivers this processor will handle
  65. * @return a string that can be used to describe the message handled by this processor
  66. */
  67. protected function getLogString (action:String, receiverCount:int) : String {
  68. return LogUtil.buildLogMessage("{0} message '{1}' with {2} receiver(s)", [action, message.instance, receiverCount]);
  69. }
  70. private function illegalState (methodName:String) : void {
  71. throw new IllegalStateError("Attempt to call " + methodName
  72. + " on MessageProcessor in illegal state: " + state);
  73. }
  74. private function logStatus (action:String) : void {
  75. if (log.isInfoEnabled()) {
  76. var cnt:int = currentProcessor.receiverCount;
  77. if (remainingProcessors.length) cnt += Processor(remainingProcessors[0]).receiverCount;
  78. log.info(getLogString(action, cnt));
  79. }
  80. }
  81. public function proceed () : void {
  82. if (!state) {
  83. start();
  84. }
  85. else {
  86. resume();
  87. }
  88. }
  89. /**
  90. * @inheritDoc
  91. */
  92. public function resume () : void {
  93. if (state != MessageState.SUSPENDED) {
  94. illegalState("resume");
  95. }
  96. logStatus("Resume");
  97. _state = MessageState.ACTIVE;
  98. processReceivers();
  99. }
  100. private function processReceivers () : void {
  101. do {
  102. while (!currentProcessor.hasNext()) {
  103. if (complete()) {
  104. return;
  105. }
  106. currentProcessor = remainingProcessors.shift() as Processor;
  107. }
  108. try {
  109. currentProcessor.proceed();
  110. }
  111. catch (e:Error) {
  112. log.error("Message receiver {0} threw Error: {1}", currentProcessor.currentReceiver, e);
  113. if (!currentProcessor.handleErrors || (e is MessageProcessorError)) {
  114. // avoid the risk of endless loops
  115. throw e;
  116. }
  117. if (!handleError(e)) return;
  118. }
  119. } while (state == MessageState.ACTIVE);
  120. }
  121. /**
  122. * @inheritDoc
  123. */
  124. public function get state () : MessageState {
  125. return _state;
  126. }
  127. private function complete () : Boolean {
  128. if (remainingProcessors.length == 0) {
  129. currentProcessor = null;
  130. _state = MessageState.COMPLETE;
  131. return true;
  132. }
  133. return false;
  134. }
  135. /**
  136. * @private
  137. */
  138. internal function start () : void {
  139. createProcessors();
  140. logStatus("Dispatch");
  141. _state = MessageState.ACTIVE;
  142. processReceivers();
  143. }
  144. /**
  145. * @inheritDoc
  146. */
  147. public function suspend () : void {
  148. if (state != MessageState.ACTIVE) {
  149. illegalState("suspend");
  150. }
  151. logStatus("Suspend");
  152. _state = MessageState.SUSPENDED;
  153. }
  154. /**
  155. * @inheritDoc
  156. */
  157. public function cancel () : void {
  158. if (state == MessageState.CANCELLED) {
  159. return;
  160. }
  161. logStatus("Cancel");
  162. _state = MessageState.CANCELLED;
  163. currentProcessor = null;
  164. remainingProcessors = null;
  165. }
  166. private function handleError (e:Error) : Boolean {
  167. var handlers:Array = new Array();
  168. var errorHandlers:Array = (_message) ? cache.getReceivers(MessageReceiverKind.ERROR_HANDLER, _message.selector) : [];
  169. for each (var errorHandler:MessageErrorHandler in errorHandlers) {
  170. if (e is errorHandler.errorType) {
  171. handlers.push(errorHandler);
  172. }
  173. }
  174. if (log.isInfoEnabled()) {
  175. log.info("Select " + handlers.length + " out of " + errorHandlers.length + " error handlers");
  176. }
  177. if (handlers.length > 0) {
  178. currentError = e;
  179. remainingProcessors.unshift(currentProcessor);
  180. currentProcessor = new Processor(handlers, invokeErrorHandler, false);
  181. return true;
  182. }
  183. else {
  184. return unhandledError(e);
  185. }
  186. }
  187. private function unhandledError (e:Error) : Boolean {
  188. if (settings.unhandledError == ErrorPolicy.RETHROW) {
  189. throw new MessageProcessorError("Error in message receiver", e);
  190. }
  191. else if (settings.unhandledError == ErrorPolicy.ABORT) {
  192. log.info("Unhandled error - abort message processor");
  193. return false;
  194. }
  195. else {
  196. log.info("Unhandled error - continue message processing");
  197. return true;
  198. }
  199. }
  200. private function invokeTarget (target:MessageTarget) : void {
  201. target.handleMessage(this);
  202. }
  203. private function invokeErrorHandler (errorHandler:MessageErrorHandler) : void {
  204. errorHandler.handleError(this, currentError);
  205. }
  206. /**
  207. * @inheritDoc
  208. */
  209. public function rewind () : void {
  210. if (state == MessageState.CANCELLED) {
  211. illegalState("rewind");
  212. }
  213. logStatus("Rewind");
  214. createProcessors();
  215. }
  216. private function createProcessors () : void {
  217. currentProcessor = new Processor(fetchReceivers(), receiverHandler);
  218. remainingProcessors = [];
  219. }
  220. /**
  221. * Fetches the receivers for the message type and receiver kind this processor handles.
  222. *
  223. * @return the receivers for the message type and receiver kind this processor handles
  224. */
  225. protected function fetchReceivers () : Array {
  226. return cache.getReceivers(MessageReceiverKind.TARGET, _message.selector);
  227. }
  228. /**
  229. * The receiver cache for the message type this processor handles
  230. */
  231. protected function get cache () : MessageReceiverCache {
  232. return _cache;
  233. }
  234. /**
  235. * @inheritDoc
  236. */
  237. public function get message () : Message {
  238. return (_message);
  239. }
  240. /**
  241. * @inheritDoc
  242. */
  243. public function sendResponse (msg:Object, selector:* = null) : void {
  244. if (message && message.senderContext) {
  245. message.senderContext.scopeManager.dispatchMessage(msg, selector);
  246. }
  247. else {
  248. throw new IllegalStateError("Unable to send response for message "
  249. + message + ": sender Context unknown");
  250. }
  251. }
  252. }
  253. }
  254. import org.spicefactory.lib.errors.NestedError;
  255. import org.spicefactory.parsley.core.messaging.receiver.MessageReceiver;
  256. class Processor {
  257. private var receivers:Array;
  258. private var handler:Function;
  259. private var currentIndex:uint = 0;
  260. internal var handleErrors:Boolean;
  261. function Processor (receivers:Array, handler:Function, handleErrors:Boolean = true) {
  262. this.receivers = receivers;
  263. this.handler = handler;
  264. this.handleErrors = handleErrors;
  265. receivers.sortOn("order", Array.NUMERIC);
  266. }
  267. internal function hasNext () : Boolean {
  268. return (receivers.length > currentIndex);
  269. }
  270. internal function get receiverCount () : uint {
  271. return receivers.length;
  272. }
  273. internal function rewind () : void {
  274. currentIndex = 0;
  275. }
  276. internal function get currentReceiver () : MessageReceiver {
  277. return (hasNext()) ? receivers[currentIndex] as MessageReceiver : null;
  278. }
  279. internal function proceed () : void {
  280. handler(receivers[currentIndex++]);
  281. }
  282. }
  283. class MessageProcessorError extends NestedError {
  284. public function MessageProcessorError (message:String = "", cause:Error = null) {
  285. super(message, cause);
  286. }
  287. }