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