1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7 **
8 **  File:    RemotingConfigParser.cs
9 **
10 **  Purpose: Parse remoting configuration files.
11 **
12 **
13 ===========================================================*/
14 
15 using System;
16 using System.Collections;
17 using System.IO;
18 using System.Reflection;
19 using System.Runtime.Remoting;
20 using System.Runtime.Remoting.Channels;
21 using System.Globalization;
22 using System.Runtime.Versioning;
23 
24 namespace System.Runtime.Remoting.Activation {
25 
26 
27     internal class RemotingXmlConfigFileData
28     {
29         // debug settings
30         internal static volatile bool LoadTypes = false; // indicates whether we should attempt to load types in config files
31 
32 
33         //
34         // configuration entry storage classes (in alphabetical order)
35         //   There is one class for each type of entry in a remoting config file.
36         //
37 
38         internal class ChannelEntry
39         {
40             internal String TypeName;
41             internal String AssemblyName;
42             internal Hashtable Properties;
43             internal bool DelayLoad = false;
44             internal ArrayList ClientSinkProviders = new ArrayList();
45             internal ArrayList ServerSinkProviders = new ArrayList();
46 
ChannelEntry(String typeName, String assemblyName, Hashtable properties)47             internal ChannelEntry(String typeName, String assemblyName, Hashtable properties)
48             {
49                 TypeName = typeName;
50                 AssemblyName = assemblyName;
51                 Properties = properties;
52             } // ChannelEntry
53         } // class ChannelEntry
54 
55 
56         internal class ClientWellKnownEntry
57         {
58             internal String TypeName;
59             internal String AssemblyName;
60             internal String Url;
61 
ClientWellKnownEntry(String typeName, String assemName, String url)62             internal ClientWellKnownEntry(String typeName, String assemName, String url)
63             {
64                 TypeName = typeName;
65                 AssemblyName = assemName;
66                 Url = url;
67             }
68         } // class ClientWellKnownEntry
69 
70 
71         internal class ContextAttributeEntry
72         {
73             internal String TypeName;
74             internal String AssemblyName;
75             internal Hashtable Properties;
76 
ContextAttributeEntry(String typeName, String assemName, Hashtable properties)77             internal ContextAttributeEntry(String typeName, String assemName, Hashtable properties)
78             {
79                 TypeName = typeName;
80                 AssemblyName = assemName;
81                 Properties = properties;
82             }
83         } // class ContextAttributeEntry
84 
85 
86         internal class InteropXmlElementEntry
87         {
88             internal String XmlElementName;
89             internal String XmlElementNamespace;
90             internal String UrtTypeName;
91             internal String UrtAssemblyName;
92 
InteropXmlElementEntry(String xmlElementName, String xmlElementNamespace, String urtTypeName, String urtAssemblyName)93             internal InteropXmlElementEntry(String xmlElementName, String xmlElementNamespace,
94                                             String urtTypeName, String urtAssemblyName)
95             {
96                 XmlElementName = xmlElementName;
97                 XmlElementNamespace = xmlElementNamespace;
98                 UrtTypeName = urtTypeName;
99                 UrtAssemblyName = urtAssemblyName;
100             }
101         } // class InteropXmlElementEntry
102 
103         internal class CustomErrorsEntry {
104             internal CustomErrorsModes Mode;
105 
CustomErrorsEntry(CustomErrorsModes mode)106             internal CustomErrorsEntry(CustomErrorsModes mode) {
107                 Mode = mode;
108             }
109         }
110 
111         internal class InteropXmlTypeEntry
112         {
113             internal String XmlTypeName;
114             internal String XmlTypeNamespace;
115             internal String UrtTypeName;
116             internal String UrtAssemblyName;
117 
InteropXmlTypeEntry(String xmlTypeName, String xmlTypeNamespace, String urtTypeName, String urtAssemblyName)118             internal InteropXmlTypeEntry(String xmlTypeName, String xmlTypeNamespace,
119                                          String urtTypeName, String urtAssemblyName)
120             {
121                 XmlTypeName = xmlTypeName;
122                 XmlTypeNamespace = xmlTypeNamespace;
123                 UrtTypeName = urtTypeName;
124                 UrtAssemblyName = urtAssemblyName;
125             }
126         } // class InteropXmlTypeEntry
127 
128 
129         internal class LifetimeEntry
130         {
131             // If any of these are false, then the corresponding property wasn't specified
132             //   in the config file.
133             internal bool IsLeaseTimeSet = false;
134             internal bool IsRenewOnCallTimeSet = false;
135             internal bool IsSponsorshipTimeoutSet = false;
136             internal bool IsLeaseManagerPollTimeSet = false;
137 
138             private TimeSpan _leaseTime;
139             private TimeSpan _renewOnCallTime;
140             private TimeSpan _sponsorshipTimeout;
141             private TimeSpan _leaseManagerPollTime;
142 
143             internal TimeSpan LeaseTime {
144                 get
145                 {
146                     BCLDebug.Assert(IsLeaseTimeSet == true, "LeaseTime not set");
147                     return _leaseTime;
148                 }
149                 set
150                 {
151                     _leaseTime = value;
152                     IsLeaseTimeSet = true;
153                 }
154             }
155 
156             internal TimeSpan RenewOnCallTime {
157                 get
158                 {
159                     BCLDebug.Assert(IsRenewOnCallTimeSet == true, "RenewOnCallTime not set");
160                     return _renewOnCallTime;
161                 }
162                 set
163                 {
164                     _renewOnCallTime = value;
165                     IsRenewOnCallTimeSet = true;
166                 }
167             }
168 
169             internal TimeSpan SponsorshipTimeout {
170                 get
171                 {
172                     BCLDebug.Assert(IsSponsorshipTimeoutSet == true, "SponsorShipTimeout not set");
173                     return _sponsorshipTimeout;
174                 }
175                 set
176                 {
177                     _sponsorshipTimeout = value;
178                     IsSponsorshipTimeoutSet = true;
179                 }
180             }
181 
182             internal TimeSpan LeaseManagerPollTime {
183                 get
184                 {
185                     BCLDebug.Assert(IsLeaseManagerPollTimeSet == true, "LeaseManagerPollTime not set");
186                     return _leaseManagerPollTime;
187                 }
188                 set
189                 {
190                     _leaseManagerPollTime = value;
191                     IsLeaseManagerPollTimeSet = true;
192                 }
193             }
194 
195         } // class LifetimeEntry
196 
197 
198         internal class PreLoadEntry
199         {
200             // If TypeName is null, then all types in the assembly specified
201             //   should be preloaded.
202 
203             internal String TypeName;
204             internal String AssemblyName;
205 
PreLoadEntry(String typeName, String assemblyName)206             public PreLoadEntry(String typeName, String assemblyName)
207             {
208                 TypeName = typeName;
209                 AssemblyName = assemblyName;
210             }
211         } // class PreLoadEntry
212 
213 
214         internal class RemoteAppEntry
215         {
216             internal String AppUri;
217 
218             internal ArrayList WellKnownObjects = new ArrayList();
219             internal ArrayList ActivatedObjects = new ArrayList();
220 
RemoteAppEntry(String appUri)221             internal RemoteAppEntry(String appUri)
222             {
223                 AppUri = appUri;
224             }
225 
AddWellKnownEntry(String typeName, String assemName, String url)226             internal void AddWellKnownEntry(String typeName, String assemName, String url)
227             {
228                 ClientWellKnownEntry cwke = new ClientWellKnownEntry(typeName, assemName, url);
229                 WellKnownObjects.Add(cwke);
230             }
231 
AddActivatedEntry(String typeName, String assemName, ArrayList contextAttributes)232             internal void AddActivatedEntry(String typeName, String assemName,
233                                             ArrayList contextAttributes)
234             {
235                 TypeEntry te = new TypeEntry(typeName, assemName, contextAttributes);
236                 ActivatedObjects.Add(te);
237             }
238 
239         } // class RemoteAppEntry
240 
241 
242         internal class ServerWellKnownEntry : TypeEntry
243         {
244             internal String ObjectURI;
245             internal WellKnownObjectMode ObjectMode;
246 
ServerWellKnownEntry( String typeName, String assemName, ArrayList contextAttributes, String objURI, WellKnownObjectMode objMode)247             internal ServerWellKnownEntry(
248                 String typeName, String assemName, ArrayList contextAttributes,
249                 String objURI, WellKnownObjectMode objMode) :
250                     base(typeName, assemName, contextAttributes)
251             {
252                 ObjectURI = objURI;
253                 ObjectMode = objMode;
254             }
255         } // class ServerWellKnownEntry
256 
257 
258         internal class SinkProviderEntry
259         {
260             internal String TypeName;
261             internal String AssemblyName;
262             internal Hashtable Properties;
263             internal ArrayList ProviderData = new ArrayList(); // array of SinkProviderData structures
264             internal bool IsFormatter; // Is this a formatter sink provider?
265 
SinkProviderEntry(String typeName, String assemName, Hashtable properties, bool isFormatter)266             internal SinkProviderEntry(String typeName, String assemName, Hashtable properties,
267                                        bool isFormatter)
268             {
269                 TypeName = typeName;
270                 AssemblyName = assemName;
271                 Properties = properties;
272                 IsFormatter = isFormatter;
273             }
274         } // class SinkProviderEntry
275 
276 
277         internal class TypeEntry
278         {
279             internal String TypeName;
280             internal String AssemblyName;
281             internal ArrayList ContextAttributes;
282 
TypeEntry(String typeName, String assemName, ArrayList contextAttributes)283             internal TypeEntry(String typeName, String assemName,
284                                ArrayList contextAttributes)
285             {
286                 TypeName = typeName;
287                 AssemblyName = assemName;
288                 ContextAttributes = contextAttributes;
289             }
290         } // class TypeEntry
291 
292 
293         //
294         // end of configuration entry storage classes
295         //
296 
297 
298         //
299         // configuration data access
300         //
301 
302         internal String ApplicationName = null;  // application name
303         internal LifetimeEntry Lifetime = null;  // corresponds to top-level lifetime element
304         internal bool UrlObjRefMode = RemotingConfigHandler.UrlObjRefMode;  // should url obj ref's be used?
305         internal CustomErrorsEntry CustomErrors = null;
306 
307         internal ArrayList ChannelEntries = new ArrayList();
308         internal ArrayList InteropXmlElementEntries = new ArrayList();
309         internal ArrayList InteropXmlTypeEntries = new ArrayList();
310         internal ArrayList PreLoadEntries = new ArrayList();
311         internal ArrayList RemoteAppEntries = new ArrayList();
312         internal ArrayList ServerActivatedEntries = new ArrayList();
313         internal ArrayList ServerWellKnownEntries = new ArrayList();
314 
315 
316         //
317         // end of configuration data access
318         //
319 
320 
321         //
322         // modify configuration data (for multiple entry entities)
323         //
324 
AddInteropXmlElementEntry(String xmlElementName, String xmlElementNamespace, String urtTypeName, String urtAssemblyName)325         internal void AddInteropXmlElementEntry(String xmlElementName, String xmlElementNamespace,
326                                                 String urtTypeName, String urtAssemblyName)
327         {
328             TryToLoadTypeIfApplicable(urtTypeName, urtAssemblyName);
329             InteropXmlElementEntry ixee = new InteropXmlElementEntry(
330                 xmlElementName, xmlElementNamespace, urtTypeName, urtAssemblyName);
331             InteropXmlElementEntries.Add(ixee);
332         }
333 
AddInteropXmlTypeEntry(String xmlTypeName, String xmlTypeNamespace, String urtTypeName, String urtAssemblyName)334         internal void AddInteropXmlTypeEntry(String xmlTypeName, String xmlTypeNamespace,
335                                              String urtTypeName, String urtAssemblyName)
336         {
337             TryToLoadTypeIfApplicable(urtTypeName, urtAssemblyName);
338             InteropXmlTypeEntry ixte = new InteropXmlTypeEntry(xmlTypeName, xmlTypeNamespace,
339                                                                urtTypeName, urtAssemblyName);
340             InteropXmlTypeEntries.Add(ixte);
341         }
342 
AddPreLoadEntry(String typeName, String assemblyName)343         internal void AddPreLoadEntry(String typeName, String assemblyName)
344         {
345             TryToLoadTypeIfApplicable(typeName, assemblyName);
346             PreLoadEntry ple = new PreLoadEntry(typeName, assemblyName);
347             PreLoadEntries.Add(ple);
348         }
349 
AddRemoteAppEntry(String appUri)350         internal RemoteAppEntry AddRemoteAppEntry(String appUri)
351         {
352             RemoteAppEntry rae = new RemoteAppEntry(appUri);
353             RemoteAppEntries.Add(rae);
354             return rae;
355         }
356 
AddServerActivatedEntry(String typeName, String assemName, ArrayList contextAttributes)357         internal void AddServerActivatedEntry(String typeName, String assemName,
358                                               ArrayList contextAttributes)
359         {
360             TryToLoadTypeIfApplicable(typeName, assemName);
361             TypeEntry te = new TypeEntry(typeName, assemName, contextAttributes);
362             ServerActivatedEntries.Add(te);
363         }
364 
AddServerWellKnownEntry(String typeName, String assemName, ArrayList contextAttributes, String objURI, WellKnownObjectMode objMode)365         internal ServerWellKnownEntry AddServerWellKnownEntry(String typeName, String assemName,
366             ArrayList contextAttributes, String objURI, WellKnownObjectMode objMode)
367         {
368             TryToLoadTypeIfApplicable(typeName, assemName);
369             ServerWellKnownEntry swke = new ServerWellKnownEntry(typeName, assemName,
370                 contextAttributes, objURI, objMode);
371             ServerWellKnownEntries.Add(swke);
372             return swke;
373         }
374 
375 
376         // debug settings helper
TryToLoadTypeIfApplicable(String typeName, String assemblyName)377         private void TryToLoadTypeIfApplicable(String typeName, String assemblyName)
378         {
379             if (!LoadTypes)
380                 return;
381 
382             Assembly asm = Assembly.Load(assemblyName);
383             if (asm == null)
384             {
385                 throw new RemotingException(
386                     Environment.GetResourceString("Remoting_AssemblyLoadFailed",
387                     assemblyName));
388             }
389 
390             Type type = asm.GetType(typeName, false, false);
391             if (type == null)
392             {
393                 throw new RemotingException(
394                     Environment.GetResourceString("Remoting_BadType",
395                     typeName));
396             }
397         }
398 
399     } // RemotingXmlConfigFileData
400 
401 
402 
403 
404     internal static class RemotingXmlConfigFileParser
405     {
406         // template arrays
407         private static Hashtable _channelTemplates = CreateSyncCaseInsensitiveHashtable();
408         private static Hashtable _clientChannelSinkTemplates = CreateSyncCaseInsensitiveHashtable();
409         private static Hashtable _serverChannelSinkTemplates = CreateSyncCaseInsensitiveHashtable();
410 
411 
CreateSyncCaseInsensitiveHashtable()412         private static Hashtable CreateSyncCaseInsensitiveHashtable()
413         {
414             return Hashtable.Synchronized(CreateCaseInsensitiveHashtable());
415         }
416 
CreateCaseInsensitiveHashtable()417         private static Hashtable CreateCaseInsensitiveHashtable()
418         {
419             return new Hashtable(StringComparer.InvariantCultureIgnoreCase);
420         }
421 
422 
ParseDefaultConfiguration()423         public static RemotingXmlConfigFileData ParseDefaultConfiguration() {
424             ConfigNode node;
425 
426             // <system.runtime.remoting>
427             ConfigNode rootNode = new ConfigNode("system.runtime.remoting", null);
428 
429             /*
430             <application>
431                 <channels>
432                     <channel ref="http client" displayName="http client (delay loaded)" delayLoadAsClientChannel="true" />
433                     <channel ref="tcp client" displayName="tcp client (delay loaded)" delayLoadAsClientChannel="true" />
434                     <channel ref="ipc client" displayName="ipc client (delay loaded)" delayLoadAsClientChannel="true" />
435                 </channels>
436             </application>
437             */
438             ConfigNode appNode = new ConfigNode("application", rootNode);
439             rootNode.Children.Add(appNode);
440 
441             ConfigNode channelsNode = new ConfigNode("channels", appNode);
442             appNode.Children.Add(channelsNode);
443 
444             node = new ConfigNode("channel", appNode);
445             node.Attributes.Add(new DictionaryEntry("ref", "http client"));
446             node.Attributes.Add(new DictionaryEntry("displayName", "http client (delay loaded)"));
447             node.Attributes.Add(new DictionaryEntry("delayLoadAsClientChannel", "true"));
448             channelsNode.Children.Add(node);
449 
450             node = new ConfigNode("channel", appNode);
451             node.Attributes.Add(new DictionaryEntry("ref", "tcp client"));
452             node.Attributes.Add(new DictionaryEntry("displayName", "tcp client (delay loaded)"));
453             node.Attributes.Add(new DictionaryEntry("delayLoadAsClientChannel", "true"));
454             channelsNode.Children.Add(node);
455 
456             node = new ConfigNode("channel", appNode);
457             node.Attributes.Add(new DictionaryEntry("ref", "ipc client"));
458             node.Attributes.Add(new DictionaryEntry("displayName", "ipc client (delay loaded)"));
459             node.Attributes.Add(new DictionaryEntry("delayLoadAsClientChannel", "true"));
460             channelsNode.Children.Add(node);
461 
462             /*
463             <channels>
464                 <channel id="http" type="System.Runtime.Remoting.Channels.Http.HttpChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
465                 <channel id="http client" type="System.Runtime.Remoting.Channels.Http.HttpClientChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
466                 <channel id="http server" type="System.Runtime.Remoting.Channels.Http.HttpServerChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
467                 <channel id="tcp" type="System.Runtime.Remoting.Channels.Tcp.TcpChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
468                 <channel id="tcp client" type="System.Runtime.Remoting.Channels.Tcp.TcpClientChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
469                 <channel id="tcp server" type="System.Runtime.Remoting.Channels.Tcp.TcpServerChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
470                 <channel id="ipc" type="System.Runtime.Remoting.Channels.Ipc.IpcChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
471                 <channel id="ipc client" type="System.Runtime.Remoting.Channels.Ipc.IpcClientChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
472                 <channel id="ipc server" type="System.Runtime.Remoting.Channels.Ipc.IpcServerChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
473             </channels>
474             */
475             channelsNode = new ConfigNode("channels", rootNode);
476             rootNode.Children.Add(channelsNode);
477 
478             node = new ConfigNode("channel", channelsNode);
479             node.Attributes.Add(new DictionaryEntry("id", "http"));
480             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Http.HttpChannel, " + AssemblyRef.SystemRuntimeRemoting));
481             channelsNode.Children.Add(node);
482 
483             node = new ConfigNode("channel", channelsNode);
484             node.Attributes.Add(new DictionaryEntry("id", "http client"));
485             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Http.HttpClientChannel, " + AssemblyRef.SystemRuntimeRemoting));
486             channelsNode.Children.Add(node);
487 
488             node = new ConfigNode("channel", channelsNode);
489             node.Attributes.Add(new DictionaryEntry("id", "http server"));
490             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Http.HttpServerChannel, " + AssemblyRef.SystemRuntimeRemoting));
491             channelsNode.Children.Add(node);
492 
493             node = new ConfigNode("channel", channelsNode);
494             node.Attributes.Add(new DictionaryEntry("id", "tcp"));
495             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Tcp.TcpChannel, " + AssemblyRef.SystemRuntimeRemoting));
496             channelsNode.Children.Add(node);
497 
498             node = new ConfigNode("channel", channelsNode);
499             node.Attributes.Add(new DictionaryEntry("id", "tcp client"));
500             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Tcp.TcpClientChannel, " + AssemblyRef.SystemRuntimeRemoting));
501             channelsNode.Children.Add(node);
502 
503             node = new ConfigNode("channel", channelsNode);
504             node.Attributes.Add(new DictionaryEntry("id", "tcp server"));
505             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Tcp.TcpServerChannel, " + AssemblyRef.SystemRuntimeRemoting));
506             channelsNode.Children.Add(node);
507 
508             node = new ConfigNode("channel", channelsNode);
509             node.Attributes.Add(new DictionaryEntry("id", "ipc"));
510             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Ipc.IpcChannel, " + AssemblyRef.SystemRuntimeRemoting));
511             channelsNode.Children.Add(node);
512 
513             node = new ConfigNode("channel", channelsNode);
514             node.Attributes.Add(new DictionaryEntry("id", "ipc client"));
515             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Ipc.IpcClientChannel, " + AssemblyRef.SystemRuntimeRemoting));
516             channelsNode.Children.Add(node);
517 
518             node = new ConfigNode("channel", channelsNode);
519             node.Attributes.Add(new DictionaryEntry("id", "ipc server"));
520             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Ipc.IpcServerChannel, " + AssemblyRef.SystemRuntimeRemoting));
521             channelsNode.Children.Add(node);
522 
523             /*
524             <channelSinkProviders>
525                 <clientProviders>
526                     <formatter id="soap" type="System.Runtime.Remoting.Channels.SoapClientFormatterSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
527                     <formatter id="binary" type="System.Runtime.Remoting.Channels.BinaryClientFormatterSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
528                 </clientProviders>
529                 <serverProviders>
530                     <formatter id="soap" type="System.Runtime.Remoting.Channels.SoapServerFormatterSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
531                     <formatter id="binary" type="System.Runtime.Remoting.Channels.BinaryServerFormatterSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
532                     <provider id="wsdl" type="System.Runtime.Remoting.MetadataServices.SdlChannelSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
533                 </serverProviders>
534             </channelSinkProviders>
535             */
536             ConfigNode channelsSinkNode = new ConfigNode("channelSinkProviders", rootNode);
537             rootNode.Children.Add(channelsSinkNode);
538 
539             ConfigNode clientProvidersNode = new ConfigNode("clientProviders", channelsSinkNode);
540             channelsSinkNode.Children.Add(clientProvidersNode);
541 
542             node = new ConfigNode("formatter", clientProvidersNode);
543             node.Attributes.Add(new DictionaryEntry("id", "soap"));
544             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.SoapClientFormatterSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
545             clientProvidersNode.Children.Add(node);
546 
547             node = new ConfigNode("formatter", clientProvidersNode);
548             node.Attributes.Add(new DictionaryEntry("id", "binary"));
549             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.BinaryClientFormatterSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
550             clientProvidersNode.Children.Add(node);
551 
552             ConfigNode serverProvidersNode = new ConfigNode("serverProviders", channelsSinkNode);
553             channelsSinkNode.Children.Add(serverProvidersNode);
554 
555             node = new ConfigNode("formatter", serverProvidersNode);
556             node.Attributes.Add(new DictionaryEntry("id", "soap"));
557             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.SoapServerFormatterSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
558             serverProvidersNode.Children.Add(node);
559 
560             node = new ConfigNode("formatter", serverProvidersNode);
561             node.Attributes.Add(new DictionaryEntry("id", "binary"));
562             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.BinaryServerFormatterSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
563             serverProvidersNode.Children.Add(node);
564 
565             node = new ConfigNode("provider", serverProvidersNode);
566             node.Attributes.Add(new DictionaryEntry("id", "wsdl"));
567             node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.MetadataServices.SdlChannelSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
568             serverProvidersNode.Children.Add(node);
569 
570             return ParseConfigNode(rootNode);
571         }
572 
573 
574         [ResourceExposure(ResourceScope.Machine)]
575         [ResourceConsumption(ResourceScope.Machine)]
ParseConfigFile(String filename)576         public static RemotingXmlConfigFileData ParseConfigFile(String filename)
577         {
578             ConfigTreeParser parser = new ConfigTreeParser();
579             ConfigNode rootNode = parser.Parse(filename, "/configuration/system.runtime.remoting");
580 
581             return ParseConfigNode(rootNode);
582         }
583 
ParseConfigNode(ConfigNode rootNode)584         private static RemotingXmlConfigFileData ParseConfigNode(ConfigNode rootNode)
585         {
586             RemotingXmlConfigFileData configData = new RemotingXmlConfigFileData();
587 
588             // check to see if this file has a system.runtime.remoting section
589             if (rootNode == null)
590                 return null;
591 
592             // process attributes
593             foreach (DictionaryEntry entry in rootNode.Attributes)
594             {
595                 String key = entry.Key.ToString();
596                 switch (key)
597                 {
598                 case "version":
599                 {
600                     // we ignore the version attribute because this may be used
601                     //   by the configuration system
602                     break;
603                 }
604 
605                 default: break;
606                 } // switch
607             } // foreach
608 
609             ConfigNode appNode = null;       // "application" node
610             ConfigNode channelsNode = null;  // "channels" node
611             ConfigNode providerNode = null;  // "channelSinkProviders" node
612             ConfigNode debugNode = null;     // "debug" node
613             ConfigNode customErrorsNode = null;     // "customErrors" node
614 
615             foreach (ConfigNode node in rootNode.Children)
616             {
617                 switch (node.Name)
618                 {
619 
620                 case "application":
621                 {
622                     // there can only be one application node in a config file
623                     if (appNode != null)
624                         ReportUniqueSectionError(rootNode, appNode, configData);
625 
626                     appNode = node;
627                     break;
628                 } // case "application"
629 
630                 case "channels":
631                 {
632                     if (channelsNode != null)
633                         ReportUniqueSectionError(rootNode, channelsNode, configData);
634 
635                     channelsNode = node;
636                     break;
637                 } // case "channels"
638 
639                 case "channelSinkProviders":
640                 {
641                     if (providerNode != null)
642                         ReportUniqueSectionError(rootNode, providerNode, configData);
643 
644                     providerNode = node;
645                     break;
646                 } // case "channelSinkProviders"
647 
648                 case "debug":
649                 {
650                     if (debugNode != null)
651                         ReportUniqueSectionError(rootNode, debugNode, configData);
652 
653                     debugNode = node;
654                     break;
655                 } // case "debug"
656 
657                 case "customErrors":
658                 {
659                     if (customErrorsNode != null)
660                         ReportUniqueSectionError(rootNode, customErrorsNode, configData);
661 
662                     customErrorsNode = node;
663                     break;
664                 }// case "customErrors"
665 
666                 default: break;
667                 } // switch
668             } // foreach
669 
670 
671             if (debugNode != null)
672                 ProcessDebugNode(debugNode, configData);
673 
674             if (providerNode != null)
675                 ProcessChannelSinkProviderTemplates(providerNode, configData);
676 
677             if (channelsNode != null)
678                 ProcessChannelTemplates(channelsNode, configData);
679 
680             if (appNode != null)
681                 ProcessApplicationNode(appNode, configData);
682 
683             if (customErrorsNode != null)
684                 ProcessCustomErrorsNode(customErrorsNode, configData);
685 
686             return configData;
687         } // ParseConfigFile
688 
689 
ReportError(String errorStr, RemotingXmlConfigFileData configData)690         private static void ReportError(String errorStr, RemotingXmlConfigFileData configData)
691         {
692             // <
693 
694 
695             throw new RemotingException(errorStr);
696         } // ReportError
697 
698         // means section must be unique
ReportUniqueSectionError(ConfigNode parent, ConfigNode child, RemotingXmlConfigFileData configData)699         private static void ReportUniqueSectionError(ConfigNode parent, ConfigNode child,
700                                                      RemotingXmlConfigFileData configData)
701         {
702             ReportError(
703                 String.Format(
704                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_NodeMustBeUnique"),
705                     child.Name, parent.Name),
706                 configData);
707         } // ReportUniqueSectionError
708 
ReportUnknownValueError(ConfigNode node, String value, RemotingXmlConfigFileData configData)709         private static void ReportUnknownValueError(ConfigNode node, String value,
710                                                         RemotingXmlConfigFileData configData)
711         {
712             ReportError(
713                 String.Format(
714                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_UnknownValue"),
715                     node.Name, value),
716                 configData);
717         } // ReportUnknownValueError
718 
ReportMissingAttributeError(ConfigNode node, String attributeName, RemotingXmlConfigFileData configData)719         private static void ReportMissingAttributeError(ConfigNode node, String attributeName,
720                                                         RemotingXmlConfigFileData configData)
721         {
722             ReportMissingAttributeError(node.Name, attributeName, configData);
723         } // ReportMissingAttributeError
724 
ReportMissingAttributeError(String nodeDescription, String attributeName, RemotingXmlConfigFileData configData)725         private static void ReportMissingAttributeError(String nodeDescription, String attributeName,
726                                                         RemotingXmlConfigFileData configData)
727         {
728             ReportError(
729                 String.Format(
730                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_RequiredXmlAttribute"),
731                     nodeDescription, attributeName),
732                 configData);
733         } // ReportMissingAttributeError
734 
ReportMissingTypeAttributeError(ConfigNode node, String attributeName, RemotingXmlConfigFileData configData)735         private static void ReportMissingTypeAttributeError(ConfigNode node, String attributeName,
736                                                             RemotingXmlConfigFileData configData)
737         {
738             ReportError(
739                 String.Format(
740                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_MissingTypeAttribute"),
741                     node.Name, attributeName),
742                 configData);
743         } // ReportMissingAttributeError
744 
ReportMissingXmlTypeAttributeError(ConfigNode node, String attributeName, RemotingXmlConfigFileData configData)745         private static void ReportMissingXmlTypeAttributeError(ConfigNode node, String attributeName,
746                                                                RemotingXmlConfigFileData configData)
747         {
748             ReportError(
749                 String.Format(
750                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_MissingXmlTypeAttribute"),
751                     node.Name, attributeName),
752                 configData);
753         } // ReportMissingAttributeError
754 
ReportInvalidTimeFormatError(String time, RemotingXmlConfigFileData configData)755         private static void ReportInvalidTimeFormatError(String time,
756                                                          RemotingXmlConfigFileData configData)
757         {
758             ReportError(
759                 String.Format(
760                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_InvalidTimeFormat"),
761                     time),
762                 configData);
763         } // ReportInvalidTypeFormatError
764 
765         // If nodes can be represented as a template, only a template version
766         //   can have an 'id' attribute
ReportNonTemplateIdAttributeError(ConfigNode node, RemotingXmlConfigFileData configData)767         private static void ReportNonTemplateIdAttributeError(ConfigNode node,
768                                                               RemotingXmlConfigFileData configData)
769         {
770             ReportError(
771                 String.Format(
772                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_NonTemplateIdAttribute"),
773                     node.Name),
774                 configData);
775         } // ReportNonTemplateIdAttributeError
776 
ReportTemplateCannotReferenceTemplateError( ConfigNode node, RemotingXmlConfigFileData configData)777         private static void ReportTemplateCannotReferenceTemplateError(
778             ConfigNode node,
779             RemotingXmlConfigFileData configData)
780         {
781             ReportError(
782                 String.Format(
783                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_TemplateCannotReferenceTemplate"),
784                     node.Name),
785                 configData);
786         } // ReportTemplateCannotReferenceTemplateError
787 
ReportUnableToResolveTemplateReferenceError( ConfigNode node, String referenceName, RemotingXmlConfigFileData configData)788         private static void ReportUnableToResolveTemplateReferenceError(
789             ConfigNode node, String referenceName,
790             RemotingXmlConfigFileData configData)
791         {
792             ReportError(
793                 String.Format(
794                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_UnableToResolveTemplate"),
795                     node.Name, referenceName),
796                 configData);
797         } // ReportUnableToResolveTemplateReferenceError
798 
ReportAssemblyVersionInfoPresent( String assemName, String entryDescription, RemotingXmlConfigFileData configData)799         private static void ReportAssemblyVersionInfoPresent(
800             String assemName, String entryDescription,
801             RemotingXmlConfigFileData configData)
802         {
803             // for some entries, version information is not allowed in the assembly name
804             ReportError(
805                 String.Format(
806                     CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_VersionPresent"),
807                     assemName, entryDescription),
808                 configData);
809         } // ReportAssemblyVersionInfoPresent
810 
811 
ProcessDebugNode(ConfigNode node, RemotingXmlConfigFileData configData)812         private static void ProcessDebugNode(ConfigNode node, RemotingXmlConfigFileData configData)
813         {
814             foreach (DictionaryEntry entry in node.Attributes)
815             {
816                 String key = entry.Key.ToString();
817                 switch (key)
818                 {
819                 case "loadTypes":
820                     RemotingXmlConfigFileData.LoadTypes =
821                         Convert.ToBoolean((String)entry.Value, CultureInfo.InvariantCulture);
822                     break;
823 
824                 default: break;
825                 } // switch
826             } // foreach
827 
828         } // ProcessDebugNode
829 
830 
ProcessApplicationNode(ConfigNode node, RemotingXmlConfigFileData configData)831         private static void ProcessApplicationNode(ConfigNode node, RemotingXmlConfigFileData configData)
832         {
833             foreach (DictionaryEntry entry in node.Attributes)
834             {
835                 String key = entry.Key.ToString();
836                 if (key.Equals("name"))
837                     configData.ApplicationName = (String)entry.Value;
838             }
839 
840             foreach (ConfigNode childNode in node.Children)
841             {
842                 switch (childNode.Name)
843                 {
844                 case "channels": ProcessChannelsNode(childNode, configData); break;
845                 case "client": ProcessClientNode(childNode, configData); break;
846                 case "lifetime": ProcessLifetimeNode(node, childNode, configData); break;
847                 case "service": ProcessServiceNode(childNode, configData); break;
848                 case "soapInterop": ProcessSoapInteropNode(childNode, configData); break;
849 
850                 default: break;
851                 } // switch
852             } // foreach
853         } // ProcessApplicationNode
854 
ProcessCustomErrorsNode(ConfigNode node, RemotingXmlConfigFileData configData)855         private static void ProcessCustomErrorsNode(ConfigNode node, RemotingXmlConfigFileData configData) {
856             foreach (DictionaryEntry entry in node.Attributes)
857             {
858                 String key = entry.Key.ToString();
859                 if (key.Equals("mode")) {
860                     string value = (string)entry.Value;
861                     CustomErrorsModes mode = CustomErrorsModes.On;
862 
863                     if (String.Compare(value, "on", StringComparison.OrdinalIgnoreCase) == 0)
864                         mode = CustomErrorsModes.On;
865                     else if (String.Compare(value, "off", StringComparison.OrdinalIgnoreCase) == 0)
866                         mode = CustomErrorsModes.Off;
867                     else if (String.Compare(value, "remoteonly", StringComparison.OrdinalIgnoreCase) == 0)
868                         mode = CustomErrorsModes.RemoteOnly;
869                     else
870                         ReportUnknownValueError(node, value, configData);
871 
872                     configData.CustomErrors = new RemotingXmlConfigFileData.CustomErrorsEntry(mode);
873                 }
874             }
875 
876         }
877 
ProcessLifetimeNode(ConfigNode parentNode, ConfigNode node, RemotingXmlConfigFileData configData)878         private static void ProcessLifetimeNode(ConfigNode parentNode, ConfigNode node, RemotingXmlConfigFileData configData)
879         {
880             if (configData.Lifetime != null)
881                 ReportUniqueSectionError(node, parentNode, configData);
882 
883             configData.Lifetime = new RemotingXmlConfigFileData.LifetimeEntry();
884 
885             foreach (DictionaryEntry entry in node.Attributes)
886             {
887                 String key = entry.Key.ToString();
888                 switch (key)
889                 {
890 
891                 case "leaseTime":
892                     configData.Lifetime.LeaseTime = ParseTime((String)entry.Value, configData);
893                     break;
894 
895                 case "sponsorshipTimeout":
896                     configData.Lifetime.SponsorshipTimeout = ParseTime((String)entry.Value, configData);
897                     break;
898 
899                 case "renewOnCallTime":
900                     configData.Lifetime.RenewOnCallTime = ParseTime((String)entry.Value, configData);
901                     break;
902 
903                 case "leaseManagerPollTime":
904                     configData.Lifetime.LeaseManagerPollTime = ParseTime((String)entry.Value, configData);
905                     break;
906 
907                 default: break;
908 
909                 } // switch
910             } // foreach
911 
912         } // ProcessLifetimeNode
913 
914 
915         // appears under "application"
ProcessServiceNode(ConfigNode node, RemotingXmlConfigFileData configData)916         private static void ProcessServiceNode(ConfigNode node, RemotingXmlConfigFileData configData)
917         {
918             foreach (ConfigNode childNode in node.Children)
919             {
920                 switch (childNode.Name)
921                 {
922                 case "wellknown": ProcessServiceWellKnownNode(childNode, configData); break;
923                 case "activated": ProcessServiceActivatedNode(childNode, configData); break;
924 
925                 default: break;
926                 } // switch
927             } // foreach
928         } // ProcessServiceNode
929 
930 
931         // appears under "application"
ProcessClientNode(ConfigNode node, RemotingXmlConfigFileData configData)932         private static void ProcessClientNode(ConfigNode node, RemotingXmlConfigFileData configData)
933         {
934             String remoteAppUri = null;
935 
936             // process attributes
937             foreach (DictionaryEntry entry in node.Attributes)
938             {
939                 String key = entry.Key.ToString();
940                 switch (key)
941                 {
942                 case "url": remoteAppUri = (String)entry.Value; break;
943 
944                 case "displayName": break; // displayName is ignored (used by config utility for labelling the application)
945 
946                 default: break;
947                 } // switch
948             } // foreach attribute
949 
950             RemotingXmlConfigFileData.RemoteAppEntry remoteApp =
951                 configData.AddRemoteAppEntry(remoteAppUri);
952 
953             // process child nodes
954             foreach (ConfigNode childNode in node.Children)
955             {
956                 switch (childNode.Name)
957                 {
958                 case "wellknown": ProcessClientWellKnownNode(childNode, configData, remoteApp); break;
959                 case "activated": ProcessClientActivatedNode(childNode, configData, remoteApp); break;
960 
961                 default: break;
962                 } // switch
963             } // foreach child node
964 
965 
966             // if there are any activated entries, we require a remote app url.
967             if ((remoteApp.ActivatedObjects.Count > 0) && (remoteAppUri == null))
968                 ReportMissingAttributeError(node, "url", configData);
969         } // ProcessClientNode
970 
971 
972         // appears under "application"
ProcessSoapInteropNode(ConfigNode node, RemotingXmlConfigFileData configData)973         private static void ProcessSoapInteropNode(ConfigNode node, RemotingXmlConfigFileData configData)
974         {
975             // process attributes
976             foreach (DictionaryEntry entry in node.Attributes)
977             {
978                 String key = entry.Key.ToString();
979                 switch (key)
980                 {
981                 case "urlObjRef":
982                 {
983                     configData.UrlObjRefMode = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
984                     break;
985                 }
986 
987                 default: break;
988                 } // switch
989             } // foreach attribute
990 
991             foreach (ConfigNode childNode in node.Children)
992             {
993                 switch (childNode.Name)
994                 {
995                 case "preLoad": ProcessPreLoadNode(childNode, configData); break;
996                 case "interopXmlElement": ProcessInteropXmlElementNode(childNode, configData); break;
997                 case "interopXmlType": ProcessInteropXmlTypeNode(childNode, configData); break;
998 
999                 default: break;
1000                 } // switch
1001             }
1002         } // ProcessSoapInteropNode
1003 
1004 
1005         // appears under "application"
ProcessChannelsNode(ConfigNode node, RemotingXmlConfigFileData configData)1006         private static void ProcessChannelsNode(ConfigNode node, RemotingXmlConfigFileData configData)
1007         {
1008             foreach (ConfigNode childNode in node.Children)
1009             {
1010                 if (childNode.Name.Equals("channel"))
1011                 {
1012                     RemotingXmlConfigFileData.ChannelEntry channelEntry =
1013                         ProcessChannelsChannelNode(childNode, configData, false);
1014                     configData.ChannelEntries.Add(channelEntry);
1015                 }
1016             } // foreach
1017         } // ProcessInteropNode
1018 
1019 
1020         // appears under "application/service"
ProcessServiceWellKnownNode(ConfigNode node, RemotingXmlConfigFileData configData)1021         private static void ProcessServiceWellKnownNode(ConfigNode node, RemotingXmlConfigFileData configData)
1022         {
1023             String typeName = null;
1024             String assemName = null;
1025             ArrayList contextAttributes = new ArrayList();
1026 
1027             String objectURI = null;
1028 
1029             WellKnownObjectMode objectMode = WellKnownObjectMode.Singleton;
1030             bool objectModeFound = false;
1031 
1032             // examine attributes
1033             foreach (DictionaryEntry entry in node.Attributes)
1034             {
1035                 String key = entry.Key.ToString();
1036                 switch (key)
1037                 {
1038                 case "displayName": break; // displayName is ignored (used by config utility for labelling the application)
1039 
1040                 case "mode":
1041                 {
1042                     String value = (String)entry.Value;
1043                     objectModeFound = true;
1044                     if (String.CompareOrdinal(value, "Singleton") == 0)
1045                         objectMode = WellKnownObjectMode.Singleton;
1046                     else
1047                     if (String.CompareOrdinal(value, "SingleCall") == 0)
1048                         objectMode = WellKnownObjectMode.SingleCall;
1049                     else
1050                         objectModeFound = false;
1051                     break;
1052                 } // case "mode"
1053 
1054                 case "objectUri": objectURI = (String)entry.Value; break;
1055 
1056                 case "type":
1057                 {
1058                     RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
1059                     break;
1060                 } // case "type"
1061 
1062 
1063                 default: break;
1064                 } // switch
1065             } // foreach
1066 
1067             // examine child nodes
1068             foreach (ConfigNode childNode in node.Children)
1069             {
1070                 switch (childNode.Name)
1071                 {
1072                 case "contextAttribute":
1073                 {
1074                     contextAttributes.Add(ProcessContextAttributeNode(childNode, configData));
1075                     break;
1076                 } // case "contextAttribute"
1077 
1078                 case "lifetime":
1079                 {
1080                     // <
1081                      break;
1082                 } // case "lifetime"
1083 
1084 
1085                 default: break;
1086 
1087                 } // switch
1088             } // foreach child node
1089 
1090 
1091             // check for errors
1092             if (!objectModeFound)
1093             {
1094                 ReportError(
1095                     Environment.GetResourceString("Remoting_Config_MissingWellKnownModeAttribute"),
1096                     configData);
1097             }
1098 
1099             if ((typeName == null) || (assemName == null))
1100                 ReportMissingTypeAttributeError(node, "type", configData);
1101 
1102 
1103             // objectURI defaults to typeName if not specified
1104             if (objectURI == null)
1105                 objectURI = typeName + ".soap";
1106 
1107             configData.AddServerWellKnownEntry(typeName, assemName, contextAttributes,
1108                 objectURI, objectMode);
1109         } // ProcessServiceWellKnownNode
1110 
1111 
1112         // appears under "application/service"
ProcessServiceActivatedNode(ConfigNode node, RemotingXmlConfigFileData configData)1113         private static void ProcessServiceActivatedNode(ConfigNode node, RemotingXmlConfigFileData configData)
1114         {
1115             String typeName = null;
1116             String assemName = null;
1117             ArrayList contextAttributes = new ArrayList();
1118 
1119             foreach (DictionaryEntry entry in node.Attributes)
1120             {
1121                 String key = entry.Key.ToString();
1122                 switch (key)
1123                 {
1124                 case "type":
1125                 {
1126                     RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
1127                     break;
1128                 } // case "type"
1129 
1130                 default: break;
1131                 } // switch
1132             } // foreach attribute
1133 
1134 
1135             foreach (ConfigNode childNode in node.Children)
1136             {
1137                 switch (childNode.Name)
1138                 {
1139                 case "contextAttribute":
1140                 {
1141                     contextAttributes.Add(ProcessContextAttributeNode(childNode, configData));
1142                     break;
1143                 } // case "contextattribute"
1144 
1145                 case "lifetime":
1146                 {
1147                     // <
1148                     break;
1149                 } // case "lifetime"
1150 
1151                 default: break;
1152 
1153                 } // switch
1154             } // foreach child node
1155 
1156             // check for errors
1157             if ((typeName == null) || (assemName == null))
1158                 ReportMissingTypeAttributeError(node, "type", configData);
1159 
1160             if (CheckAssemblyNameForVersionInfo(assemName))
1161                 ReportAssemblyVersionInfoPresent(assemName, "service activated", configData);
1162 
1163             configData.AddServerActivatedEntry(typeName, assemName, contextAttributes);
1164         } // ProcessServiceActivatedNode
1165 
1166 
1167         // appears under "application/client"
ProcessClientWellKnownNode(ConfigNode node, RemotingXmlConfigFileData configData, RemotingXmlConfigFileData.RemoteAppEntry remoteApp)1168         private static void ProcessClientWellKnownNode(ConfigNode node, RemotingXmlConfigFileData configData,
1169             RemotingXmlConfigFileData.RemoteAppEntry remoteApp)
1170         {
1171             String typeName = null;
1172             String assemName = null;
1173             String url = null;
1174 
1175             foreach (DictionaryEntry entry in node.Attributes)
1176             {
1177                 String key = entry.Key.ToString();
1178                 switch (key)
1179                 {
1180                 case "displayName": break; // displayName is ignored (used by config utility for labelling the application)
1181 
1182                 case "type":
1183                 {
1184                     RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
1185                     break;
1186                 } // case "type"
1187 
1188                 case "url": url = (String)entry.Value; break;
1189 
1190                 default: break;
1191                 } // switch
1192             } // foreach
1193 
1194             // check for errors
1195             if (url == null)
1196                 ReportMissingAttributeError("WellKnown client", "url", configData);
1197 
1198             if ((typeName == null) || (assemName == null))
1199                 ReportMissingTypeAttributeError(node, "type", configData);
1200 
1201             if (CheckAssemblyNameForVersionInfo(assemName))
1202                 ReportAssemblyVersionInfoPresent(assemName, "client wellknown", configData);
1203 
1204             remoteApp.AddWellKnownEntry(typeName, assemName, url);
1205         } // ProcessClientWellKnownNode
1206 
1207 
1208         // appears under "application/client"
ProcessClientActivatedNode(ConfigNode node, RemotingXmlConfigFileData configData, RemotingXmlConfigFileData.RemoteAppEntry remoteApp)1209         private static void ProcessClientActivatedNode(ConfigNode node, RemotingXmlConfigFileData configData,
1210             RemotingXmlConfigFileData.RemoteAppEntry remoteApp)
1211         {
1212             String typeName = null;
1213             String assemName = null;
1214             ArrayList contextAttributes = new ArrayList();
1215 
1216             foreach (DictionaryEntry entry in node.Attributes)
1217             {
1218                 String key = entry.Key.ToString();
1219                 switch (key)
1220                 {
1221                 case "type":
1222                 {
1223                     RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
1224                     break;
1225                 } // case "type"
1226 
1227                 default: break;
1228                 } // switch
1229             } // foreach
1230 
1231             foreach (ConfigNode childNode in node.Children)
1232             {
1233                 switch (childNode.Name)
1234                 {
1235                 case "contextAttribute":
1236                 {
1237                     contextAttributes.Add(ProcessContextAttributeNode(childNode, configData));
1238                     break;
1239                 } // case "contextAttribute"
1240 
1241                 default: break;
1242                 } // switch
1243             } // foreach child node
1244 
1245             // check for errors
1246             if ((typeName == null) || (assemName == null))
1247                 ReportMissingTypeAttributeError(node, "type", configData);
1248 
1249             remoteApp.AddActivatedEntry(typeName, assemName, contextAttributes);
1250         } // ProcessClientActivatedNode
1251 
1252 
ProcessInteropXmlElementNode(ConfigNode node, RemotingXmlConfigFileData configData)1253         private static void ProcessInteropXmlElementNode(ConfigNode node, RemotingXmlConfigFileData configData)
1254         {
1255             String xmlElementName = null;
1256             String xmlElementNamespace = null;
1257             String urtTypeName = null;
1258             String urtAssemName = null;
1259 
1260             foreach (DictionaryEntry entry in node.Attributes)
1261             {
1262                 String key = entry.Key.ToString();
1263                 switch (key)
1264                 {
1265                 case "xml":
1266                 {
1267                     RemotingConfigHandler.ParseType((String)entry.Value, out xmlElementName, out xmlElementNamespace);
1268                     break;
1269                 }
1270 
1271                 case "clr":
1272                 {
1273                     RemotingConfigHandler.ParseType((String)entry.Value, out urtTypeName, out urtAssemName);
1274                     break;
1275                 } // case "clr"
1276 
1277                 default: break;
1278                 } // switch
1279             } // foreach
1280 
1281             // check for errors
1282             if ((xmlElementName == null) || (xmlElementNamespace == null))
1283                 ReportMissingXmlTypeAttributeError(node, "xml", configData);
1284 
1285             if ((urtTypeName == null) || (urtAssemName == null))
1286                 ReportMissingTypeAttributeError(node, "clr", configData);
1287 
1288             configData.AddInteropXmlElementEntry(xmlElementName, xmlElementNamespace,
1289                                                  urtTypeName, urtAssemName);
1290         } // ProcessInteropNode
1291 
1292 
ProcessInteropXmlTypeNode(ConfigNode node, RemotingXmlConfigFileData configData)1293         private static void ProcessInteropXmlTypeNode(ConfigNode node, RemotingXmlConfigFileData configData)
1294         {
1295             String xmlTypeName = null;
1296             String xmlTypeNamespace = null;
1297             String urtTypeName = null;
1298             String urtAssemName = null;
1299 
1300             foreach (DictionaryEntry entry in node.Attributes)
1301             {
1302                 String key = entry.Key.ToString();
1303                 switch (key)
1304                 {
1305                 case "xml":
1306                 {
1307                     RemotingConfigHandler.ParseType((String)entry.Value, out xmlTypeName, out xmlTypeNamespace);
1308                     break;
1309                 }
1310 
1311                 case "clr":
1312                 {
1313                     RemotingConfigHandler.ParseType((String)entry.Value, out urtTypeName, out urtAssemName);
1314                     break;
1315                 } // case "type"
1316 
1317                 default: break;
1318                 } // switch
1319             } // foreach
1320 
1321             // check for errors
1322             if ((xmlTypeName == null) || (xmlTypeNamespace == null))
1323                 ReportMissingXmlTypeAttributeError(node, "xml", configData);
1324 
1325             if ((urtTypeName == null) || (urtAssemName == null))
1326                 ReportMissingTypeAttributeError(node, "clr", configData);
1327 
1328             configData.AddInteropXmlTypeEntry(xmlTypeName, xmlTypeNamespace,
1329                                               urtTypeName, urtAssemName);
1330         } // ProcessInteropNode
1331 
1332 
ProcessPreLoadNode(ConfigNode node, RemotingXmlConfigFileData configData)1333         private static void ProcessPreLoadNode(ConfigNode node, RemotingXmlConfigFileData configData)
1334         {
1335             String typeName = null;
1336             String assemblyName = null;
1337 
1338             foreach (DictionaryEntry entry in node.Attributes)
1339             {
1340                 String key = entry.Key.ToString();
1341                 switch (key)
1342                 {
1343                 case "type":
1344                 {
1345                     RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemblyName);
1346                     break;
1347                 }
1348 
1349                 case "assembly":
1350                 {
1351                     assemblyName = (String)entry.Value;
1352                     break;
1353                 } // case "type"
1354 
1355                 default: break;
1356                 } // switch
1357             } // foreach
1358 
1359             // check for errors
1360             if (assemblyName == null)
1361             {
1362                 ReportError(
1363                     Environment.GetResourceString("Remoting_Config_PreloadRequiresTypeOrAssembly"),
1364                     configData);
1365             }
1366 
1367             configData.AddPreLoadEntry(typeName, assemblyName);
1368         } // ProcessPreLoadNode
1369 
1370 
1371 
1372         private static RemotingXmlConfigFileData.ContextAttributeEntry
ProcessContextAttributeNode(ConfigNode node, RemotingXmlConfigFileData configData)1373         ProcessContextAttributeNode(ConfigNode node, RemotingXmlConfigFileData configData)
1374         {
1375             String typeName = null;
1376             String assemName = null;
1377             Hashtable properties = CreateCaseInsensitiveHashtable();
1378 
1379             // examine attributes
1380             foreach (DictionaryEntry entry in node.Attributes)
1381             {
1382                 String lowercaseKey = ((String)entry.Key).ToLower(CultureInfo.InvariantCulture);
1383                 switch (lowercaseKey)
1384                 {
1385 
1386                 case "type":
1387                 {
1388                     RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
1389                     break;
1390                 } // case "type"
1391 
1392                 default:
1393                     properties[lowercaseKey] = entry.Value;
1394                     break;
1395                 } // switch
1396             } // foreach attribute
1397 
1398             // check for errors
1399             if ((typeName == null) || (assemName == null))
1400                  ReportMissingTypeAttributeError(node, "type", configData);
1401 
1402             RemotingXmlConfigFileData.ContextAttributeEntry attributeEntry =
1403                 new RemotingXmlConfigFileData.ContextAttributeEntry(
1404                     typeName, assemName, properties);
1405 
1406             return attributeEntry;
1407         } // ProcessContextAttributeNode
1408 
1409 
1410         // appears under "application/client"
1411         private static RemotingXmlConfigFileData.ChannelEntry
ProcessChannelsChannelNode(ConfigNode node, RemotingXmlConfigFileData configData, bool isTemplate)1412         ProcessChannelsChannelNode(ConfigNode node, RemotingXmlConfigFileData configData,
1413                                    bool isTemplate)
1414         {
1415             String id = null;
1416             String typeName = null;
1417             String assemName = null;
1418             Hashtable properties = CreateCaseInsensitiveHashtable();
1419 
1420             bool delayLoad = false;
1421 
1422             RemotingXmlConfigFileData.ChannelEntry channelTemplate = null;
1423 
1424             // examine attributes
1425             foreach (DictionaryEntry entry in node.Attributes)
1426             {
1427                 String keyStr = (String)entry.Key;
1428                 switch (keyStr)
1429                 {
1430                 case "displayName": break; // displayName is ignored (used by config utility for labelling the application)
1431 
1432                 case "id":
1433                 {
1434                     if (!isTemplate)
1435                     {
1436                         ReportNonTemplateIdAttributeError(node, configData);
1437                     }
1438                     else
1439                         id = ((String)entry.Value).ToLower(CultureInfo.InvariantCulture);
1440 
1441                     break;
1442                 } // case "id"
1443 
1444                 case "ref":
1445                 {
1446                     if (isTemplate)
1447                     {
1448                         ReportTemplateCannotReferenceTemplateError(node, configData);
1449                     }
1450                     else
1451                     {
1452                         channelTemplate =
1453                             (RemotingXmlConfigFileData.ChannelEntry)_channelTemplates[entry.Value];
1454                         if (channelTemplate == null)
1455                         {
1456                             ReportUnableToResolveTemplateReferenceError(
1457                                 node, entry.Value.ToString(), configData);
1458                         }
1459                         else
1460                         {
1461                             // load template data
1462                             typeName = channelTemplate.TypeName;
1463                             assemName = channelTemplate.AssemblyName;
1464 
1465                             foreach (DictionaryEntry param in channelTemplate.Properties)
1466                             {
1467                                 properties[param.Key] = param.Value;
1468                             }
1469                         }
1470                     }
1471 
1472                     break;
1473                 } // case "ref"
1474 
1475                 case "type":
1476                 {
1477                     RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
1478                     break;
1479                 } // case "type"
1480 
1481                 case "delayLoadAsClientChannel":
1482                 {
1483                     delayLoad = Convert.ToBoolean((String)entry.Value, CultureInfo.InvariantCulture);
1484                     break;
1485                 } // case "delayLoadAsClientChannel"
1486 
1487                 default:
1488                     properties[keyStr] = entry.Value;
1489                     break;
1490                 } // switch
1491             } // foreach attribute
1492 
1493             // check for errors
1494             if ((typeName == null) || (assemName == null))
1495                 ReportMissingTypeAttributeError(node, "type", configData);
1496 
1497             RemotingXmlConfigFileData.ChannelEntry channelEntry =
1498                 new RemotingXmlConfigFileData.ChannelEntry(typeName, assemName, properties);
1499 
1500             channelEntry.DelayLoad = delayLoad;
1501 
1502 
1503             // look for sink providers
1504             foreach (ConfigNode childNode in node.Children)
1505             {
1506                 switch (childNode.Name)
1507                 {
1508                 case "clientProviders":
1509                     ProcessSinkProviderNodes(childNode, channelEntry, configData, false);
1510                     break;
1511                 case "serverProviders":
1512                     ProcessSinkProviderNodes(childNode, channelEntry, configData, true);
1513                     break;
1514 
1515                  default: break;
1516                 } // switch
1517             } // foreach
1518 
1519             // if we reference a template and didn't specify any sink providers, we
1520             //   should copy over the providers from the template
1521             if (channelTemplate != null)
1522             {
1523                 // <
1524 
1525                 if (channelEntry.ClientSinkProviders.Count == 0)
1526                 {
1527                     channelEntry.ClientSinkProviders = channelTemplate.ClientSinkProviders;
1528                 }
1529                 if (channelEntry.ServerSinkProviders.Count == 0)
1530                 {
1531                     channelEntry.ServerSinkProviders = channelTemplate.ServerSinkProviders;
1532                 }
1533             }
1534 
1535 
1536             if (isTemplate)
1537             {
1538                 _channelTemplates[id] = channelEntry;
1539                 return null;
1540             }
1541             else
1542             {
1543                 return channelEntry;
1544             }
1545         } // ProcessChannelsChannelNode
1546 
1547 
1548 
1549 
1550 
1551         //
1552         // process sink provider data
1553         //
1554 
ProcessSinkProviderNodes(ConfigNode node, RemotingXmlConfigFileData.ChannelEntry channelEntry, RemotingXmlConfigFileData configData, bool isServer)1555         private static void ProcessSinkProviderNodes(ConfigNode node,
1556             RemotingXmlConfigFileData.ChannelEntry channelEntry, RemotingXmlConfigFileData configData,
1557             bool isServer)
1558         {
1559             // look for sink providers
1560             foreach (ConfigNode childNode in node.Children)
1561             {
1562                 RemotingXmlConfigFileData.SinkProviderEntry entry =
1563                     ProcessSinkProviderNode(childNode, configData, false, isServer);
1564                 if (isServer)
1565                     channelEntry.ServerSinkProviders.Add(entry);
1566                 else
1567                     channelEntry.ClientSinkProviders.Add(entry);
1568             } // foreach
1569 
1570         } // ProcessSinkProviderNodes
1571 
1572 
1573         private static RemotingXmlConfigFileData.SinkProviderEntry
ProcessSinkProviderNode(ConfigNode node, RemotingXmlConfigFileData configData, bool isTemplate, bool isServer)1574         ProcessSinkProviderNode(ConfigNode node, RemotingXmlConfigFileData configData,
1575                                 bool isTemplate, bool isServer)
1576         {
1577             bool isFormatter = false;
1578 
1579             // Make sure the node is a "formatter" or "provider".
1580             String nodeName = node.Name;
1581             if (nodeName.Equals("formatter"))
1582                 isFormatter = true;
1583             else
1584             if (nodeName.Equals("provider"))
1585                 isFormatter = false;
1586             else
1587             {
1588                 ReportError(
1589                     Environment.GetResourceString("Remoting_Config_ProviderNeedsElementName"),
1590                     configData);
1591             }
1592 
1593             String id = null;
1594             String typeName = null;
1595             String assemName = null;
1596             Hashtable properties = CreateCaseInsensitiveHashtable();
1597 
1598             RemotingXmlConfigFileData.SinkProviderEntry template = null;
1599 
1600 
1601             foreach (DictionaryEntry entry in node.Attributes)
1602             {
1603                 String keyStr = (String)entry.Key;
1604                 switch (keyStr)
1605                 {
1606                 case "id":
1607                 {
1608                     if (!isTemplate)
1609                     {
1610                         // only templates can have the id attribute
1611                         ReportNonTemplateIdAttributeError(node, configData);
1612                     }
1613                     else
1614                         id = (String)entry.Value;
1615 
1616                     break;
1617                 } // case "id"
1618 
1619                 case "ref":
1620                 {
1621                     if (isTemplate)
1622                     {
1623                         ReportTemplateCannotReferenceTemplateError(node, configData);
1624                     }
1625                     else
1626                     {
1627                         if (isServer)
1628                         {
1629                             template = (RemotingXmlConfigFileData.SinkProviderEntry)
1630                                 _serverChannelSinkTemplates[entry.Value];
1631                         }
1632                         else
1633                         {
1634                             template = (RemotingXmlConfigFileData.SinkProviderEntry)
1635                                 _clientChannelSinkTemplates[entry.Value];
1636                         }
1637 
1638                         if (template == null)
1639                         {
1640                             ReportUnableToResolveTemplateReferenceError(
1641                                 node, entry.Value.ToString(), configData);
1642                         }
1643                         else
1644                         {
1645                             // load template data
1646                             typeName = template.TypeName;
1647                             assemName = template.AssemblyName;
1648 
1649                             foreach (DictionaryEntry param in template.Properties)
1650                             {
1651                                 properties[param.Key] = param.Value;
1652                             }
1653                         }
1654                     }
1655 
1656                     break;
1657                 } // case "ref"
1658 
1659                 case "type":
1660                 {
1661                     RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
1662                     break;
1663                 } // case "type"
1664 
1665                 default:
1666                     properties[keyStr] = entry.Value;
1667                     break;
1668                 } // switch
1669             } // foreach attribute
1670 
1671             // check for errors
1672             if ((typeName == null) || (assemName == null))
1673                 ReportMissingTypeAttributeError(node, "type", configData);
1674 
1675             RemotingXmlConfigFileData.SinkProviderEntry sinkProviderEntry =
1676                 new RemotingXmlConfigFileData.SinkProviderEntry(typeName, assemName, properties,
1677                                                                 isFormatter);
1678 
1679             // start storing sink data
1680             foreach (ConfigNode childNode in node.Children)
1681             {
1682                 SinkProviderData providerData =
1683                     ProcessSinkProviderData(childNode, configData);
1684                 sinkProviderEntry.ProviderData.Add(providerData);
1685             } // foreach
1686 
1687 
1688             // if we reference a template and didn't specify any provider data, we
1689             //   should copy over the provider data from the template
1690             if (template != null)
1691             {
1692                 // <
1693 
1694                 if (sinkProviderEntry.ProviderData.Count == 0)
1695                 {
1696                     sinkProviderEntry.ProviderData = template.ProviderData;
1697                 }
1698             }
1699 
1700 
1701             if (isTemplate)
1702             {
1703                 if (isServer)
1704                     _serverChannelSinkTemplates[id] = sinkProviderEntry;
1705                 else
1706                     _clientChannelSinkTemplates[id] = sinkProviderEntry;
1707                 return null;
1708             }
1709             else
1710             {
1711                 return sinkProviderEntry;
1712             }
1713         } // ProcessSinkProviderNode
1714 
1715 
1716         // providerData will already contain an object with the same name as the config node
ProcessSinkProviderData(ConfigNode node, RemotingXmlConfigFileData configData)1717         private static SinkProviderData ProcessSinkProviderData(ConfigNode node,
1718             RemotingXmlConfigFileData configData)
1719         {
1720             SinkProviderData providerData = new SinkProviderData(node.Name);
1721 
1722             foreach (ConfigNode childNode in node.Children)
1723             {
1724                 SinkProviderData childData = ProcessSinkProviderData(childNode, configData);
1725                 providerData.Children.Add(childData);
1726             }
1727 
1728             foreach (DictionaryEntry entry in node.Attributes)
1729             {
1730                 providerData.Properties[entry.Key] = entry.Value;
1731             }
1732 
1733             return providerData;
1734         } // ProcessSinkProviderData
1735 
1736 
1737 
1738         //
1739         // process template nodes
1740         //
1741 
ProcessChannelTemplates(ConfigNode node, RemotingXmlConfigFileData configData)1742         private static void ProcessChannelTemplates(ConfigNode node, RemotingXmlConfigFileData configData)
1743         {
1744 
1745             foreach (ConfigNode childNode in node.Children)
1746             {
1747                 switch (childNode.Name)
1748                 {
1749                 case "channel": ProcessChannelsChannelNode(childNode, configData, true); break;
1750 
1751                 default: break;
1752                 } // switch
1753             }
1754         } // ProcessChannelTemplates
1755 
1756 
ProcessChannelSinkProviderTemplates(ConfigNode node, RemotingXmlConfigFileData configData)1757         private static void ProcessChannelSinkProviderTemplates(ConfigNode node, RemotingXmlConfigFileData configData)
1758         {
1759             foreach (ConfigNode childNode in node.Children)
1760             {
1761                 switch (childNode.Name)
1762                 {
1763                 case "clientProviders": ProcessChannelProviderTemplates(childNode, configData, false); break;
1764                 case "serverProviders": ProcessChannelProviderTemplates(childNode, configData, true); break;
1765 
1766                 default: break;
1767                 }
1768             }
1769         } // ProcessChannelSinkProviderTemplates
1770 
1771 
ProcessChannelProviderTemplates(ConfigNode node, RemotingXmlConfigFileData configData, bool isServer)1772         private static void ProcessChannelProviderTemplates(ConfigNode node, RemotingXmlConfigFileData configData,
1773                                                             bool isServer)
1774         {
1775             foreach (ConfigNode childNode in node.Children)
1776             {
1777                 ProcessSinkProviderNode(childNode, configData, true, isServer);
1778             }
1779         } // ProcessClientProviderTemplates
1780 
1781 
1782         // assembly names aren't supposed to have version information in some places
1783         //   so we use this method to make sure that only an assembly name is
1784         //   specified.
CheckAssemblyNameForVersionInfo(String assemName)1785         private static bool CheckAssemblyNameForVersionInfo(String assemName)
1786         {
1787             if (assemName == null)
1788                 return false;
1789 
1790             // if the assembly name has a comma, we know that version information is present
1791             int index = assemName.IndexOf(',');
1792             return (index != -1);
1793         } // CheckAssemblyNameForVersionInfo
1794 
1795 
ParseTime(String time, RemotingXmlConfigFileData configData)1796         private static TimeSpan ParseTime(String time, RemotingXmlConfigFileData configData)
1797         {
1798             // time formats, e.g.
1799             //   10D -> 10 days
1800             //   10H -> 10 hours
1801             //   10M -> 10 minutes
1802             //   10S -> 10 seconds
1803             //   10MS -> 10 milliseconds
1804             //   10 -> default is seconds: 10 seconds
1805 
1806             String specifiedTime = time;
1807 
1808             String metric = "s"; // default is seconds
1809             int metricLength = 0;
1810 
1811             char lastChar = ' ';
1812             if (time.Length > 0)
1813                 lastChar = time[time.Length - 1];
1814 
1815             TimeSpan span = TimeSpan.FromSeconds(0);
1816 
1817             try
1818             {
1819                 if (!Char.IsDigit(lastChar))
1820                 {
1821                     if (time.Length == 0)
1822                         ReportInvalidTimeFormatError(specifiedTime, configData);
1823 
1824                     time = time.ToLower(CultureInfo.InvariantCulture);
1825 
1826                     metricLength = 1;
1827                     if (time.EndsWith("ms", StringComparison.Ordinal))
1828                         metricLength = 2;
1829                     metric = time.Substring(time.Length - metricLength, metricLength);
1830                 }
1831 
1832                 int value = Int32.Parse(time.Substring(0, time.Length - metricLength), CultureInfo.InvariantCulture);
1833 
1834                 switch (metric)
1835                 {
1836                     case "d": span = TimeSpan.FromDays(value); break;
1837                     case "h": span = TimeSpan.FromHours(value); break;
1838                     case "m": span = TimeSpan.FromMinutes(value); break;
1839                     case "s": span = TimeSpan.FromSeconds(value); break;
1840                     case "ms": span = TimeSpan.FromMilliseconds(value); break;
1841 
1842                     default:
1843                     {
1844                         ReportInvalidTimeFormatError(specifiedTime, configData);
1845                         break;
1846                     }
1847                 } // switch
1848 
1849             }
1850             catch (Exception)
1851             {
1852                 ReportInvalidTimeFormatError(specifiedTime, configData);
1853             }
1854 
1855             return span;
1856         } // ParseTime
1857 
1858     } // class RemotingXmlConfigFileParser
1859 
1860 
1861 
1862 } // namespace
1863