1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.Workflow.Activities
6 {
7     using System;
8     using System.Collections;
9     using System.Collections.Generic;
10     using System.Collections.Specialized;
11     using System.ComponentModel;
12     using System.ComponentModel.Design;
13     using System.ComponentModel.Design.Serialization;
14     using System.Diagnostics.CodeAnalysis;
15     using System.ServiceModel;
16     using System.ServiceModel.Channels;
17     using System.ServiceModel.Dispatcher;
18     using System.Workflow.ComponentModel;
19     using System.Workflow.ComponentModel.Design;
20     using System.Workflow.ComponentModel.Serialization;
21     using System.Xml;
22 
23     [DesignerSerializer(typeof(DependencyObjectCodeDomSerializer), typeof(CodeDomSerializer))]
24     [TypeConverter(typeof(ChannelTokenTypeConverter))]
25     [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
26     public sealed class ChannelToken : DependencyObject, IPropertyValueProvider
27     {
28         [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
29         internal static readonly DependencyProperty EndpointNameProperty =
30             DependencyProperty.Register("EndpointName",
31             typeof(string),
32             typeof(ChannelToken),
33             new PropertyMetadata(null));
34 
35         [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
36         internal static readonly DependencyProperty NameProperty =
37             DependencyProperty.Register("Name",
38             typeof(string),
39             typeof(ChannelToken),
40             new PropertyMetadata(null, DependencyPropertyOptions.Metadata,
41             new Attribute[] { new BrowsableAttribute(false) }));
42 
43         [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
44         internal static readonly DependencyProperty OwnerActivityNameProperty =
45             DependencyProperty.Register("OwnerActivityName",
46             typeof(string),
47             typeof(ChannelToken),
48             new PropertyMetadata(null, DependencyPropertyOptions.Metadata,
49             new Attribute[] { new TypeConverterAttribute(typeof(PropertyValueProviderTypeConverter)) }));
50 
ChannelToken()51         public ChannelToken()
52         {
53         }
54 
ChannelToken(string name)55         internal ChannelToken(string name)
56         {
57             this.Name = name;
58         }
59 
60         [DefaultValue(null)]
61         [SR2Description(SR2DescriptionAttribute.ChannelToken_EndpointName_Description)]
62         public string EndpointName
63         {
64             get
65             {
66                 return (string) GetValue(EndpointNameProperty);
67             }
68 
69             set
70             {
71                 SetValue(EndpointNameProperty, value);
72             }
73         }
74 
75         [Browsable(false)]
76         [DefaultValue(null)]
77         [SR2Description(SR2DescriptionAttribute.ChannelToken_Name_Description)]
78         public string Name
79         {
80             get
81             {
82                 return (string) GetValue(NameProperty);
83             }
84             set
85             {
86                 SetValue(NameProperty, value);
87             }
88         }
89 
90         [DefaultValue(null)]
91         [TypeConverter(typeof(PropertyValueProviderTypeConverter))]
92         [SR2Description(SR2DescriptionAttribute.ChannelToken_OwnerActivityName_Description)]
93         public string OwnerActivityName
94         {
95             get
96             {
97                 return (string) GetValue(OwnerActivityNameProperty);
98             }
99 
100             set
101             {
102                 SetValue(OwnerActivityNameProperty, value);
103             }
104         }
105 
IPropertyValueProvider.GetPropertyValues(ITypeDescriptorContext context)106         ICollection IPropertyValueProvider.GetPropertyValues(ITypeDescriptorContext context)
107         {
108             StringCollection names = new StringCollection();
109 
110             if (string.Equals(context.PropertyDescriptor.Name, "OwnerActivityName", StringComparison.Ordinal))
111             {
112                 ISelectionService selectionService = context.GetService(typeof(ISelectionService)) as ISelectionService;
113                 if (selectionService != null && selectionService.SelectionCount == 1 && selectionService.PrimarySelection is Activity)
114                 {
115                     // add empty string as an option
116                     //
117                     names.Add(string.Empty);
118 
119                     Activity currentActivity = selectionService.PrimarySelection as Activity;
120 
121                     foreach (Activity activity in GetEnclosingCompositeActivities(currentActivity))
122                     {
123                         string activityId = activity.QualifiedName;
124                         if (!names.Contains(activityId))
125                         {
126                             names.Add(activityId);
127                         }
128                     }
129                 }
130             }
131             return names;
132         }
133 
GetLogicalChannel(Activity activity, ChannelToken endpoint, Type contractType)134         internal static LogicalChannel GetLogicalChannel(Activity activity,
135             ChannelToken endpoint,
136             Type contractType)
137         {
138             if (activity == null)
139             {
140                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
141             }
142             if (endpoint == null)
143             {
144                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
145             }
146             if (contractType == null)
147             {
148                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
149             }
150 
151             return GetLogicalChannel(activity, endpoint.Name, endpoint.OwnerActivityName, contractType);
152         }
153 
GetLogicalChannel(Activity activity, string name, string ownerActivityName, Type contractType)154         internal static LogicalChannel GetLogicalChannel(Activity activity,
155             string name,
156             string ownerActivityName,
157             Type contractType)
158         {
159             if (activity == null)
160             {
161                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
162             }
163             if (string.IsNullOrEmpty(name))
164             {
165                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("name",
166                     SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
167             }
168             if (contractType == null)
169             {
170                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
171             }
172 
173             Activity contextActivity = activity.ContextActivity;
174             Activity owner = null;
175 
176             if (contextActivity == null)
177             {
178                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
179                     new InvalidOperationException(SR2.GetString(SR2.Error_ContextOwnerActivityMissing)));
180             }
181 
182             if (string.IsNullOrEmpty(ownerActivityName))
183             {
184                 owner = contextActivity.RootActivity;
185             }
186             else
187             {
188                 while (contextActivity != null)
189                 {
190                     owner = contextActivity.GetActivityByName(ownerActivityName, true);
191                     if (owner != null)
192                     {
193                         break;
194                     }
195 
196                     contextActivity = contextActivity.Parent;
197                     if (contextActivity != null)
198                     {
199                         contextActivity = contextActivity.ContextActivity;
200                     }
201                 }
202             }
203 
204             if (owner == null && !string.IsNullOrEmpty(ownerActivityName))
205             {
206                 owner = Helpers.ParseActivityForBind(activity, ownerActivityName);
207             }
208 
209             if (owner == null)
210             {
211                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
212                     new InvalidOperationException(SR2.GetString(SR2.Error_ContextOwnerActivityMissing)));
213             }
214 
215             LogicalChannel logicalChannel = null;
216 
217             LogicalChannelCollection collection =
218                 owner.GetValue(LogicalChannelCollection.LogicalChannelCollectionProperty) as LogicalChannelCollection;
219             if (collection == null)
220             {
221                 collection = new LogicalChannelCollection();
222                 owner.SetValue(LogicalChannelCollection.LogicalChannelCollectionProperty, collection);
223 
224                 logicalChannel = new LogicalChannel(name, contractType);
225                 collection.Add(logicalChannel);
226             }
227             else if (!collection.Contains(name))
228             {
229                 logicalChannel = new LogicalChannel(name, contractType);
230                 collection.Add(logicalChannel);
231             }
232             else
233             {
234                 logicalChannel = collection[name];
235             }
236 
237             if (logicalChannel.ContractType != contractType)
238             {
239                 logicalChannel = null;
240             }
241 
242             return logicalChannel;
243         }
244 
Register(Activity activity, ChannelToken endpoint, Type contractType)245         internal static LogicalChannel Register(Activity activity,
246             ChannelToken endpoint,
247             Type contractType)
248         {
249             if (activity == null)
250             {
251                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
252             }
253             if (endpoint == null)
254             {
255                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
256             }
257             if (contractType == null)
258             {
259                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
260             }
261 
262             LogicalChannel logicalChannel = GetLogicalChannel(activity, endpoint, contractType);
263             if (logicalChannel == null)
264             {
265                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
266                     new InvalidOperationException(SR2.GetString(SR2.Error_FailedToRegisterChannel, endpoint.Name)));
267             }
268 
269             return logicalChannel;
270         }
271 
GetEnclosingCompositeActivities(Activity startActivity)272         private static IEnumerable GetEnclosingCompositeActivities(Activity startActivity)
273         {
274             Activity currentActivity = null;
275             Stack<Activity> activityStack = new Stack<Activity>();
276             activityStack.Push(startActivity);
277 
278             while ((currentActivity = activityStack.Pop()) != null)
279             {
280                 if (currentActivity.Enabled)
281                 {
282                     yield return currentActivity;
283                 }
284                 activityStack.Push(currentActivity.Parent);
285             }
286             yield break;
287         }
288     }
289 }
290