1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 using System;
6 using System.Threading;
7 using System.Collections;
8 using System.Globalization;
9 
10 namespace Ice
11 {
12     /// <summary>
13     /// Interface for thread notification hooks. Applications can derive
14     /// a class tat implements the start and stop
15     /// methods to intercept creation and destruction of threads created
16     /// by the Ice run time.
17     /// </summary>
18     public interface ThreadNotification
19     {
20         /// <summary>
21         /// The Ice run time calls start for each new
22         /// thread it creates. The call is made by the newly-started thread.
23         /// </summary>
start()24         void start();
25 
26         /// <summary>
27         /// The Ice run time calls stop before it destroys
28         /// a thread. The call is made by thread that is about to be
29         /// destroyed.
30         /// </summary>
stop()31         void stop();
32     }
33 
34     /// <summary>
35     /// A class that encpasulates data to initialize a communicator.
36     /// </summary>
37     public class InitializationData : ICloneable
38     {
39         /// <summary>
40         /// Creates and returns a copy of this object.
41         /// </summary>
Clone()42         public object Clone()
43         {
44             //
45             // A member-wise copy is safe because the members are immutable.
46             //
47             return MemberwiseClone();
48         }
49 
50         /// <summary>
51         /// The properties for the communicator.
52         /// </summary>
53         public Properties properties;
54 
55         /// <summary>
56         /// The logger for the communicator.
57         /// </summary>
58         public Logger logger;
59 
60         /// <summary>
61         /// The communicator observer used by the Ice run-time.
62         /// </summary>
63         public Instrumentation.CommunicatorObserver observer;
64 
65         /// <summary>
66         /// The thread hook for the communicator.
67         /// </summary>
68         [Obsolete("This data member is deprecated. Use threadStart or threadStop instead.")]
69         public ThreadNotification threadHook;
70 
71         /// <summary>
72         /// The thread start hook for the communicator. The Ice run time
73         /// calls this hook for each new thread it creates. The call is
74         /// made by the newly-started thread.
75         /// </summary>
76         public System.Action threadStart;
77 
78         /// <summary>
79         /// The thread stop hook for the communicator. The Ice run time
80         /// calls stop before it destroys a thread. The call is made by
81         /// thread that is about to be destroyed.
82         /// </summary>
83         public System.Action threadStop;
84 
85         /// <summary>
86         /// The dispatcher for the communicator.
87         /// </summary>
88         public System.Action<System.Action, Connection> dispatcher;
89 
90         /// <summary>
91         /// The compact type ID resolver.
92         /// </summary>
93         public System.Func<int, string> compactIdResolver;
94 
95         /// <summary>
96         /// The batch request interceptor.
97         /// </summary>
98         public System.Action<BatchRequest, int, int> batchRequestInterceptor;
99 
100         /// <summary>
101         /// The value factory manager.
102         /// </summary>
103         public ValueFactoryManager valueFactoryManager;
104 
105         /// <summary>
106         /// The list of TypeId namespaces. Default is Ice.TypeId.
107         /// </summary>
108         public string[] typeIdNamespaces = { "Ice.TypeId" };
109     }
110 
111     /// <summary>
112     /// Utility methods for the Ice run time.
113     /// </summary>
114     public sealed class Util
115     {
116         /// <summary>
117         /// Creates a new empty property set.
118         /// </summary>
119         /// <returns>A new empty property set.</returns>
createProperties()120         public static Properties createProperties()
121         {
122             return new PropertiesI();
123         }
124 
125         /// <summary>
126         /// Creates a property set initialized from an argument vector.
127         /// </summary>
128         /// <param name="args">A command-line argument vector, possibly containing
129         /// options to set properties. If the command-line options include
130         /// a --Ice.Config option, the corresponding configuration
131         /// files are parsed. If the same property is set in a configuration
132         /// file and in the argument vector, the argument vector takes precedence.
133         /// This method modifies the argument vector by removing any Ice-related options.</param>
134         /// <returns>A property set initialized with the property settings
135         /// that were removed from args.</returns>
createProperties(ref string[] args)136         public static Properties createProperties(ref string[] args)
137         {
138             return new PropertiesI(ref args, null);
139         }
140 
141         /// <summary>
142         /// Creates a property set initialized from an argument vector.
143         /// </summary>
144         /// <param name="args">A command-line argument vector, possibly containing
145         /// options to set properties. If the command-line options include
146         /// a --Ice.Config option, the corresponding configuration
147         /// files are parsed. If the same property is set in a configuration
148         /// file and in the argument vector, the argument vector takes precedence.
149         /// This method modifies the argument vector by removing any Ice-related options.</param>
150         /// <param name="defaults">Default values for the property set. Settings in configuration
151         /// files and args override these defaults.</param>
152         /// <returns>A property set initialized with the property settings
153         /// that were removed from args.</returns>
createProperties(ref string[] args, Properties defaults)154         public static Properties createProperties(ref string[] args, Properties defaults)
155         {
156             return new PropertiesI(ref args, defaults);
157         }
158 
159         /// <summary>
160         /// Creates a communicator.
161         /// </summary>
162         /// <param name="args">A command-line argument vector. Any Ice-related options
163         /// in this vector are used to intialize the communicator.
164         /// This method modifies the argument vector by removing any Ice-related options.</param>
165         /// <returns>The initialized communicator.</returns>
initialize(ref string[] args)166         public static Communicator initialize(ref string[] args)
167         {
168             return initialize(ref args, (InitializationData)null);
169         }
170 
171         /// <summary>
172         /// Creates a communicator.
173         /// </summary>
174         /// <param name="args">A command-line argument vector. Any Ice-related options
175         /// in this vector are used to initialize the communicator.
176         /// This method modifies the argument vector by removing any Ice-related options.</param>
177         /// <param name="initData">Additional intialization data. Property settings in args
178         /// override property settings in initData.</param>
179         /// <returns>The initialized communicator.</returns>
initialize(ref string[] args, InitializationData initData)180         public static Communicator initialize(ref string[] args, InitializationData initData)
181         {
182             if(initData == null)
183             {
184                 initData = new InitializationData();
185             }
186             else
187             {
188                 initData = (InitializationData)initData.Clone();
189             }
190 
191             initData.properties = createProperties(ref args, initData.properties);
192 
193             CommunicatorI result = new CommunicatorI(initData);
194             result.finishSetup(ref args);
195             return result;
196         }
197 
198         /// <summary>
199         /// Creates a communicator.
200         /// </summary>
201         /// <param name="args">A command-line argument vector. Any Ice-related options
202         /// in this vector are used to initialize the communicator.
203         /// This method modifies the argument vector by removing any Ice-related options.</param>
204         /// <param name="configFile">Path to a config file that sets the new communicator's default
205         /// properties.</param>
206         /// <returns>The initialized communicator.</returns>
initialize(ref string[] args, string configFile)207         public static Communicator initialize(ref string[] args, string configFile)
208         {
209             InitializationData initData = null;
210             if(configFile != null)
211             {
212                 initData = new InitializationData();
213                 initData.properties = Util.createProperties();
214                 initData.properties.load(configFile);
215             }
216             return initialize(ref args, initData);
217         }
218 
219         /// <summary>
220         /// Creates a communicator.
221         /// </summary>
222         /// <param name="initData">Additional intialization data.</param>
223         /// <returns>The initialized communicator.</returns>
initialize(InitializationData initData)224         public static Communicator initialize(InitializationData initData)
225         {
226             if(initData == null)
227             {
228                 initData = new InitializationData();
229             }
230             else
231             {
232                 initData = (InitializationData)initData.Clone();
233             }
234 
235             CommunicatorI result = new CommunicatorI(initData);
236             string[] args = new string[0];
237             result.finishSetup(ref args);
238             return result;
239         }
240 
241         /// <summary>
242         /// Creates a communicator.
243         /// </summary>
244         /// <param name="configFile">Path to a config file that sets the new communicator's default
245         /// properties.</param>
246         /// <returns>The initialized communicator.</returns>
initialize(string configFile)247         public static Communicator initialize(string configFile)
248         {
249             InitializationData initData = null;
250             if(configFile != null)
251             {
252                 initData = new InitializationData();
253                 initData.properties = Util.createProperties();
254                 initData.properties.load(configFile);
255             }
256             return initialize(initData);
257         }
258 
259         /// <summary>
260         /// Creates a communicator using a default configuration.
261         /// </summary>
initialize()262         public static Communicator initialize()
263         {
264             return initialize((InitializationData)null);
265         }
266 
267         /// <summary>
268         /// Converts a string to an object identity.
269         /// </summary>
270         /// <param name="s">The string to convert.</param>
271         /// <returns>The converted object identity.</returns>
stringToIdentity(string s)272         public static Identity stringToIdentity(string s)
273         {
274             Identity ident = new Identity();
275 
276             //
277             // Find unescaped separator; note that the string may contain an escaped
278             // backslash before the separator.
279             //
280             int slash = -1, pos = 0;
281             while((pos = s.IndexOf((System.Char) '/', pos)) != -1)
282             {
283                 int escapes = 0;
284                 while(pos - escapes > 0 && s[pos - escapes - 1] == '\\')
285                 {
286                     escapes++;
287                 }
288 
289                 //
290                 // We ignore escaped escapes
291                 //
292                 if(escapes % 2 == 0)
293                 {
294                     if(slash == -1)
295                     {
296                         slash = pos;
297                     }
298                     else
299                     {
300                         //
301                         // Extra unescaped slash found.
302                         //
303                         IdentityParseException ex = new IdentityParseException();
304                         ex.str = "unescaped backslash in identity `" + s + "'";
305                         throw ex;
306                     }
307                 }
308                 pos++;
309             }
310 
311             if(slash == -1)
312             {
313                 ident.category = "";
314                 try
315                 {
316                     ident.name = IceUtilInternal.StringUtil.unescapeString(s, 0, s.Length, "/");
317                 }
318                 catch(ArgumentException e)
319                 {
320                     IdentityParseException ex = new IdentityParseException();
321                     ex.str = "invalid identity name `" + s + "': " + e.Message;
322                     throw ex;
323                 }
324             }
325             else
326             {
327                 try
328                 {
329                     ident.category = IceUtilInternal.StringUtil.unescapeString(s, 0, slash, "/");
330                 }
331                 catch(ArgumentException e)
332                 {
333                     IdentityParseException ex = new IdentityParseException();
334                     ex.str = "invalid category in identity `" + s + "': " + e.Message;
335                     throw ex;
336                 }
337                 if(slash + 1 < s.Length)
338                 {
339                     try
340                     {
341                         ident.name = IceUtilInternal.StringUtil.unescapeString(s, slash + 1, s.Length, "/");
342                     }
343                     catch(ArgumentException e)
344                     {
345                         IdentityParseException ex = new IdentityParseException();
346                         ex.str = "invalid name in identity `" + s + "': " + e.Message;
347                         throw ex;
348                     }
349                 }
350                 else
351                 {
352                     ident.name = "";
353                 }
354             }
355 
356             return ident;
357         }
358 
359         /// <summary>
360         /// Converts an object identity to a string.
361         /// </summary>
362         /// <param name="ident">The object identity to convert.</param>
363         /// <param name="toStringMode">Specifies if and how non-printable ASCII characters are escaped in the result.</param>
364         /// <returns>The string representation of the object identity.</returns>
identityToString(Identity ident, ToStringMode toStringMode = ToStringMode.Unicode)365         public static string identityToString(Identity ident, ToStringMode toStringMode = ToStringMode.Unicode)
366         {
367             if(ident.category == null || ident.category.Length == 0)
368             {
369                 return IceUtilInternal.StringUtil.escapeString(ident.name, "/", toStringMode);
370             }
371             else
372             {
373                 return IceUtilInternal.StringUtil.escapeString(ident.category, "/", toStringMode) + '/' +
374                     IceUtilInternal.StringUtil.escapeString(ident.name, "/", toStringMode);
375             }
376         }
377 
378         /// <summary>
379         /// This method is deprecated. Use System.Guid instead.
380         /// </summary>
381         [Obsolete("This method is deprecated. Use System.Guid instead.")]
generateUUID()382         public static string generateUUID()
383         {
384             return Guid.NewGuid().ToString().ToUpper(System.Globalization.CultureInfo.InvariantCulture);
385         }
386 
387         /// <summary>
388         /// Compares the object identities of two proxies.
389         /// </summary>
390         /// <param name="lhs">A proxy.</param>
391         /// <param name="rhs">A proxy.</param>
392         /// <returns>-1 if the identity in lhs compares
393         /// less than the identity in rhs; 0 if the identities
394         /// compare equal; 1, otherwise.</returns>
proxyIdentityCompare(ObjectPrx lhs, ObjectPrx rhs)395         public static int proxyIdentityCompare(ObjectPrx lhs, ObjectPrx rhs)
396         {
397             if(lhs == null && rhs == null)
398             {
399                 return 0;
400             }
401             else if(lhs == null && rhs != null)
402             {
403                 return -1;
404             }
405             else if(lhs != null && rhs == null)
406             {
407                 return 1;
408             }
409             else
410             {
411                 Identity lhsIdentity = lhs.ice_getIdentity();
412                 Identity rhsIdentity = rhs.ice_getIdentity();
413                 int n;
414                 n = string.CompareOrdinal(lhsIdentity.name, rhsIdentity.name);
415                 if(n != 0)
416                 {
417                     return n;
418                 }
419                 return string.CompareOrdinal(lhsIdentity.category, rhsIdentity.category);
420             }
421         }
422 
423         /// <summary>
424         /// Compares the object identities and facets of two proxies.
425         /// </summary>
426         /// <param name="lhs">A proxy.</param>
427         /// <param name="rhs">A proxy.</param>
428         /// <returns>-1 if the identity and facet in lhs compare
429         /// less than the identity and facet in rhs; 0 if the identities
430         /// and facets compare equal; 1, otherwise.</returns>
proxyIdentityAndFacetCompare(ObjectPrx lhs, ObjectPrx rhs)431         public static int proxyIdentityAndFacetCompare(ObjectPrx lhs, ObjectPrx rhs)
432         {
433             if(lhs == null && rhs == null)
434             {
435                 return 0;
436             }
437             else if(lhs == null && rhs != null)
438             {
439                 return -1;
440             }
441             else if(lhs != null && rhs == null)
442             {
443                     return 1;
444             }
445             else
446             {
447                 Identity lhsIdentity = lhs.ice_getIdentity();
448                 Identity rhsIdentity = rhs.ice_getIdentity();
449                 int n;
450                 n = string.CompareOrdinal(lhsIdentity.name, rhsIdentity.name);
451                 if(n != 0)
452                 {
453                     return n;
454                 }
455                 n = string.CompareOrdinal(lhsIdentity.category, rhsIdentity.category);
456                 if(n != 0)
457                 {
458                     return n;
459                 }
460 
461                 string lhsFacet = lhs.ice_getFacet();
462                 string rhsFacet = rhs.ice_getFacet();
463                 if(lhsFacet == null && rhsFacet == null)
464                 {
465                     return 0;
466                 }
467                 else if(lhsFacet == null)
468                 {
469                     return -1;
470                 }
471                 else if(rhsFacet == null)
472                 {
473                     return 1;
474                 }
475                 else
476                 {
477                     return string.CompareOrdinal(lhsFacet, rhsFacet);
478                 }
479             }
480         }
481 
482         /// <summary>
483         /// Returns the process-wide logger.
484         /// </summary>
485         /// <returns>The process-wide logger.</returns>
getProcessLogger()486         public static Logger getProcessLogger()
487         {
488             lock(_processLoggerMutex)
489             {
490                 if(_processLogger == null)
491                 {
492                     _processLogger = new ConsoleLoggerI(AppDomain.CurrentDomain.FriendlyName);
493                 }
494                 return _processLogger;
495             }
496         }
497 
498         /// <summary>
499         /// Changes the process-wide logger.
500         /// </summary>
501         /// <param name="logger">The new process-wide logger.</param>
setProcessLogger(Logger logger)502         public static void setProcessLogger(Logger logger)
503         {
504             lock(_processLoggerMutex)
505             {
506                 _processLogger = logger;
507             }
508         }
509 
510         /// <summary>
511         /// Returns the Ice version in the form A.B.C, where A indicates the
512         /// major version, B indicates the minor version, and C indicates the
513         /// patch level.
514         /// </summary>
515         /// <returns>The Ice version.</returns>
stringVersion()516         public static string stringVersion()
517         {
518             return "3.7.2"; // "A.B.C", with A=major, B=minor, C=patch
519         }
520 
521         /// <summary>
522         /// Returns the Ice version as an integer in the form A.BB.CC, where A
523         /// indicates the major version, BB indicates the minor version, and CC
524         /// indicates the patch level. For example, for Ice 3.3.1, the returned value is 30301.
525         /// </summary>
526         /// <returns>The Ice version.</returns>
intVersion()527         public static int intVersion()
528         {
529             return 30702; // AABBCC, with AA=major, BB=minor, CC=patch
530         }
531 
532         /// <summary>
533         /// Converts a string to a protocol version.
534         /// </summary>
535         /// <param name="version">The string to convert.</param>
536         /// <returns>The converted protocol version.</returns>
stringToProtocolVersion(string version)537         public static ProtocolVersion stringToProtocolVersion(string version)
538         {
539             byte major, minor;
540             stringToMajorMinor(version, out major, out minor);
541             return new ProtocolVersion(major, minor);
542         }
543 
544         /// <summary>
545         /// Converts a string to an encoding version.
546         /// </summary>
547         /// <param name="version">The string to convert.</param>
548         /// <returns>The converted object identity.</returns>
stringToEncodingVersion(string version)549         public static EncodingVersion stringToEncodingVersion(string version)
550         {
551             byte major, minor;
552             stringToMajorMinor(version, out major, out minor);
553             return new EncodingVersion(major, minor);
554         }
555 
556         /// <summary>
557         /// Converts a protocol version to a string.
558         /// </summary>
559         /// <param name="v">The protocol version to convert.</param>
560         /// <returns>The converted string.</returns>
protocolVersionToString(Ice.ProtocolVersion v)561         public static string protocolVersionToString(Ice.ProtocolVersion v)
562         {
563             return majorMinorToString(v.major, v.minor);
564         }
565 
566         /// <summary>
567         /// Converts an encoding version to a string.
568         /// </summary>
569         /// <param name="v">The encoding version to convert.</param>
570         /// <returns>The converted string.</returns>
encodingVersionToString(Ice.EncodingVersion v)571         public static string encodingVersionToString(Ice.EncodingVersion v)
572         {
573             return majorMinorToString(v.major, v.minor);
574         }
575 
stringToMajorMinor(string str, out byte major, out byte minor)576         static private void stringToMajorMinor(string str, out byte major, out byte minor)
577         {
578             int pos = str.IndexOf('.');
579             if(pos == -1)
580             {
581                 throw new VersionParseException("malformed version value `" + str + "'");
582             }
583 
584             string majStr = str.Substring(0, (pos) - (0));
585             string minStr = str.Substring(pos + 1, (str.Length) - (pos + 1));
586             int majVersion;
587             int minVersion;
588             try
589             {
590                 majVersion = int.Parse(majStr, CultureInfo.InvariantCulture);
591                 minVersion = int.Parse(minStr, CultureInfo.InvariantCulture);
592             }
593             catch(FormatException)
594             {
595                 throw new VersionParseException("invalid version value `" + str + "'");
596             }
597 
598             if(majVersion < 1 || majVersion > 255 || minVersion < 0 || minVersion > 255)
599             {
600                 throw new VersionParseException("range error in version `" + str + "'");
601             }
602 
603             major = (byte)majVersion;
604             minor = (byte)minVersion;
605         }
606 
majorMinorToString(byte major, byte minor)607         static private string majorMinorToString(byte major, byte minor)
608         {
609             return string.Format("{0}.{1}", major, minor);
610         }
611 
registerPluginFactory(string name, PluginFactory factory, bool loadOnInit)612         public static void registerPluginFactory(string name, PluginFactory factory, bool loadOnInit)
613         {
614             PluginManagerI.registerPluginFactory(name, factory, loadOnInit);
615         }
616 
617         public static readonly ProtocolVersion currentProtocol =
618             new ProtocolVersion(IceInternal.Protocol.protocolMajor, IceInternal.Protocol.protocolMinor);
619 
620         public static readonly EncodingVersion currentProtocolEncoding =
621             new EncodingVersion(IceInternal.Protocol.protocolEncodingMajor,
622                                 IceInternal.Protocol.protocolEncodingMinor);
623 
624         public static readonly EncodingVersion currentEncoding =
625             new EncodingVersion(IceInternal.Protocol.encodingMajor, IceInternal.Protocol.encodingMinor);
626 
627         public static readonly ProtocolVersion Protocol_1_0 = new ProtocolVersion(1, 0);
628 
629         public static readonly EncodingVersion Encoding_1_0 = new EncodingVersion(1, 0);
630         public static readonly EncodingVersion Encoding_1_1 = new EncodingVersion(1, 1);
631 
632         public static readonly NoneType None = new NoneType();
633 
634         private static object _processLoggerMutex = new object();
635         private static Logger _processLogger = null;
636     }
637 }
638 
639 namespace IceInternal
640 {
641     public sealed class HashUtil
642     {
hashAdd(ref int hashCode, bool value)643         public static void hashAdd(ref int hashCode, bool value)
644         {
645             hashCode = unchecked(((hashCode << 5) + hashCode) ^ value.GetHashCode());
646         }
647 
hashAdd(ref int hashCode, short value)648         public static void hashAdd(ref int hashCode, short value)
649         {
650             hashCode = unchecked(((hashCode << 5) + hashCode) ^ (int)(2654435761 * value));
651         }
652 
hashAdd(ref int hashCode, byte value)653         public static void hashAdd(ref int hashCode, byte value)
654         {
655             hashCode = unchecked(((hashCode << 5) + hashCode) ^ (int)(2654435761 * value));
656         }
657 
hashAdd(ref int hashCode, int value)658         public static void hashAdd(ref int hashCode, int value)
659         {
660             hashCode = unchecked(((hashCode << 5) + hashCode) ^ (int)(2654435761 * value));
661         }
662 
hashAdd(ref int hashCode, long value)663         public static void hashAdd(ref int hashCode, long value)
664         {
665             hashCode = unchecked(((hashCode << 5) + hashCode) ^ value.GetHashCode());
666         }
667 
hashAdd(ref int hashCode, float value)668         public static void hashAdd(ref int hashCode, float value)
669         {
670             hashCode = unchecked(((hashCode << 5) + hashCode) ^ value.GetHashCode());
671         }
672 
hashAdd(ref int hashCode, double value)673         public static void hashAdd(ref int hashCode, double value)
674         {
675             hashCode = unchecked(((hashCode << 5) + hashCode) ^ value.GetHashCode());
676         }
677 
hashAdd(ref int hashCode, object value)678         public static void hashAdd(ref int hashCode, object value)
679         {
680             if(value != null)
681             {
682                 hashCode = unchecked(((hashCode << 5) + hashCode) ^ value.GetHashCode());
683             }
684         }
685 
hashAdd(ref int hashCode, object[] arr)686         public static void hashAdd(ref int hashCode, object[] arr)
687         {
688             if(arr != null)
689             {
690                 hashCode = unchecked(((hashCode << 5) + hashCode) ^ IceUtilInternal.Arrays.GetHashCode(arr));
691             }
692         }
693 
hashAdd(ref int hashCode, Array arr)694         public static void hashAdd(ref int hashCode, Array arr)
695         {
696             if(arr != null)
697             {
698                 hashCode = unchecked(((hashCode << 5) + hashCode) ^ IceUtilInternal.Arrays.GetHashCode(arr));
699             }
700         }
701 
hashAdd(ref int hashCode, IEnumerable s)702         public static void hashAdd(ref int hashCode, IEnumerable s)
703         {
704             if(s != null)
705             {
706                 hashCode = unchecked(((hashCode << 5) + hashCode) ^ IceUtilInternal.Collections.SequenceGetHashCode(s));
707             }
708         }
709 
hashAdd(ref int hashCode, IDictionary d)710         public static void hashAdd(ref int hashCode, IDictionary d)
711         {
712             if(d != null)
713             {
714                 hashCode = unchecked(((hashCode << 5) + hashCode) ^ IceUtilInternal.Collections.DictionaryGetHashCode(d));
715             }
716         }
717     }
718 
719     public sealed class Util
720     {
getInstance(Ice.Communicator communicator)721         public static Instance getInstance(Ice.Communicator communicator)
722         {
723             Ice.CommunicatorI p = (Ice.CommunicatorI) communicator;
724             return p.getInstance();
725         }
726 
getProtocolPluginFacade(Ice.Communicator communicator)727         public static ProtocolPluginFacade getProtocolPluginFacade(Ice.Communicator communicator)
728         {
729             return new ProtocolPluginFacadeI(communicator);
730         }
731 
stringToThreadPriority(string s)732         public static ThreadPriority stringToThreadPriority(string s)
733         {
734             if(string.IsNullOrEmpty(s))
735             {
736                 return ThreadPriority.Normal;
737             }
738             if(s.StartsWith("ThreadPriority.", StringComparison.Ordinal))
739             {
740                 s = s.Substring("ThreadPriority.".Length, s.Length);
741             }
742             if(s.Equals("Lowest"))
743             {
744                 return ThreadPriority.Lowest;
745             }
746             else if(s.Equals("BelowNormal"))
747             {
748                 return ThreadPriority.BelowNormal;
749             }
750             else if(s.Equals("Normal"))
751             {
752                 return ThreadPriority.Normal;
753             }
754             else if(s.Equals("AboveNormal"))
755             {
756                 return ThreadPriority.AboveNormal;
757             }
758             else if(s.Equals("Highest"))
759             {
760                 return ThreadPriority.Highest;
761             }
762             return ThreadPriority.Normal;
763         }
764     }
765 }
766