Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Workflow.ComponentModel / Shared / CompModHelpers.cs
1 // Copyright (c) Microsoft Corporation. All rights reserved. 
2 //  
3 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
4 // WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
5 // WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
6 // THE ENTIRE RISK OF USE OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE 
7 // AND INFORMATION REMAINS WITH THE USER. 
8
9
10 /*********************************************************************
11  * NOTE: A copy of this file exists at: WF\Activities\Common
12  * The two files must be kept in [....].  Any change made here must also
13  * be made to WF\Activities\Common\CompModHelpers.cs
14 *********************************************************************/
15 namespace System.Workflow.ComponentModel.Design
16 {
17     using System;
18     using System.CodeDom;
19     using System.Collections;
20     using System.Collections.Generic;
21     using System.ComponentModel;
22     using System.Diagnostics;
23     using System.ComponentModel.Design;
24     using System.ComponentModel.Design.Serialization;
25     using System.Workflow.ComponentModel.Serialization;
26     using System.IO;
27     using System.Runtime.Serialization.Formatters.Binary;
28     using System.Windows.Forms;
29     using System.Drawing;
30     using System.Drawing.Design;
31     using System.Workflow.ComponentModel;
32     using System.Workflow.ComponentModel.Compiler;
33     using System.Text;
34     using System.Reflection;
35     using System.Xml;
36     using System.Globalization;
37     using Microsoft.Win32;
38     using System.Runtime.InteropServices;
39     using System.Diagnostics.CodeAnalysis;
40
41     #region Class Helpers
42     internal static class Helpers
43     {
44         private static readonly string VSExtensionProductRegistrySubKey = "Visual Studio Ext for Windows Workflow";
45         // 
46
47         internal static readonly string ProductRootRegKey = @"SOFTWARE\Microsoft\Net Framework Setup\NDP\v4.0\Setup\Windows Workflow Foundation";
48         internal static readonly string ProductInstallDirectory = GetInstallDirectory(false);
49         internal static readonly string ProductSDKInstallDirectory = GetInstallDirectory(true);
50         internal static readonly string TypeProviderAssemblyRegValueName = "References";
51
52         private static readonly string ProductRootRegKey30 = @"SOFTWARE\Microsoft\Net Framework Setup\NDP\v3.0\Setup\Windows Workflow Foundation";
53         internal static readonly string ProductInstallDirectory30 = GetInstallDirectory30();
54
55         private const string ProductCode = "{B644FB52-BB3D-4C43-80EC-57644210536A}";
56         private const string ProductSDKCode = "{C8A7718A-FF6D-4DDC-AE36-BBF968D6799B}";
57         private const string INSTALLPROPERTY_INSTALLLOCATION = "InstallLocation";
58
59         internal const int FILENAME_MAX = 260; //"stdio.h"
60
61         [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", Justification = "LastIndexOf(\"\\\") not a security issue.")]
62         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
63         internal static string PerUserRegistryKey
64         {
65             get
66             {
67                 string keyPath = String.Empty;
68                 using (RegistryKey userRegistryKey = Application.UserAppDataRegistry)
69                 {
70                     keyPath = userRegistryKey.ToString().Substring(Registry.CurrentUser.ToString().Length + 1);
71                     keyPath = keyPath.Substring(0, keyPath.LastIndexOf("\\"));
72                     keyPath += "\\" + VSExtensionProductRegistrySubKey;
73                 }
74                 return keyPath;
75             }
76         }
77
78         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
79         private static string TypeProviderRegistryKeyPath
80         {
81             get
82             {
83                 return PerUserRegistryKey + "\\TypeProvider";
84             }
85         }
86
87         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
88         internal static bool IsFileNameValid(string fileName)
89         {
90             int length = Path.GetInvalidPathChars().GetLength(0) + 5;
91             char[] invalidChars = new char[length];
92             Path.GetInvalidPathChars().CopyTo(invalidChars, 0);
93             invalidChars[length - 5] = ':';
94             invalidChars[length - 4] = '?';
95             invalidChars[length - 3] = '*';
96             invalidChars[length - 2] = '/';
97             invalidChars[length - 1] = '\\';
98
99             return (fileName != null &&
100                     fileName.Length != 0 &&
101                     fileName.Length <= FILENAME_MAX &&
102                     fileName.IndexOfAny(invalidChars) == -1);
103         }
104
105         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
106         internal static bool AreAllActivities(ICollection c)
107         {
108             if (c == null)
109                 throw new ArgumentNullException("c");
110
111             foreach (object obj in c)
112             {
113                 if (!(obj is Activity))
114                     return false;
115             }
116             return true;
117         }
118
119         // this will return IDictionary, whose keys are parent and value is arraylist of child activities
120         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
121         internal static IDictionary PairUpCommonParentActivities(ICollection activities)
122         {
123             if (activities == null)
124                 throw new ArgumentNullException("activities");
125
126             Hashtable commonParentActivities = new Hashtable();
127             foreach (Activity activity in activities)
128             {
129                 if (activity.Parent != null)
130                 {
131                     ArrayList childActivities = (ArrayList)commonParentActivities[activity.Parent];
132                     if (childActivities == null)
133                     {
134                         childActivities = new ArrayList();
135                         commonParentActivities.Add(activity.Parent, childActivities);
136                     }
137                     childActivities.Add(activity);
138                 }
139             }
140             return commonParentActivities;
141         }
142
143         // this will remove any activity from the collection whose parent is already there in the collection
144         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
145         internal static Activity[] GetTopLevelActivities(ICollection activities)
146         {
147             if (activities == null)
148                 throw new ArgumentNullException("activities");
149
150             List<Activity> filteredActivities = new List<Activity>();
151             foreach (object obj in activities)
152             {
153                 Activity activity = obj as Activity;
154                 if (activity != null)
155                 {
156                     bool foundParent = false;
157                     Activity parentActivity = activity.Parent;
158                     while (parentActivity != null && !foundParent)
159                     {
160                         foreach (object obj2 in activities)
161                         {
162                             if (obj2 == parentActivity)
163                             {
164                                 foundParent = true;
165                                 break;
166                             }
167                         }
168                         parentActivity = parentActivity.Parent;
169                     }
170
171                     if (!foundParent)
172                         filteredActivities.Add(activity);
173                 }
174             }
175             return filteredActivities.ToArray();
176         }
177
178         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
179         internal static Activity[] GetNestedActivities(CompositeActivity compositeActivity)
180         {
181
182             if (compositeActivity == null)
183                 throw new ArgumentNullException("compositeActivity");
184
185             IList<Activity> childActivities = null;
186             ArrayList nestedActivities = new ArrayList();
187             Queue compositeActivities = new Queue();
188             compositeActivities.Enqueue(compositeActivity);
189             while (compositeActivities.Count > 0)
190             {
191                 CompositeActivity compositeActivity2 = (CompositeActivity)compositeActivities.Dequeue();
192                 childActivities = compositeActivity2.Activities;
193
194                 foreach (Activity activity in childActivities)
195                 {
196                     nestedActivities.Add(activity);
197                     if (activity is CompositeActivity)
198                         compositeActivities.Enqueue(activity);
199                 }
200             }
201             return (Activity[])nestedActivities.ToArray(typeof(Activity));
202         }
203
204
205         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
206         internal static IList GetIdentifiersInCompositeActivity(CompositeActivity compositeActivity)
207         {
208             ArrayList identifiers = new ArrayList();
209             if (compositeActivity != null)
210             {
211                 identifiers.Add(compositeActivity.Name);
212                 IList<Activity> allChildren = GetAllNestedActivities(compositeActivity);
213                 foreach (Activity activity in allChildren)
214                     identifiers.Add(activity.Name);
215             }
216             return ArrayList.ReadOnly(identifiers);
217         }
218
219         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
220         internal static Activity[] GetAllNestedActivities(CompositeActivity compositeActivity)
221         {
222             if (compositeActivity == null)
223                 throw new ArgumentNullException("compositeActivity");
224
225             ArrayList nestedActivities = new ArrayList();
226
227             // Note: GetAllNestedActivities will not check for black box activities.
228             // This is to allow it to be invoked from within the activity's 
229             // constructor.
230             //if(Helpers.IsCustomActivity(compositeActivity))
231             //return (Activity[])nestedActivities.ToArray(typeof(Activity));
232
233             Queue compositeActivities = new Queue();
234             compositeActivities.Enqueue(compositeActivity);
235             while (compositeActivities.Count > 0)
236             {
237                 CompositeActivity compositeActivity2 = (CompositeActivity)compositeActivities.Dequeue();
238                 if (compositeActivity2 == compositeActivity || !Helpers.IsCustomActivity(compositeActivity2))
239                 {
240                     foreach (Activity activity in compositeActivity2.Activities)
241                     {
242                         nestedActivities.Add(activity);
243                         if (activity is CompositeActivity)
244                             compositeActivities.Enqueue(activity);
245                     }
246
247                     foreach (Activity activity in compositeActivity2.EnabledActivities)
248                     {
249                         if (!nestedActivities.Contains(activity))
250                         {
251                             nestedActivities.Add(activity);
252                             if (activity is CompositeActivity)
253                                 compositeActivities.Enqueue(activity);
254                         }
255                     }
256                 }
257             }
258             return (Activity[])nestedActivities.ToArray(typeof(Activity));
259         }
260
261         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
262         internal static string MergeNamespaces(string primaryNs, string secondaryNs)
263         {
264             string newNs = primaryNs;
265             if (secondaryNs != null && secondaryNs.Length > 0)
266             {
267                 if (newNs != null && newNs.Length > 0)
268                     newNs += ("." + secondaryNs);
269                 else
270                     newNs = secondaryNs;
271             }
272
273             if (newNs == null)
274                 newNs = string.Empty;
275             return newNs;
276         }
277
278         internal static Activity GetRootActivity(Activity activity)
279         {
280             if (activity == null)
281                 throw new ArgumentNullException("activity");
282
283             while (activity.Parent != null)
284                 activity = activity.Parent;
285
286             return activity;
287         }
288
289         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
290         internal static Stream SerializeDesignersToStream(ICollection activities)
291         {
292             Stream stateStream = new MemoryStream();
293             BinaryWriter writer = new BinaryWriter(stateStream);
294
295             Queue<IComponent> serializedComponents = new Queue<IComponent>();
296             foreach (IComponent activity in activities)
297                 serializedComponents.Enqueue(activity);
298
299             while (serializedComponents.Count > 0)
300             {
301                 IComponent component = serializedComponents.Dequeue();
302                 if (component != null && component.Site != null)
303                 {
304                     IDesignerHost designerHost = component.Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
305                     if (designerHost == null)
306                         throw new InvalidOperationException(
307                             SR.GetString(SR.General_MissingService, typeof(IDesignerHost).Name));
308
309                     ActivityDesigner activityDesigner = designerHost.GetDesigner(component) as ActivityDesigner;
310                     if (activityDesigner != null)
311                     {
312                         try
313                         {
314                             ((IPersistUIState)activityDesigner).SaveViewState(writer);
315
316                             CompositeActivity compositeActivity = component as CompositeActivity;
317                             if (compositeActivity != null)
318                             {
319                                 foreach (IComponent childActivity in compositeActivity.Activities)
320                                 {
321                                     serializedComponents.Enqueue(childActivity);
322                                 }
323                             }
324                         }
325                         catch
326                         {
327                         }
328                     }
329                 }
330             }
331
332             return stateStream;
333         }
334
335         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
336         internal static void DeserializeDesignersFromStream(ICollection activities, Stream stateStream)
337         {
338             if (stateStream.Length == 0)
339                 return;
340
341             BinaryReader reader = new BinaryReader(stateStream);
342             stateStream.Seek(0, SeekOrigin.Begin);
343
344             Queue<IComponent> serializedComponents = new Queue<IComponent>();
345             foreach (IComponent component in activities)
346                 serializedComponents.Enqueue(component);
347
348             while (serializedComponents.Count > 0)
349             {
350                 IComponent component = serializedComponents.Dequeue();
351                 if (component != null && component.Site != null)
352                 {
353                     IDesignerHost designerHost = component.Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
354                     if (designerHost == null)
355                         throw new InvalidOperationException(
356                             SR.GetString(SR.General_MissingService, typeof(IDesignerHost).Name));
357
358                     ActivityDesigner activityDesigner = designerHost.GetDesigner(component) as ActivityDesigner;
359                     if (activityDesigner != null)
360                     {
361                         try
362                         {
363                             ((IPersistUIState)activityDesigner).LoadViewState(reader);
364
365                             CompositeActivity compositeActivity = component as CompositeActivity;
366                             if (compositeActivity != null)
367                             {
368                                 foreach (IComponent childActivity in compositeActivity.Activities)
369                                 {
370                                     serializedComponents.Enqueue(childActivity);
371                                 }
372                             }
373                         }
374                         catch
375                         {
376                         }
377                     }
378                 }
379             }
380         }
381
382         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
383         internal static string GetBaseIdentifier(Activity activity)
384         {
385             string baseIdentifier = activity.GetType().Name;
386             StringBuilder b = new StringBuilder(baseIdentifier.Length);
387             for (int i = 0; i < baseIdentifier.Length; i++)
388             {
389                 if (Char.IsUpper(baseIdentifier[i]) && (i == 0 || i == baseIdentifier.Length - 1 || Char.IsUpper(baseIdentifier[i + 1])))
390                 {
391                     b.Append(Char.ToLowerInvariant(baseIdentifier[i]));
392                 }
393                 else
394                 {
395                     b.Append(baseIdentifier.Substring(i));
396                     break;
397                 }
398             }
399             return b.ToString();
400         }
401
402         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
403         internal static string GetRootNamespace(IServiceProvider serviceProvider)
404         {
405             if (serviceProvider == null)
406                 throw new ArgumentNullException("serviceProvider");
407
408             string rootNs = string.Empty;
409             IWorkflowCompilerOptionsService compilerOptionsService = (IWorkflowCompilerOptionsService)serviceProvider.GetService(typeof(IWorkflowCompilerOptionsService));
410             if (compilerOptionsService != null && compilerOptionsService.RootNamespace != null)
411                 rootNs = compilerOptionsService.RootNamespace; //e.g. WorkflowApp1
412             return rootNs;
413         }
414
415         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
416         internal static Type GetDataSourceClass(Activity activity, IServiceProvider serviceProvider)
417         {
418             if (activity == null)
419                 throw new ArgumentNullException("activity");
420             if (serviceProvider == null)
421                 throw new ArgumentNullException("serviceProvider");
422
423             Type activityType = null;
424             string className = null;
425             if (activity == GetRootActivity(activity))
426                 className = activity.GetValue(WorkflowMarkupSerializer.XClassProperty) as String;
427
428             if (!String.IsNullOrEmpty(className))
429             {
430                 ITypeProvider typeProvider = (ITypeProvider)serviceProvider.GetService(typeof(ITypeProvider));
431                 if (typeProvider == null)
432                     throw new InvalidOperationException(
433                         SR.GetString(SR.General_MissingService, typeof(ITypeProvider).Name));
434
435                 activityType = typeProvider.GetType(className);
436             }
437             else
438             {
439                 return activity.GetType();
440             }
441
442             return activityType;
443         }
444
445         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
446         internal static Activity GetDataSourceActivity(Activity activity, string inputName, out string name)
447         {
448             if (activity == null)
449                 throw new ArgumentNullException("activity");
450             if (string.IsNullOrEmpty(inputName))
451                 throw new ArgumentException("inputName");
452
453             name = inputName;
454             if (inputName.IndexOf('.') == -1)
455                 return activity;
456
457             int indexOfDot = inputName.LastIndexOf('.');
458             string scopeID = inputName.Substring(0, indexOfDot);
459             name = inputName.Substring(indexOfDot + 1);
460
461             Activity contextActivity = Helpers.ParseActivityForBind(activity, scopeID);
462             if (contextActivity == null)
463                 contextActivity = Helpers.ParseActivity(Helpers.GetRootActivity(activity), scopeID);
464
465             // activity can be either the qualified id of the scope activity or the qualified id of the custom activity.
466             return contextActivity;
467         }
468
469         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
470         internal static void GetNamespaceAndClassName(string fullQualifiedName, out string namespaceName, out string className)
471         {
472             namespaceName = String.Empty;
473             className = String.Empty;
474
475             if (fullQualifiedName == null)
476                 return;
477
478             int indexOfDot = fullQualifiedName.LastIndexOf('.');
479             if (indexOfDot != -1)
480             {
481                 namespaceName = fullQualifiedName.Substring(0, indexOfDot);
482                 className = fullQualifiedName.Substring(indexOfDot + 1);
483             }
484             else
485             {
486                 className = fullQualifiedName;
487             }
488         }
489
490         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
491         internal static CodeTypeDeclaration GetCodeNamespaceAndClass(CodeNamespaceCollection namespaces, string namespaceName, string className, out CodeNamespace codeNamespace)
492         {
493             codeNamespace = null;
494             foreach (CodeNamespace ns in namespaces)
495             {
496                 if (ns.Name == namespaceName)
497                 {
498                     codeNamespace = ns;
499                     break;
500                 }
501             }
502
503             CodeTypeDeclaration codeTypeDeclaration = null;
504             if (codeNamespace != null)
505             {
506                 foreach (CodeTypeDeclaration typeDecl in codeNamespace.Types)
507                 {
508                     if (typeDecl.Name == className)
509                     {
510                         codeTypeDeclaration = typeDecl;
511                         break;
512                     }
513                 }
514             }
515             return codeTypeDeclaration;
516         }
517
518         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
519         internal static string GetClassName(string fullQualifiedName)
520         {
521             if (fullQualifiedName == null)
522                 return null;
523
524             string className = fullQualifiedName;
525             int indexOfDot = fullQualifiedName.LastIndexOf('.');
526             if (indexOfDot != -1)
527                 className = fullQualifiedName.Substring(indexOfDot + 1);
528             return className;
529         }
530
531
532         [DllImport("msi.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
533         private static extern int MsiGetProductInfoW(string szProduct, string szProperty, StringBuilder lpValueBuf, ref int pcchValueBuf);
534         private static string GetInstallDirectory(bool getSDKDir)
535         {
536             string path = string.Empty;
537             try
538             {
539                 //ERROR_UNKNOWN_PROPERTY           1608L
540                 //ERROR_INVALID_PARAMETER          87L
541                 int length = FILENAME_MAX + 1;
542                 StringBuilder location = new StringBuilder(length);
543                 int hr = MsiGetProductInfoW(getSDKDir ? ProductSDKCode : ProductCode, INSTALLPROPERTY_INSTALLLOCATION, location, ref length);
544                 int error = Marshal.GetLastWin32Error();
545                 if (hr == 0)
546                 {
547                     path = location.ToString();
548                 }
549                 else
550                 {
551                     Debug.WriteLine("Error loading install directory: " + error.ToString(CultureInfo.CurrentCulture));
552                 }
553
554             }
555             catch
556             {
557             }
558
559             if (string.IsNullOrEmpty(path))
560             {
561                 try
562                 {
563                     if (!getSDKDir)
564                     {
565                         using (RegistryKey key = Registry.LocalMachine.OpenSubKey(ProductRootRegKey))
566                         {
567                             if (key != null)
568                                 path = (string)key.GetValue("InstallDir");
569                         }
570                     }
571                 }
572                 catch
573                 {
574                 }
575             }
576
577             // 
578             if (string.IsNullOrEmpty(path))
579                 path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
580
581             return path;
582         }
583
584         private static string GetInstallDirectory30()
585         {
586             string path = string.Empty;
587             try
588             {
589                 //ERROR_UNKNOWN_PROPERTY           1608L
590                 //ERROR_INVALID_PARAMETER          87L
591                 int length = FILENAME_MAX + 1;
592                 StringBuilder location = new StringBuilder(length);
593                 int hr = MsiGetProductInfoW(ProductCode, INSTALLPROPERTY_INSTALLLOCATION, location, ref length);
594                 int error = Marshal.GetLastWin32Error();
595                 if (hr == 0)
596                 {
597                     path = location.ToString();
598                 }
599                 else
600                 {
601                     Debug.WriteLine("Error loading 3.0 install directory: " + error.ToString(CultureInfo.CurrentCulture));
602                 }
603
604             }
605             catch
606             {
607             }
608
609             if (string.IsNullOrEmpty(path))
610             {
611                 try
612                 {
613                     using (RegistryKey key = Registry.LocalMachine.OpenSubKey(ProductRootRegKey30))
614                     {
615                         if (key != null)
616                         {
617                             path = (string)key.GetValue("InstallDir");
618                         }
619                     }
620                 }
621                 catch
622                 {
623                 }
624             }
625
626             return path;
627         }
628
629         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
630         internal static Type GetBaseType(PropertyInfo property, object owner, IServiceProvider serviceProvider)
631         {
632             //When we are emitting code for the dynamic properties we might get the propertyinfo as null
633             if (owner == null)
634                 throw new ArgumentNullException("owner");
635
636             if (serviceProvider == null)
637                 throw new ArgumentNullException("serviceProvider");
638
639             if (property != null)
640             {
641                 IDynamicPropertyTypeProvider basetypeProvider = owner as IDynamicPropertyTypeProvider;
642                 if (basetypeProvider != null)
643                 {
644                     Type type = basetypeProvider.GetPropertyType(serviceProvider, property.Name);
645                     if (type != null)
646                         return type;
647                 }
648
649                 return property.PropertyType;
650             }
651
652             return null;
653         }
654
655         //
656         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
657         internal static AccessTypes GetAccessType(PropertyInfo property, object owner, IServiceProvider serviceProvider)
658         {
659             //When we are emitting code for the dynamic properties we might get the propertyinfo as null
660             if (owner == null)
661                 throw new ArgumentNullException("owner");
662
663             if (serviceProvider == null)
664                 throw new ArgumentNullException("serviceProvider");
665
666             if (property != null)
667             {
668                 IDynamicPropertyTypeProvider basetypeProvider = owner as IDynamicPropertyTypeProvider;
669                 if (basetypeProvider != null)
670                     return basetypeProvider.GetAccessType(serviceProvider, property.Name);
671             }
672
673             return AccessTypes.Read;
674         }
675
676         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
677         internal static bool IsChildActivity(CompositeActivity parent, Activity activity)
678         {
679             foreach (Activity containedActivity in parent.Activities)
680             {
681                 if (activity == containedActivity)
682                     return true;
683
684                 if (containedActivity is CompositeActivity &&
685                     Helpers.IsChildActivity(containedActivity as CompositeActivity, activity))
686                     return true;
687             }
688
689             return false;
690         }
691
692         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
693         internal static bool TypesEqual(CodeTypeReference typeLeft, Type typeRight)
694         {
695             if (typeRight.IsArray && typeLeft.ArrayRank != typeRight.GetArrayRank()) return false;
696             // 
697             if (!typeLeft.BaseType.Equals(typeRight.FullName)) return false;
698
699             if (typeLeft.ArrayRank > 0)
700                 return TypesEqual(typeLeft.ArrayElementType, typeRight.GetElementType());
701             return true;
702         }
703
704         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
705         internal static bool TypesEqual(CodeTypeReference typeLeft, CodeTypeReference typeRight)
706         {
707             if (typeLeft.ArrayRank != typeRight.ArrayRank) return false;
708             if (!typeLeft.BaseType.Equals(typeRight.BaseType)) return false;
709
710             if (typeLeft.ArrayRank > 0)
711                 return TypesEqual(typeLeft.ArrayElementType, typeRight.ArrayElementType);
712             return true;
713         }
714
715         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
716         internal static DesignerSerializationVisibility GetSerializationVisibility(MemberInfo memberInfo)
717         {
718
719             if (memberInfo == null)
720                 throw new ArgumentNullException("memberInfo");
721
722             DesignerSerializationVisibility designerSerializationVisibility = DesignerSerializationVisibility.Visible;
723
724             // Calling GetCustomAttributes on PropertyInfo or EventInfo when the inherit parameter of GetCustomAttributes 
725             // is true does not walk the type hierarchy. But System.Attribute.GetCustomAttributes causes perf issues.
726             object[] attributes = memberInfo.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true);
727             if (attributes.Length > 0)
728                 designerSerializationVisibility = (attributes[0] as DesignerSerializationVisibilityAttribute).Visibility;
729             else if (Attribute.IsDefined(memberInfo, typeof(DesignerSerializationVisibilityAttribute)))
730                 designerSerializationVisibility = (Attribute.GetCustomAttribute(memberInfo, typeof(DesignerSerializationVisibilityAttribute)) as DesignerSerializationVisibilityAttribute).Visibility;
731
732             return designerSerializationVisibility;
733         }
734
735         // Method parameters must match exactly
736         // 
737         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
738         internal static MethodInfo GetMethodExactMatch(Type type, string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
739         {
740             MethodInfo foundMethod = null;
741             MethodInfo[] methods = type.GetMethods(bindingAttr);
742             foreach (MethodInfo method in methods)
743             {
744                 bool matchName = ((bindingAttr & BindingFlags.IgnoreCase) == BindingFlags.IgnoreCase) ? string.Compare(method.Name, name, StringComparison.OrdinalIgnoreCase) == 0 : string.Compare(method.Name, name, StringComparison.Ordinal) == 0;
745                 if (matchName)
746                 {
747                     bool mismatch = false;
748                     if (types != null)
749                     {
750                         ParameterInfo[] parameters = method.GetParameters();
751                         if (parameters.GetLength(0) == types.Length)
752                         {
753                             for (int index = 0; !mismatch && index < parameters.Length; index++)
754                                 mismatch = (parameters[index].ParameterType == null) || (!parameters[index].ParameterType.IsAssignableFrom(types[index]));
755                         }
756                         else
757                             mismatch = true;
758                     }
759                     if (!mismatch)
760                     {
761                         foundMethod = method;
762                         break;
763                     }
764                 }
765             }
766
767             return foundMethod;
768         }
769
770         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
771         internal static T GetAttributeFromObject<T>(object attributeObject) where T : Attribute
772         {
773             if (attributeObject is AttributeInfoAttribute)
774                 return (T)((AttributeInfoAttribute)attributeObject).AttributeInfo.CreateAttribute();
775
776             if (attributeObject is T)
777                 return (T)attributeObject;
778
779             return null;
780         }
781
782         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
783         internal static Type GetDelegateFromEvent(EventInfo eventInfo)
784         {
785             if (eventInfo.EventHandlerType != null)
786                 return eventInfo.EventHandlerType;
787
788             return TypeProvider.GetEventHandlerType(eventInfo);
789         }
790
791         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
792         internal static void AddTypeProviderAssembliesFromRegistry(TypeProvider typeProvider, IServiceProvider serviceProvider)
793         {
794             if (typeProvider == null)
795                 throw new ArgumentNullException("typeProvider");
796             if (serviceProvider == null)
797                 throw new ArgumentNullException("serviceProvider");
798
799             RegistryKey referenceKey = Registry.CurrentUser.OpenSubKey(TypeProviderRegistryKeyPath);
800             if (referenceKey != null)
801             {
802                 ITypeProviderCreator typeProviderCreator = serviceProvider.GetService(typeof(ITypeProviderCreator)) as ITypeProviderCreator;
803                 foreach (string assemblyName in ((string[])referenceKey.GetValue(TypeProviderAssemblyRegValueName)))
804                 {
805                     try
806                     {
807                         if (typeProviderCreator != null)
808                         {
809                             bool addAssembly = true;
810                             Assembly assembly = typeProviderCreator.GetTransientAssembly(AssemblyName.GetAssemblyName(assemblyName));
811                             // Check to see if a copy of the assembly is already added.
812                             if (assembly != null)
813                             {
814                                 foreach (Type type in assembly.GetTypes())
815                                 {
816                                     if (typeProvider.GetType(type.AssemblyQualifiedName) != null)
817                                         addAssembly = false;
818                                     break;
819                                 }
820                                 if (addAssembly)
821                                     typeProvider.AddAssembly(assembly);
822                             }
823                         }
824                         else
825                             // AddAssemblyReference should take care of duplicates.
826                             typeProvider.AddAssemblyReference(assemblyName);
827
828                     }
829                     catch
830                     {
831                         // Continue loading.
832                     }
833                 }
834
835                 referenceKey.Close();
836             }
837         }
838
839         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
840         internal static void UpdateTypeProviderAssembliesRegistry(string assemblyName)
841         {
842             RegistryKey referenceKey = Registry.CurrentUser.CreateSubKey(TypeProviderRegistryKeyPath);
843             if (referenceKey != null)
844             {
845                 try
846                 {
847                     ArrayList references = null;
848                     if (referenceKey.ValueCount > 0)
849                         references = new ArrayList((string[])referenceKey.GetValue(TypeProviderAssemblyRegValueName));
850                     else
851                         references = new ArrayList();
852
853                     if (!references.Contains(assemblyName))
854                     {
855                         references.Add(assemblyName);
856                         referenceKey.SetValue(TypeProviderAssemblyRegValueName, ((string[])references.ToArray(typeof(string))));
857                     }
858                 }
859                 catch
860                 {
861                     //We eat the exception
862                 }
863                 finally
864                 {
865                     referenceKey.Close();
866                 }
867             }
868         }
869
870         internal static CompositeActivity GetDeclaringActivity(Activity activity)
871         {
872             if (activity == null)
873                 throw new ArgumentNullException("activity");
874
875             CompositeActivity parent = activity.Parent;
876             while (parent != null)
877             {
878                 // This will be the root
879                 if (parent.Parent == null)
880                     return parent;
881
882                 // Any custom activity found is the declaring activity
883                 if (IsCustomActivity(parent))
884                     return parent;
885
886                 parent = parent.Parent;
887             }
888             return null;
889         }
890
891         internal static bool IsActivityLocked(Activity activity)
892         {
893             if (activity == null)
894                 throw new ArgumentNullException("activity");
895
896             CompositeActivity parent = activity.Parent;
897             while (parent != null)
898             {
899                 // If root, not locked
900                 if (parent.Parent == null)
901                     return false;
902
903                 // Any custom activity found, then locked
904                 if (IsCustomActivity(parent))
905                     return true;
906
907                 parent = parent.Parent;
908             }
909
910             return false;
911         }
912
913         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
914         internal static Activity GetEnclosingActivity(Activity activity)
915         {
916             Activity enclosingActivity;
917
918             if (IsActivityLocked(activity))
919                 enclosingActivity = Helpers.GetDeclaringActivity(activity);
920             else
921                 enclosingActivity = GetRootActivity(activity);
922
923             return enclosingActivity;
924         }
925
926         // This function returns all the executable activities including secondary flow activities.
927         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
928         public static IList<Activity> GetAllEnabledActivities(CompositeActivity compositeActivity)
929         {
930             if (compositeActivity == null)
931                 throw new ArgumentNullException("compositeActivity");
932
933             List<Activity> allActivities = new List<Activity>(compositeActivity.EnabledActivities);
934             foreach (Activity childActivity in compositeActivity.Activities)
935             {
936                 if (childActivity.Enabled &&
937                         IsFrameworkActivity(childActivity))
938                     allActivities.Add(childActivity);
939             }
940             return allActivities;
941         }
942         public static bool IsFrameworkActivity(Activity activity)
943         {
944             return (activity is CancellationHandlerActivity ||
945                         activity is CompensationHandlerActivity ||
946                         activity is FaultHandlersActivity);
947         }
948
949         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
950         internal static MethodInfo GetInterfaceMethod(Type interfaceType, string methodName)
951         {
952             MethodInfo methodInfo = null;
953             string interfaceName = String.Empty;
954             string method = String.Empty;
955
956             if (methodName.LastIndexOf('.') > 0)
957             {
958                 interfaceName = methodName.Substring(0, methodName.LastIndexOf('.'));
959                 method = methodName.Substring(methodName.LastIndexOf('.') + 1);
960             }
961
962             if (!String.IsNullOrEmpty(interfaceName))
963             {
964                 foreach (Type inheritedInterface in interfaceType.GetInterfaces())
965                 {
966                     if (String.Compare(inheritedInterface.FullName, interfaceName, StringComparison.Ordinal) == 0)
967                     {
968                         methodInfo = inheritedInterface.GetMethod(method);
969                         break;
970                     }
971                 }
972             }
973             else
974             {
975                 methodInfo = interfaceType.GetMethod(methodName);
976             }
977
978             return methodInfo;
979         }
980
981         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
982         internal static XmlWriter CreateXmlWriter(object output)
983         {
984             XmlWriterSettings settings = new XmlWriterSettings();
985             settings.Indent = true;
986             settings.IndentChars = ("\t");
987             settings.OmitXmlDeclaration = true;
988             settings.CloseOutput = true;
989
990             if (output is string)
991                 return XmlWriter.Create(output as string, settings);
992             else if (output is TextWriter)
993                 return XmlWriter.Create(output as TextWriter, settings);
994             else
995             {
996                 Debug.Assert(false, "Invalid argument type.  'output' must either be string or TextWriter.");
997                 return null;
998             }
999         }
1000
1001         #region DesignTimeType Support
1002         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1003         internal static string GetDesignTimeTypeName(object owner, object key)
1004         {
1005             string typeName = null;
1006             DependencyObject dependencyObject = owner as DependencyObject;
1007             if (dependencyObject != null && key != null)
1008             {
1009                 if (dependencyObject.UserData.Contains(UserDataKeys.DesignTimeTypeNames))
1010                 {
1011                     Hashtable typeNames = dependencyObject.UserData[UserDataKeys.DesignTimeTypeNames] as Hashtable;
1012                     if (typeNames != null && typeNames.ContainsKey(key))
1013                         typeName = typeNames[key] as string;
1014                 }
1015             }
1016             return typeName;
1017         }
1018
1019         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1020         internal static void SetDesignTimeTypeName(object owner, object key, string value)
1021         {
1022             DependencyObject dependencyObject = owner as DependencyObject;
1023             if (dependencyObject != null && key != null)
1024             {
1025                 if (!dependencyObject.UserData.Contains(UserDataKeys.DesignTimeTypeNames))
1026                     dependencyObject.UserData[UserDataKeys.DesignTimeTypeNames] = new Hashtable();
1027
1028                 Hashtable typeNames = dependencyObject.UserData[UserDataKeys.DesignTimeTypeNames] as Hashtable;
1029                 typeNames[key] = value;
1030             }
1031         }
1032         #endregion
1033
1034         #region Helpers from ExecutableCompModHelpers
1035         // This only works for composite activity.
1036         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1037         internal static bool IsCustomActivity(CompositeActivity compositeActivity)
1038         {
1039             if (compositeActivity == null)
1040                 throw new ArgumentNullException("compositeActivity");
1041
1042             if (compositeActivity.UserData.Contains(UserDataKeys.CustomActivity))
1043             {
1044                 return (bool)(compositeActivity.UserData[UserDataKeys.CustomActivity]);
1045             }
1046             else
1047             {
1048                 try
1049                 {
1050                     CompositeActivity activity = Activator.CreateInstance(compositeActivity.GetType()) as CompositeActivity;
1051                     if (activity != null && activity.Activities.Count > 0)
1052                     {
1053                         compositeActivity.UserData[UserDataKeys.CustomActivityDefaultName] = activity.Name;
1054                         compositeActivity.UserData[UserDataKeys.CustomActivity] = true; //
1055                         return true;
1056                     }
1057                 }
1058                 catch
1059                 {
1060                     // 
1061                 }
1062             }
1063
1064             compositeActivity.UserData[UserDataKeys.CustomActivity] = false; //
1065             return false;
1066         }
1067
1068         [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", Justification = "IndexOf(\".\") not a security issue.")]
1069         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1070         internal static Activity ParseActivity(Activity parsingContext, string activityName)
1071         {
1072             if (parsingContext == null)
1073                 throw new ArgumentNullException("parsingContext");
1074             if (activityName == null)
1075                 throw new ArgumentNullException("activityName");
1076
1077             string currentAtivityName = activityName;
1078             string nextActivityName = string.Empty;
1079             int indexOfDot = activityName.IndexOf(".");
1080             if (indexOfDot != -1)
1081             {
1082                 currentAtivityName = activityName.Substring(0, indexOfDot);
1083                 nextActivityName = activityName.Substring(indexOfDot + 1);
1084                 if (nextActivityName.Length == 0)
1085                     return null;
1086             }
1087
1088             Activity currentActivity = GetActivity(parsingContext, currentAtivityName);
1089             if (currentActivity != null)
1090             {
1091                 if (nextActivityName.Length > 0)
1092                 {
1093                     if (!(currentActivity is CompositeActivity) || !IsCustomActivity(currentActivity as CompositeActivity))
1094                         // current activity must be a custom activity, otherwise there should be no dots in the name.
1095                         return null;
1096
1097                     string[] names = nextActivityName.Split('.');
1098                     for (int i = 0; i < names.Length; i++)
1099                     {
1100                         Activity nextActivity = GetActivity(currentActivity, names[i]);
1101                         if (nextActivity == null || !Helpers.IsActivityLocked(nextActivity))
1102                             return null;
1103
1104                         CompositeActivity declaringActivity = GetDeclaringActivity(nextActivity);
1105                         if (currentActivity != declaringActivity)
1106                             return null;
1107
1108                         currentActivity = nextActivity;
1109                     }
1110
1111                     return currentActivity;
1112                 }
1113                 else
1114                 {
1115                     // This activity should always be unlocked, unless if GetChildActivity() is called from
1116                     // within the custom activity's companion class, then we don't have the full qualified ID available
1117                     // at that time.  We allow this to succeed only if the declaring activity is the same as the declaring
1118                     // activity of the context activity passed in.
1119                     if (Helpers.IsActivityLocked(currentActivity))//.IsLocked)
1120                     {
1121                         if (!IsDeclaringActivityMatchesContext(currentActivity, parsingContext))
1122                             return null;
1123                     }
1124
1125                     return currentActivity;
1126                 }
1127             }
1128
1129             return null;
1130         }
1131
1132         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1133         internal static Activity ParseActivityForBind(Activity context, string activityName)
1134         {
1135             if (context == null)
1136                 throw new ArgumentNullException("context");
1137             if (activityName == null)
1138                 throw new ArgumentNullException("activityName");
1139
1140             if (string.Equals(activityName, "/Self", StringComparison.Ordinal))
1141             {
1142                 return context;
1143             }
1144             else if (activityName.StartsWith("/Parent", StringComparison.OrdinalIgnoreCase))
1145             {
1146                 Activity activity = context;
1147                 string[] paths = activityName.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
1148                 for (int i = 0; i < paths.Length && activity != null; i++)
1149                 {
1150                     string parent = paths[i].Trim();
1151                     activity = (string.Equals(parent, "Parent", StringComparison.OrdinalIgnoreCase)) ? activity.Parent : null;
1152                 }
1153                 return activity;
1154             }
1155             else if (Helpers.IsActivityLocked(context))
1156             {
1157                 // Look for the matching activity inside the custom activity context first.  This is because if a bind
1158                 // is coming from a custom activity, it's activity ref ID may not match the qualified ID of the
1159                 // the activity.
1160                 Activity activity = null;
1161                 Activity declaringActivity = Helpers.GetDeclaringActivity(context);
1162                 Guid currentContextGuid = GetRuntimeContextGuid(context);
1163                 Guid declaringContextGuid = GetRuntimeContextGuid(declaringActivity);
1164
1165                 Activity currentContextActivity = context;
1166                 Activity parentContextActivity = context.Parent;
1167                 Guid parentContextGuid = GetRuntimeContextGuid(parentContextActivity);
1168                 while (activity == null && declaringContextGuid != currentContextGuid)
1169                 {
1170                     // WinOE Bug 17931: if the context id is different, it means that this activity is running in a child context (such as 
1171                     // the children of a replicator or a while).  we need to resolve the activity within the child context
1172                     // first.  If we go up to the declaring activity, we'd be finding children of the template instead of
1173                     // the actual running instance.
1174                     while (parentContextActivity != null && parentContextGuid == currentContextGuid)
1175                     {
1176                         currentContextActivity = parentContextActivity;
1177                         parentContextActivity = parentContextActivity.Parent;
1178                         parentContextGuid = GetRuntimeContextGuid(parentContextActivity);
1179                     }
1180
1181                     activity = Helpers.ParseActivity(currentContextActivity, activityName);
1182                     currentContextGuid = parentContextGuid;
1183                 }
1184
1185                 if (activity == null)
1186                 {
1187                     // Check the declaring activity
1188                     activity = Helpers.ParseActivity(declaringActivity, activityName);
1189                 }
1190
1191                 // Nothing found, let's see if this is bind to the custom activity itself.
1192                 if (activity == null)
1193                 {
1194                     if (!declaringActivity.UserData.Contains(UserDataKeys.CustomActivityDefaultName))
1195                     {
1196                         //we need to activate a new instance of the declaringActivity's type and check if its name equals to the one we are looking for
1197                         Activity newCustomActivity = Activator.CreateInstance(declaringActivity.GetType()) as Activity;
1198                         declaringActivity.UserData[UserDataKeys.CustomActivityDefaultName] = newCustomActivity.Name;
1199                     }
1200
1201                     if (((string)declaringActivity.UserData[UserDataKeys.CustomActivityDefaultName]) == activityName)
1202                         activity = declaringActivity;
1203                 }
1204
1205                 // if this is a locked activity, its bind reference must be within its declaring activity. We should not try
1206                 // to resolve it beyond that scope.
1207                 return activity;
1208             }
1209
1210             Activity targetActivity = null;
1211             Activity parentActivity = context;
1212
1213             //if it's a custom activity and it has parent, start looking for the target activity at the parent level
1214             //otherwise we'll get children of the custom activity
1215             bool mayLookInside = false; //we may look inside the custom activity if the target is not found outside
1216             CompositeActivity compositeParentActivity = parentActivity as CompositeActivity;
1217             if (compositeParentActivity != null && parentActivity.Parent != null && IsCustomActivity(compositeParentActivity))
1218             {
1219                 mayLookInside = true;
1220                 parentActivity = parentActivity.Parent;
1221             }
1222
1223             while (targetActivity == null && parentActivity != null)
1224             {
1225                 targetActivity = parentActivity.GetActivityByName(activityName, true);
1226                 parentActivity = parentActivity.Parent;
1227             }
1228
1229             if (mayLookInside && targetActivity == null)
1230             {
1231                 //if we have not found an appropriate activity at the parent level, try looking inside
1232                 //we dont need to look outside (loop while parent is not null) - it has already been done above
1233                 parentActivity = context;
1234                 targetActivity = parentActivity.GetActivityByName(activityName, true);
1235             }
1236
1237
1238             return (targetActivity == null) ? Helpers.ParseActivity(Helpers.GetRootActivity(context), activityName) : targetActivity;
1239         }
1240
1241         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1242         private static Guid GetRuntimeContextGuid(Activity currentActivity)
1243         {
1244             Activity contextActivity = currentActivity;
1245             Guid contextGuid = (Guid)contextActivity.GetValue(Activity.ActivityContextGuidProperty);
1246             while (contextGuid == Guid.Empty && contextActivity.Parent != null)
1247             {
1248                 contextActivity = contextActivity.Parent;
1249                 contextGuid = (Guid)contextActivity.GetValue(Activity.ActivityContextGuidProperty);
1250             }
1251             return contextGuid;
1252         }
1253
1254         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1255         private static bool IsDeclaringActivityMatchesContext(Activity currentActivity, Activity context)
1256         {
1257             CompositeActivity declaringContext = context as CompositeActivity;
1258
1259             CompositeActivity declaringActivityOfCurrent = Helpers.GetDeclaringActivity(currentActivity);
1260
1261             // If the context activity is locked and it is a primitive activity
1262             // or NOT a custom activity then we need to find its enclosing 
1263             // custom activity.
1264             if (Helpers.IsActivityLocked(context) &&
1265                     (declaringContext == null || !Helpers.IsCustomActivity(declaringContext))
1266                 )
1267                 declaringContext = Helpers.GetDeclaringActivity(context);
1268
1269             if (declaringContext == declaringActivityOfCurrent)
1270                 return true;
1271             else
1272                 return false;
1273         }
1274
1275         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1276         internal static bool IsAlternateFlowActivity(Activity activity)
1277         {
1278             if (activity == null)
1279                 return false;
1280
1281             bool isAlternateFlowActivityAttribute = false;
1282             //dont want to use reflection to check for the alternate flow attribute
1283             //this is a fix for a perf issue - use of reflection in a ui loop
1284             if (!activity.UserData.Contains(typeof(AlternateFlowActivityAttribute)))
1285             {
1286                 isAlternateFlowActivityAttribute = activity.GetType().GetCustomAttributes(typeof(AlternateFlowActivityAttribute), true).Length != 0;
1287                 activity.UserData[typeof(AlternateFlowActivityAttribute)] = isAlternateFlowActivityAttribute;
1288             }
1289             else
1290             {
1291                 isAlternateFlowActivityAttribute = (bool)activity.UserData[typeof(AlternateFlowActivityAttribute)];
1292             }
1293
1294             return isAlternateFlowActivityAttribute;
1295         }
1296
1297         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1298         private static Activity GetActivity(Activity containerActivity, string id)
1299         {
1300             if (containerActivity != null)
1301             {
1302                 Queue activities = new Queue();
1303                 activities.Enqueue(containerActivity);
1304                 while (activities.Count > 0)
1305                 {
1306                     Activity activity = (Activity)activities.Dequeue();
1307                     if (activity.Enabled)
1308                     {
1309                         if (activity.Name == id)
1310                             return activity;
1311
1312                         if (activity is CompositeActivity)
1313                         {
1314                             foreach (Activity child in ((CompositeActivity)activity).Activities)
1315                                 activities.Enqueue(child);
1316                         }
1317                     }
1318                 }
1319             }
1320             return null;
1321         }
1322         #endregion
1323     }
1324     #endregion
1325
1326     #region Class TypeDescriptorContext (SHARED WITH ACTIVITIES, ORCHESTRATIONDESIGNER)
1327     [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses",
1328         Justification = "Not all assemblies that include this file instantiate the class.")]
1329     internal sealed class TypeDescriptorContext : ITypeDescriptorContext
1330     {
1331         private IServiceProvider serviceProvider;
1332         private PropertyDescriptor propDesc;
1333         private object instance;
1334
1335         public TypeDescriptorContext(IServiceProvider serviceProvider, PropertyDescriptor propDesc, object instance)
1336         {
1337             this.serviceProvider = serviceProvider;
1338             this.propDesc = propDesc;
1339             this.instance = instance;
1340         }
1341
1342         public IContainer Container
1343         {
1344             get
1345             {
1346                 return (IContainer)this.serviceProvider.GetService(typeof(IContainer));
1347             }
1348         }
1349         public object Instance
1350         {
1351             get
1352             {
1353                 return this.instance;
1354             }
1355         }
1356         public PropertyDescriptor PropertyDescriptor
1357         {
1358             get
1359             {
1360                 return this.propDesc;
1361             }
1362         }
1363         public object GetService(Type serviceType)
1364         {
1365             return this.serviceProvider.GetService(serviceType);
1366         }
1367
1368         public bool OnComponentChanging()
1369         {
1370             IComponentChangeService componentChangeService = (IComponentChangeService)this.serviceProvider.GetService(typeof(IComponentChangeService));
1371             if (componentChangeService != null)
1372             {
1373                 try
1374                 {
1375                     componentChangeService.OnComponentChanging(this.instance, this.propDesc);
1376                 }
1377                 catch (CheckoutException ce)
1378                 {
1379                     if (ce == CheckoutException.Canceled)
1380                         return false;
1381                     throw ce;
1382                 }
1383             }
1384
1385             return true;
1386         }
1387         public void OnComponentChanged()
1388         {
1389             IComponentChangeService componentChangeService = (IComponentChangeService)this.serviceProvider.GetService(typeof(IComponentChangeService));
1390             if (componentChangeService != null)
1391                 componentChangeService.OnComponentChanged(this.instance, this.propDesc, null, null);
1392         }
1393     }
1394     #endregion
1395
1396     // This class has been added as a fix for bug 18214 in order to 
1397     // create an independent code-path for debugger's use of ParseActivity functionality.
1398     // The GetActivity method of this class uses QualifiedName instead of Name property
1399     // for finding activities.
1400     internal static class DebuggerHelpers
1401     {
1402         [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", Justification = "IndexOf(\".\") not a security issue.")]
1403         internal static Activity ParseActivity(Activity parsingContext, string activityName)
1404         {
1405             if (parsingContext == null)
1406                 throw new ArgumentNullException("parsingContext");
1407             if (activityName == null)
1408                 throw new ArgumentNullException("activityName");
1409
1410             string currentAtivityName = activityName;
1411             string nextActivityName = string.Empty;
1412             int indexOfDot = activityName.IndexOf(".");
1413             if (indexOfDot != -1)
1414             {
1415                 currentAtivityName = activityName.Substring(0, indexOfDot);
1416                 nextActivityName = activityName.Substring(indexOfDot + 1);
1417                 if (nextActivityName.Length == 0)
1418                     return null;
1419             }
1420
1421             Activity currentActivity = null;
1422             currentActivity = GetActivity(parsingContext, currentAtivityName);
1423
1424             // The check for parsingContext.Parent != null is added here because IsCustomActivity returns true for root activities.
1425             if (currentActivity == null && (parsingContext is CompositeActivity) && parsingContext.Parent != null && Helpers.IsCustomActivity(parsingContext as CompositeActivity))
1426                 currentActivity = GetActivity(parsingContext, parsingContext.QualifiedName + "." + currentAtivityName);
1427
1428             if (currentActivity != null)
1429             {
1430                 if (nextActivityName.Length > 0)
1431                 {
1432                     if (!(currentActivity is CompositeActivity) || !Helpers.IsCustomActivity(currentActivity as CompositeActivity))
1433                         // current activity must be a custom activity, otherwise there should be no dots in the name.
1434                         return null;
1435
1436                     string[] names = nextActivityName.Split('.');
1437                     for (int i = 0; i < names.Length; i++)
1438                     {
1439                         Activity nextActivity = GetActivity(currentActivity, currentActivity.QualifiedName + "." + names[i]);
1440                         if (nextActivity == null || !Helpers.IsActivityLocked(nextActivity))
1441                             return null;
1442
1443                         CompositeActivity declaringActivity = Helpers.GetDeclaringActivity(nextActivity);
1444                         if (currentActivity != declaringActivity)
1445                             return null;
1446
1447                         currentActivity = nextActivity;
1448                     }
1449
1450                     return currentActivity;
1451                 }
1452                 else
1453                 {
1454                     // This activity should always be unlocked, unless if GetChildActivity() is called from
1455                     // within the custom activity's companion class, then we don't have the full qualified ID available
1456                     // at that time.  We allow this to succeed only if the declaring activity is the same as the declaring
1457                     // activity of the context activity passed in.
1458                     if (Helpers.IsActivityLocked(currentActivity))//.IsLocked)
1459                     {
1460                         if (!IsDeclaringActivityMatchesContext(currentActivity, parsingContext))
1461                             return null;
1462                     }
1463
1464                     return currentActivity;
1465                 }
1466             }
1467
1468             return null;
1469         }
1470
1471         private static Activity GetActivity(Activity containerActivity, string id)
1472         {
1473             if (containerActivity != null)
1474             {
1475                 Queue activities = new Queue();
1476                 activities.Enqueue(containerActivity);
1477                 while (activities.Count > 0)
1478                 {
1479                     Activity activity = (Activity)activities.Dequeue();
1480                     if (activity.Enabled)
1481                     {
1482                         if (activity.QualifiedName == id)
1483                             return activity;
1484
1485                         if (activity is CompositeActivity)
1486                         {
1487                             foreach (Activity child in ((CompositeActivity)activity).Activities)
1488                                 activities.Enqueue(child);
1489                         }
1490                     }
1491                 }
1492             }
1493             return null;
1494         }
1495
1496         private static bool IsDeclaringActivityMatchesContext(Activity currentActivity, Activity context)
1497         {
1498             CompositeActivity declaringContext = context as CompositeActivity;
1499
1500             CompositeActivity declaringActivityOfCurrent = Helpers.GetDeclaringActivity(currentActivity);
1501
1502             // If the context activity is locked and it is a primitive activity
1503             // or NOT a custom activity then we need to find its enclosing 
1504             // custom activity.
1505             if (Helpers.IsActivityLocked(context) &&
1506                     (declaringContext == null || !Helpers.IsCustomActivity(declaringContext))
1507                 )
1508                 declaringContext = Helpers.GetDeclaringActivity(context);
1509
1510             if (declaringContext == declaringActivityOfCurrent)
1511                 return true;
1512             else
1513                 return false;
1514         }
1515     }
1516 }