1 #pragma warning disable 1634, 1691 2 3 namespace System.Workflow.ComponentModel 4 { 5 #region Imports 6 7 using System; 8 using System.Diagnostics; 9 using System.Collections; 10 using System.Collections.Generic; 11 using System.Collections.ObjectModel; 12 using System.Workflow.ComponentModel.Design; 13 using System.Runtime.Serialization; 14 using System.IO; 15 using System.Runtime.Serialization.Formatters.Binary; 16 using System.Workflow.ComponentModel.Serialization; 17 #endregion 18 19 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] 20 public sealed class ActivityExecutionContextManager 21 { 22 #region Data members and constructor 23 24 private ActivityExecutionContext ownerContext = null; 25 private List<ActivityExecutionContext> executionContexts = new List<ActivityExecutionContext>(); 26 ActivityExecutionContextManager(ActivityExecutionContext ownerContext)27 internal ActivityExecutionContextManager(ActivityExecutionContext ownerContext) 28 { 29 this.ownerContext = ownerContext; 30 31 // Populate the child collection. 32 IList<Activity> activeContexts = (IList<Activity>)this.ownerContext.Activity.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty); 33 if (activeContexts != null) 34 { 35 foreach (Activity activeContextActivity in activeContexts) 36 this.executionContexts.Add(new ActivityExecutionContext(activeContextActivity)); 37 } 38 } 39 40 #endregion 41 42 #region Public members 43 44 public ReadOnlyCollection<ActivityExecutionContext> ExecutionContexts 45 { 46 get 47 { 48 if (this.ownerContext == null) 49 #pragma warning suppress 56503 50 throw new ObjectDisposedException("ActivityExecutionContextManager"); 51 52 return new ReadOnlyCollection<ActivityExecutionContext>(this.executionContexts); 53 } 54 } 55 CreateExecutionContext(Activity activity)56 public ActivityExecutionContext CreateExecutionContext(Activity activity) 57 { 58 if (this.ownerContext == null) 59 throw new ObjectDisposedException("ActivityExecutionContextManager"); 60 61 if (activity == null) 62 throw new ArgumentNullException("activity"); 63 64 if (!this.ownerContext.IsValidChild(activity, true)) 65 throw new ArgumentException(SR.GetString(SR.AEC_InvalidActivity), "activity"); 66 67 Activity copiedActivity = activity.Clone(); 68 ((IDependencyObjectAccessor)copiedActivity).InitializeInstanceForRuntime(this.ownerContext.Activity.WorkflowCoreRuntime); 69 70 //Reset the cloned tree for execution. 71 Queue<Activity> activityQueue = new Queue<Activity>(); 72 activityQueue.Enqueue(copiedActivity); 73 74 while (activityQueue.Count != 0) 75 { 76 Activity clonedActivity = activityQueue.Dequeue(); 77 if (clonedActivity.ExecutionStatus != ActivityExecutionStatus.Initialized) 78 { 79 clonedActivity.ResetAllKnownDependencyProperties(); 80 CompositeActivity compositeActivity = clonedActivity as CompositeActivity; 81 82 if (compositeActivity != null) 83 { 84 for (int i = 0; i < compositeActivity.EnabledActivities.Count; ++i) 85 { 86 activityQueue.Enqueue(compositeActivity.EnabledActivities[i]); 87 } 88 89 ISupportAlternateFlow alternateFlow = compositeActivity as ISupportAlternateFlow; 90 91 if (alternateFlow != null) 92 { 93 for (int i = 0; i < alternateFlow.AlternateFlowActivities.Count; ++i) 94 { 95 activityQueue.Enqueue(alternateFlow.AlternateFlowActivities[i]); 96 } 97 } 98 } 99 } 100 } 101 102 // get active context activities and add it to this one 103 IList<Activity> activeContexts = (IList<Activity>)this.ownerContext.Activity.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty); 104 if (activeContexts == null) 105 { 106 activeContexts = new List<Activity>(); 107 this.ownerContext.Activity.ContextActivity.SetValue(Activity.ActiveExecutionContextsProperty, activeContexts); 108 } 109 activeContexts.Add(copiedActivity); 110 111 // prepare the copied activity as a context activity 112 ActivityExecutionContextInfo contextInfo = new ActivityExecutionContextInfo(activity.QualifiedName, this.ownerContext.WorkflowCoreRuntime.GetNewContextActivityId(), Guid.NewGuid(), this.ownerContext.ContextId); 113 copiedActivity.SetValue(Activity.ActivityExecutionContextInfoProperty, contextInfo); 114 copiedActivity.SetValue(Activity.ActivityContextGuidProperty, contextInfo.ContextGuid); 115 ActivityExecutionContext newExecutionContext = null; 116 try 117 { 118 // inform workflow runtime 119 this.ownerContext.Activity.WorkflowCoreRuntime.RegisterContextActivity(copiedActivity); 120 121 // return the new context 122 newExecutionContext = new ActivityExecutionContext(copiedActivity); 123 this.executionContexts.Add(newExecutionContext); 124 newExecutionContext.InitializeActivity(newExecutionContext.Activity); 125 return newExecutionContext; 126 } 127 catch (Exception) 128 { 129 if (newExecutionContext != null) 130 { 131 this.CompleteExecutionContext(newExecutionContext); 132 } 133 else 134 { 135 activeContexts.Remove(copiedActivity); 136 } 137 throw; 138 } 139 } 140 CompleteExecutionContext(ActivityExecutionContext childContext)141 public void CompleteExecutionContext(ActivityExecutionContext childContext) 142 { 143 if (this.ownerContext == null) 144 throw new ObjectDisposedException("ActivityExecutionContextManager"); 145 146 CompleteExecutionContext(childContext, false); 147 } 148 CompleteExecutionContext(ActivityExecutionContext childContext, bool forcePersist)149 public void CompleteExecutionContext(ActivityExecutionContext childContext, bool forcePersist) 150 { 151 if (this.ownerContext == null) 152 throw new ObjectDisposedException("ActivityExecutionContextManager"); 153 154 if (childContext == null) 155 throw new ArgumentNullException("childContext"); 156 157 if (childContext.Activity == null) 158 throw new ArgumentException("childContext", SR.GetString(SR.Error_MissingActivityProperty)); 159 160 if (childContext.Activity.ContextActivity == null) 161 throw new ArgumentException("childContext", SR.GetString(SR.Error_MissingContextActivityProperty)); 162 163 if (!this.executionContexts.Contains(childContext)) 164 throw new ArgumentException(); 165 166 if (childContext.Activity.ContextActivity.ExecutionStatus != ActivityExecutionStatus.Closed && childContext.Activity.ContextActivity.ExecutionStatus != ActivityExecutionStatus.Initialized) 167 throw new InvalidOperationException(SR.GetString(System.Globalization.CultureInfo.CurrentCulture, SR.Error_CannotCompleteContext)); 168 169 // make sure that this is in the active contexts collections 170 ActivityExecutionContextInfo childContextInfo = childContext.Activity.ContextActivity.GetValue(Activity.ActivityExecutionContextInfoProperty) as ActivityExecutionContextInfo; 171 IList<Activity> activeContexts = (IList<Activity>)this.ownerContext.Activity.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty); 172 if (activeContexts == null || !activeContexts.Contains(childContext.Activity.ContextActivity)) 173 throw new ArgumentException(); 174 175 // add it to completed contexts collection 176 bool needsCompensation = childContext.Activity.NeedsCompensation; 177 if (needsCompensation || forcePersist) 178 { 179 // add it to completed contexts 180 List<ActivityExecutionContextInfo> completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as List<ActivityExecutionContextInfo>; 181 if (completedContexts == null) 182 { 183 completedContexts = new List<ActivityExecutionContextInfo>(); 184 this.ownerContext.Activity.ContextActivity.SetValue(Activity.CompletedExecutionContextsProperty, completedContexts); 185 } 186 187 if (needsCompensation) 188 childContextInfo.Flags = PersistFlags.NeedsCompensation; 189 if (forcePersist) 190 childContextInfo.Flags |= PersistFlags.ForcePersist; 191 192 childContextInfo.SetCompletedOrderId(this.ownerContext.Activity.IncrementCompletedOrderId()); 193 completedContexts.Add(childContextInfo); 194 195 // ask runtime to save the context activity 196 this.ownerContext.Activity.WorkflowCoreRuntime.SaveContextActivity(childContext.Activity); 197 } 198 199 // remove it from active contexts 200 activeContexts.Remove(childContext.Activity.ContextActivity); 201 this.executionContexts.Remove(childContext); 202 203 //Case for those context which has compensatable child context, when those context 204 //are completed at the end of Compensation chain we need to uninitialize the context 205 //activity associated to them. 206 if (childContext.Activity.ContextActivity.CanUninitializeNow && childContext.Activity.ContextActivity.ExecutionResult != ActivityExecutionResult.Uninitialized) 207 { 208 childContext.Activity.ContextActivity.Uninitialize(this.ownerContext.Activity.RootActivity.WorkflowCoreRuntime); 209 childContext.Activity.ContextActivity.SetValue(Activity.ExecutionResultProperty, ActivityExecutionResult.Uninitialized); 210 } 211 212 // unregister it from runtime 213 this.ownerContext.Activity.WorkflowCoreRuntime.UnregisterContextActivity(childContext.Activity); 214 215 if (!(needsCompensation || forcePersist)) 216 { 217 childContext.Activity.Dispose(); 218 } 219 } 220 GetExecutionContext(Activity activity)221 public ActivityExecutionContext GetExecutionContext(Activity activity) 222 { 223 if (this.ownerContext == null) 224 throw new ObjectDisposedException("ActivityExecutionContextManager"); 225 226 if (activity == null) 227 throw new ArgumentNullException("activity"); 228 229 ActivityExecutionContextInfo contextInfo = activity.GetValue(Activity.ActivityExecutionContextInfoProperty) as ActivityExecutionContextInfo; 230 231 // Returns the first context for an activity with the same qualified name. 232 foreach (ActivityExecutionContext context in ExecutionContexts) 233 { 234 if (contextInfo == null) //Template being passed. 235 { 236 if (context.Activity.ContextActivity.QualifiedName == activity.QualifiedName) 237 return context; 238 } 239 else //Context Sensitive Activity 240 { 241 if (context.ContextGuid.Equals(contextInfo.ContextGuid)) 242 return context; 243 } 244 } 245 return null; 246 } 247 248 public IEnumerable<Guid> PersistedExecutionContexts 249 { 250 get 251 { 252 if (this.ownerContext == null) 253 #pragma warning suppress 56503 254 throw new ObjectDisposedException("ActivityExecutionContextManager"); 255 256 List<ActivityExecutionContextInfo> completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as List<ActivityExecutionContextInfo>; 257 completedContexts = (completedContexts == null) ? new List<ActivityExecutionContextInfo>() : completedContexts; 258 259 List<Guid> persistedContexts = new List<Guid>(); 260 foreach (ActivityExecutionContextInfo contextInfo in completedContexts) 261 if ((contextInfo.Flags & PersistFlags.ForcePersist) != 0) 262 persistedContexts.Add(contextInfo.ContextGuid); 263 264 return persistedContexts; 265 } 266 } 267 GetPersistedExecutionContext(Guid contextGuid)268 public ActivityExecutionContext GetPersistedExecutionContext(Guid contextGuid) 269 { 270 if (this.ownerContext == null) 271 throw new ObjectDisposedException("ActivityExecutionContextManager"); 272 273 // Check if child execution context exists. 274 IList<ActivityExecutionContextInfo> completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as IList<ActivityExecutionContextInfo>; 275 if (completedContexts == null) 276 throw new ArgumentException(); 277 278 ActivityExecutionContextInfo contextInfo = null; 279 foreach (ActivityExecutionContextInfo completedContextInfo in completedContexts) 280 { 281 if (completedContextInfo.ContextGuid == contextGuid && ((completedContextInfo.Flags & PersistFlags.ForcePersist) != 0)) 282 { 283 contextInfo = completedContextInfo; 284 break; 285 } 286 } 287 288 if (contextInfo == null) 289 throw new ArgumentException(); 290 291 // The caller would have to close the AEC with forcepersist the next time 292 // around. 293 contextInfo.Flags &= ~PersistFlags.ForcePersist; 294 return DiscardPersistedExecutionContext(contextInfo); 295 } 296 297 #endregion 298 Dispose()299 internal void Dispose() 300 { 301 if (this.ownerContext != null) 302 { 303 foreach (ActivityExecutionContext executionContext in this.ExecutionContexts) 304 ((IDisposable)executionContext).Dispose(); 305 this.ownerContext = null; 306 } 307 } 308 309 #region Internal members 310 311 internal ReadOnlyCollection<ActivityExecutionContextInfo> CompletedExecutionContexts 312 { 313 get 314 { 315 List<ActivityExecutionContextInfo> completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as List<ActivityExecutionContextInfo>; 316 completedContexts = (completedContexts == null) ? new List<ActivityExecutionContextInfo>() : completedContexts; 317 return completedContexts.AsReadOnly(); 318 } 319 } 320 DiscardPersistedExecutionContext(ActivityExecutionContextInfo contextInfo)321 internal ActivityExecutionContext DiscardPersistedExecutionContext(ActivityExecutionContextInfo contextInfo) 322 { 323 if (contextInfo == null) 324 throw new ArgumentNullException("contextInfo"); 325 326 // check if child execution context 327 IList<ActivityExecutionContextInfo> completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as IList<ActivityExecutionContextInfo>; 328 if (completedContexts == null || !completedContexts.Contains(contextInfo)) 329 throw new ArgumentException(); 330 331 // revoke from persistence service 332 Activity revokedActivity = this.ownerContext.WorkflowCoreRuntime.LoadContextActivity(contextInfo, this.ownerContext.Activity.ContextActivity.GetActivityByName(contextInfo.ActivityQualifiedName)); 333 ((IDependencyObjectAccessor)revokedActivity).InitializeInstanceForRuntime(this.ownerContext.Activity.WorkflowCoreRuntime); 334 335 // add it back to active contexts 336 IList<Activity> activeContexts = (IList<Activity>)this.ownerContext.Activity.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty); 337 if (activeContexts == null) 338 { 339 activeContexts = new List<Activity>(); 340 this.ownerContext.Activity.ContextActivity.SetValue(Activity.ActiveExecutionContextsProperty, activeContexts); 341 } 342 activeContexts.Add(revokedActivity); 343 344 // inform workflow runtime 345 this.ownerContext.Activity.WorkflowCoreRuntime.RegisterContextActivity(revokedActivity); 346 347 // return the new context 348 ActivityExecutionContext revokedContext = new ActivityExecutionContext(revokedActivity); 349 this.executionContexts.Add(revokedContext); 350 System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Information, 0, "Revoking context {0}:{1}", revokedContext.ContextId, revokedContext.Activity.ContextActivity.QualifiedName); 351 352 // remove it from completed contexts 353 completedContexts.Remove(contextInfo); 354 return revokedContext; 355 } 356 357 #endregion 358 } 359 360 #region Class ActivityExecutionContextInfo 361 362 [Serializable] 363 [Flags] 364 internal enum PersistFlags : byte 365 { 366 NeedsCompensation = 1, 367 ForcePersist = 2 368 } 369 370 [Serializable] 371 internal sealed class ActivityExecutionContextInfo 372 { 373 private string qualifiedID = string.Empty; 374 private int contextId = -1; 375 private Guid contextGuid = Guid.Empty; // 376 private int parentContextId = -1; 377 private int completedOrderId = -1; 378 private PersistFlags flags = 0; 379 ActivityExecutionContextInfo(string qualifiedName, int contextId, Guid contextGuid, int parentContextId)380 internal ActivityExecutionContextInfo(string qualifiedName, int contextId, Guid contextGuid, int parentContextId) 381 { 382 this.qualifiedID = qualifiedName; 383 this.contextId = contextId; 384 this.contextGuid = contextGuid; 385 this.parentContextId = parentContextId; 386 } 387 388 internal int ContextId 389 { 390 get 391 { 392 return this.contextId; 393 } 394 } 395 396 public Guid ContextGuid 397 { 398 get 399 { 400 return this.contextGuid; 401 } 402 } 403 404 public string ActivityQualifiedName 405 { 406 get 407 { 408 return this.qualifiedID; 409 } 410 } 411 412 public int CompletedOrderId 413 { 414 get 415 { 416 return this.completedOrderId; 417 } 418 } 419 420 internal int ParentContextId 421 { 422 get 423 { 424 return this.parentContextId; 425 } 426 } 427 SetCompletedOrderId(int completedOrderId)428 internal void SetCompletedOrderId(int completedOrderId) 429 { 430 this.completedOrderId = completedOrderId; 431 } 432 433 internal PersistFlags Flags 434 { 435 get 436 { 437 return this.flags; 438 } 439 440 set 441 { 442 this.flags = value; 443 } 444 } 445 GetHashCode()446 public override int GetHashCode() 447 { 448 return contextGuid.GetHashCode(); 449 } 450 Equals(object obj)451 public override bool Equals(object obj) 452 { 453 ActivityExecutionContextInfo otherContextInfo = obj as ActivityExecutionContextInfo; 454 455 if (otherContextInfo != null) 456 { 457 return this.ContextGuid.Equals(otherContextInfo.ContextGuid); 458 } 459 return false; 460 } 461 } 462 463 #endregion 464 } 465