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