**** Merged from MCS ****
[mono-project.git] / mcs / class / corlib / System.Runtime.Remoting / RemotingConfiguration.cs
blob2cbe62dff510798b71531f5886ed449ad343dcbe
1 //
2 // System.Runtime.Remoting.RemotingConfiguration.cs
3 //
4 // Author: Jaime Anguiano Olarra (jaime@gnome.org)
5 // Lluis Sanchez Gual (lluis@ideary.com)
6 //
7 // (C) 2002, Jaime Anguiano Olarra
8 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System;
34 using System.IO;
35 using System.Reflection;
36 using System.Collections;
37 using System.Runtime.Remoting.Activation;
38 using System.Runtime.Remoting.Channels;
39 using System.Runtime.Remoting.Lifetime;
40 using Mono.Xml;
42 namespace System.Runtime.Remoting
44 public class RemotingConfiguration
47 // Private constructor: nobody instantiates this.
49 private RemotingConfiguration ()
53 static string applicationID = null;
54 static string applicationName = null;
55 static string configFile = "";
56 static MiniParser parser = null;
57 static string processGuid = null;
58 static bool defaultConfigRead = false;
59 static bool defaultDelayedConfigRead = false;
60 static string _errorMode;
62 static Hashtable wellKnownClientEntries = new Hashtable();
63 static Hashtable activatedClientEntries = new Hashtable();
64 static Hashtable wellKnownServiceEntries = new Hashtable();
65 static Hashtable activatedServiceEntries = new Hashtable();
67 static Hashtable channelTemplates = new Hashtable ();
68 static Hashtable clientProviderTemplates = new Hashtable ();
69 static Hashtable serverProviderTemplates = new Hashtable ();
71 // public properties
72 // At this time the ID will be the application name
73 public static string ApplicationId
75 get
77 applicationID = AppDomain.CurrentDomain.SetupInformation.ApplicationName;
78 return applicationID;
82 public static string ApplicationName
84 get {
85 try {
86 applicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName;
88 catch (Exception e) {
89 throw e;
91 // We return null if the application name has not been set.
92 return null;
94 set { applicationName = value; }
97 public static string ProcessId
99 get {
100 if (processGuid == null)
101 processGuid = AppDomain.GetProcessGuid ();
103 return processGuid;
108 // public methods
110 public static void Configure (string filename)
112 lock (channelTemplates)
114 if (!defaultConfigRead)
116 ReadConfigFile (Environment.GetMachineConfigPath ());
117 defaultConfigRead = true;
120 if (filename != null)
121 ReadConfigFile (filename);
125 private static void ReadConfigFile (string filename)
129 MiniParser parser = new MiniParser ();
130 RReader rreader = new RReader (filename);
131 ConfigHandler handler = new ConfigHandler (false);
132 parser.Parse (rreader, handler);
134 catch (Exception ex)
136 throw new RemotingException ("Configuration file '" + filename + "' could not be loaded: " + ex.Message);
140 internal static void LoadDefaultDelayedChannels ()
142 lock (channelTemplates)
144 if (defaultDelayedConfigRead || defaultConfigRead) return;
146 MiniParser parser = new MiniParser ();
147 RReader rreader = new RReader (Environment.GetMachineConfigPath ());
148 ConfigHandler handler = new ConfigHandler (true);
149 parser.Parse (rreader, handler);
150 defaultDelayedConfigRead = true;
154 public static ActivatedClientTypeEntry[] GetRegisteredActivatedClientTypes ()
156 lock (channelTemplates)
158 ActivatedClientTypeEntry[] entries = new ActivatedClientTypeEntry[activatedClientEntries.Count];
159 activatedClientEntries.Values.CopyTo (entries,0);
160 return entries;
164 public static ActivatedServiceTypeEntry[] GetRegisteredActivatedServiceTypes ()
166 lock (channelTemplates)
168 ActivatedServiceTypeEntry[] entries = new ActivatedServiceTypeEntry[activatedServiceEntries.Count];
169 activatedServiceEntries.Values.CopyTo (entries,0);
170 return entries;
174 public static WellKnownClientTypeEntry[] GetRegisteredWellKnownClientTypes ()
176 lock (channelTemplates)
178 WellKnownClientTypeEntry[] entries = new WellKnownClientTypeEntry[wellKnownClientEntries.Count];
179 wellKnownClientEntries.Values.CopyTo (entries,0);
180 return entries;
184 public static WellKnownServiceTypeEntry[] GetRegisteredWellKnownServiceTypes ()
186 lock (channelTemplates)
188 WellKnownServiceTypeEntry[] entries = new WellKnownServiceTypeEntry[wellKnownServiceEntries.Count];
189 wellKnownServiceEntries.Values.CopyTo (entries,0);
190 return entries;
194 public static bool IsActivationAllowed (Type serverType)
196 lock (channelTemplates)
198 return activatedServiceEntries.ContainsKey (serverType);
202 public static ActivatedClientTypeEntry IsRemotelyActivatedClientType (Type serviceType)
204 lock (channelTemplates)
206 return activatedClientEntries [serviceType] as ActivatedClientTypeEntry;
210 public static ActivatedClientTypeEntry IsRemotelyActivatedClientType (string typeName, string assemblyName)
212 return IsRemotelyActivatedClientType (Assembly.Load(assemblyName).GetType (typeName));
215 public static WellKnownClientTypeEntry IsWellKnownClientType (Type serviceType)
217 lock (channelTemplates)
219 return wellKnownClientEntries [serviceType] as WellKnownClientTypeEntry;
223 public static WellKnownClientTypeEntry IsWellKnownClientType (string typeName, string assemblyName)
225 return IsWellKnownClientType (Assembly.Load(assemblyName).GetType (typeName));
228 public static void RegisterActivatedClientType (ActivatedClientTypeEntry entry)
230 lock (channelTemplates)
232 if (wellKnownClientEntries.ContainsKey (entry.ObjectType) || activatedClientEntries.ContainsKey (entry.ObjectType))
233 throw new RemotingException ("Attempt to redirect activation of type '" + entry.ObjectType.FullName + "' which is already redirected.");
235 activatedClientEntries[entry.ObjectType] = entry;
236 ActivationServices.EnableProxyActivation (entry.ObjectType, true);
240 public static void RegisterActivatedClientType (Type type, string appUrl)
242 if (type == null) throw new ArgumentNullException ("type");
243 if (appUrl == null) throw new ArgumentNullException ("appUrl");
245 RegisterActivatedClientType (new ActivatedClientTypeEntry (type, appUrl));
248 public static void RegisterActivatedServiceType (ActivatedServiceTypeEntry entry)
250 lock (channelTemplates)
252 activatedServiceEntries.Add (entry.ObjectType, entry);
256 public static void RegisterActivatedServiceType (Type type)
258 RegisterActivatedServiceType (new ActivatedServiceTypeEntry (type));
261 public static void RegisterWellKnownClientType (Type type, string objectUrl)
263 if (type == null) throw new ArgumentNullException ("type");
264 if (objectUrl == null) throw new ArgumentNullException ("objectUrl");
266 RegisterWellKnownClientType (new WellKnownClientTypeEntry (type, objectUrl));
269 public static void RegisterWellKnownClientType (WellKnownClientTypeEntry entry)
271 lock (channelTemplates)
273 if (wellKnownClientEntries.ContainsKey (entry.ObjectType) || activatedClientEntries.ContainsKey (entry.ObjectType))
274 throw new RemotingException ("Attempt to redirect activation of type '" + entry.ObjectType.FullName + "' which is already redirected.");
276 wellKnownClientEntries[entry.ObjectType] = entry;
277 ActivationServices.EnableProxyActivation (entry.ObjectType, true);
281 public static void RegisterWellKnownServiceType (Type type, string objectUrl, WellKnownObjectMode mode)
283 RegisterWellKnownServiceType (new WellKnownServiceTypeEntry (type, objectUrl, mode));
286 public static void RegisterWellKnownServiceType (WellKnownServiceTypeEntry entry)
288 lock (channelTemplates)
290 wellKnownServiceEntries [entry.ObjectUri] = entry;
291 RemotingServices.CreateWellKnownServerIdentity (entry.ObjectType, entry.ObjectUri, entry.Mode);
295 internal static void RegisterChannelTemplate (ChannelData channel)
297 channelTemplates [channel.Id] = channel;
300 internal static void RegisterClientProviderTemplate (ProviderData prov)
302 clientProviderTemplates [prov.Id] = prov;
305 internal static void RegisterServerProviderTemplate (ProviderData prov)
307 serverProviderTemplates [prov.Id] = prov;
310 internal static void RegisterChannels (ArrayList channels, bool onlyDelayed)
312 foreach (ChannelData channel in channels)
314 if (onlyDelayed && channel.DelayLoadAsClientChannel != "true")
315 continue;
317 if (defaultDelayedConfigRead && channel.DelayLoadAsClientChannel == "true")
318 continue;
320 if (channel.Ref != null)
322 ChannelData template = (ChannelData) channelTemplates [channel.Ref];
323 if (template == null) throw new RemotingException ("Channel template '" + channel.Ref + "' not found");
324 channel.CopyFrom (template);
327 foreach (ProviderData prov in channel.ServerProviders)
329 if (prov.Ref != null)
331 ProviderData template = (ProviderData) serverProviderTemplates [prov.Ref];
332 if (template == null) throw new RemotingException ("Provider template '" + prov.Ref + "' not found");
333 prov.CopyFrom (template);
337 foreach (ProviderData prov in channel.ClientProviders)
339 if (prov.Ref != null)
341 ProviderData template = (ProviderData) clientProviderTemplates [prov.Ref];
342 if (template == null) throw new RemotingException ("Provider template '" + prov.Ref + "' not found");
343 prov.CopyFrom (template);
347 ChannelServices.RegisterChannelConfig (channel);
351 internal static void RegisterTypes (ArrayList types)
353 foreach (TypeEntry type in types)
355 if (type is ActivatedClientTypeEntry)
356 RegisterActivatedClientType ((ActivatedClientTypeEntry)type);
357 else if (type is ActivatedServiceTypeEntry)
358 RegisterActivatedServiceType ((ActivatedServiceTypeEntry)type);
359 else if (type is WellKnownClientTypeEntry)
360 RegisterWellKnownClientType ((WellKnownClientTypeEntry)type);
361 else if (type is WellKnownServiceTypeEntry)
362 RegisterWellKnownServiceType ((WellKnownServiceTypeEntry)type);
366 #if NET_1_1
367 public static bool CustomErrorsEnabled (bool isLocalRequest)
369 if (_errorMode == "off") return false;
370 if (_errorMode == "on") return true;
371 return !isLocalRequest;
373 #endif
375 internal static void SetCustomErrorsMode (string mode)
377 if (mode != "on" && mode != "off" && mode != "remoteOnly")
378 throw new RemotingException ("Invalid custom error mode: " + mode);
380 _errorMode = mode;
384 /***************************************************************
385 * Internal classes used by RemotingConfiguration.Configure () *
386 ***************************************************************/
388 internal class RReader : MiniParser.IReader {
389 private string xml; // custom remoting config file
390 private int pos;
392 public RReader (string filename)
394 try {
395 StreamReader sr = new StreamReader (filename);
396 xml = sr.ReadToEnd ();
397 sr.Close ();
399 catch {
400 xml = null;
404 public int Read () {
405 try {
406 return (int) xml[pos++];
408 catch {
409 return -1;
414 internal class ConfigHandler : MiniParser.IHandler
416 ArrayList typeEntries = new ArrayList ();
417 ArrayList channelInstances = new ArrayList ();
419 ChannelData currentChannel = null;
420 Stack currentProviderData = null;
422 string currentClientUrl = null;
423 string appName;
425 string currentXmlPath = "";
426 bool onlyDelayedChannels;
428 public ConfigHandler (bool onlyDelayedChannels)
430 this.onlyDelayedChannels = onlyDelayedChannels;
433 void ValidatePath (string element, params string[] paths)
435 foreach (string path in paths)
436 if (CheckPath (path)) return;
438 throw new RemotingException ("Element " + element + " not allowed in this context");
441 bool CheckPath (string path)
443 if (path.StartsWith ("/"))
444 return path == currentXmlPath;
445 else
446 return currentXmlPath.EndsWith (path);
449 public void OnStartParsing (MiniParser parser) {}
451 public void OnStartElement (string name, MiniParser.IAttrList attrs)
455 if (currentXmlPath.StartsWith ("/configuration/system.runtime.remoting"))
456 ParseElement (name, attrs);
458 currentXmlPath += "/" + name;
460 catch (Exception ex)
462 throw new RemotingException ("Error in element " + name + ": " + ex.Message);
466 public void ParseElement (string name, MiniParser.IAttrList attrs)
468 if (currentProviderData != null)
470 ReadCustomProviderData (name, attrs);
471 return;
474 switch (name)
476 case "application":
477 ValidatePath (name, "system.runtime.remoting");
478 if (attrs.Names.Length > 0)
479 appName = attrs.Values[0];
480 break;
482 case "lifetime":
483 ValidatePath (name, "application");
484 ReadLifetine (attrs);
485 break;
487 case "channels":
488 ValidatePath (name, "system.runtime.remoting", "application");
489 break;
491 case "channel":
492 ValidatePath (name, "channels");
493 if (currentXmlPath.IndexOf ("application") != -1)
494 ReadChannel (attrs, false);
495 else
496 ReadChannel (attrs, true);
497 break;
499 case "serverProviders":
500 ValidatePath (name, "channelSinkProviders", "channel");
501 break;
503 case "clientProviders":
504 ValidatePath (name, "channelSinkProviders", "channel");
505 break;
507 case "provider":
508 case "formatter":
509 ProviderData prov;
511 if (CheckPath ("application/channels/channel/serverProviders") ||
512 CheckPath ("channels/channel/serverProviders"))
514 prov = ReadProvider (name, attrs, false);
515 currentChannel.ServerProviders.Add (prov);
517 else if (CheckPath ("application/channels/channel/clientProviders") ||
518 CheckPath ("channels/channel/clientProviders"))
520 prov = ReadProvider (name, attrs, false);
521 currentChannel.ClientProviders.Add (prov);
523 else if (CheckPath ("channelSinkProviders/serverProviders"))
525 prov = ReadProvider (name, attrs, true);
526 RemotingConfiguration.RegisterServerProviderTemplate (prov);
528 else if (CheckPath ("channelSinkProviders/clientProviders"))
530 prov = ReadProvider (name, attrs, true);
531 RemotingConfiguration.RegisterClientProviderTemplate (prov);
533 else
534 ValidatePath (name);
535 break;
537 case "client":
538 ValidatePath (name, "application");
539 currentClientUrl = attrs.GetValue ("url");
540 break;
542 case "service":
543 ValidatePath (name, "application");
544 break;
546 case "wellknown":
547 ValidatePath (name, "client", "service");
548 if (CheckPath ("client"))
549 ReadClientWellKnown (attrs);
550 else
551 ReadServiceWellKnown (attrs);
552 break;
554 case "activated":
555 ValidatePath (name, "client", "service");
556 if (CheckPath ("client"))
557 ReadClientActivated (attrs);
558 else
559 ReadServiceActivated (attrs);
560 break;
562 case "soapInterop":
563 ValidatePath (name, "application");
564 break;
566 case "interopXmlType":
567 ValidatePath (name, "soapInterop");
568 ReadInteropXml (attrs, false);
569 break;
571 case "interopXmlElement":
572 ValidatePath (name, "soapInterop");
573 ReadInteropXml (attrs, false);
574 break;
576 case "preLoad":
577 ValidatePath (name, "soapInterop");
578 ReadPreload (attrs);
579 break;
581 case "debug":
582 ValidatePath (name, "system.runtime.remoting");
583 break;
585 case "channelSinkProviders":
586 ValidatePath (name, "system.runtime.remoting");
587 break;
589 case "customErrors":
590 ValidatePath (name, "system.runtime.remoting");
591 RemotingConfiguration.SetCustomErrorsMode (attrs.GetValue ("mode"));
592 break;
594 default:
595 throw new RemotingException ("Element '" + name + "' is not valid in system.remoting.configuration section");
599 public void OnEndElement (string name)
601 if (currentProviderData != null)
603 currentProviderData.Pop ();
604 if (currentProviderData.Count > 0) return;
605 currentProviderData = null;
608 currentXmlPath = currentXmlPath.Substring (0, currentXmlPath.Length - name.Length - 1);
611 void ReadCustomProviderData (string name, MiniParser.IAttrList attrs)
613 SinkProviderData parent = (SinkProviderData) currentProviderData.Peek ();
615 SinkProviderData data = new SinkProviderData (name);
616 for (int i=0; i < attrs.Names.Length; ++i)
617 data.Properties [attrs.Names[i]] = attrs.GetValue (i);
619 parent.Children.Add (data);
620 currentProviderData.Push (data);
623 void ReadLifetine (MiniParser.IAttrList attrs)
625 for (int i=0; i < attrs.Names.Length; ++i) {
626 switch (attrs.Names[i]) {
627 case "leaseTime":
628 LifetimeServices.LeaseTime = ParseTime (attrs.GetValue(i));
629 break;
630 case "sponsorshipTimeout":
631 LifetimeServices.SponsorshipTimeout = ParseTime (attrs.GetValue(i));
632 break;
633 case "renewOnCallTime":
634 LifetimeServices.RenewOnCallTime = ParseTime (attrs.GetValue(i));
635 break;
636 case "leaseManagerPollTime":
637 LifetimeServices.LeaseManagerPollTime = ParseTime (attrs.GetValue(i));
638 break;
639 default:
640 throw new RemotingException ("Invalid attribute: " + attrs.Names[i]);
645 TimeSpan ParseTime (string s)
647 if (s == "" || s == null) throw new RemotingException ("Invalid time value");
649 int i = s.IndexOfAny (new char[] { 'D','H','M','S' });
651 string unit;
652 if (i == -1)
653 unit = "S";
654 else {
655 unit = s.Substring (i);
656 s = s.Substring (0,i);
658 double val;
660 try {
661 val = double.Parse (s);
663 catch {
664 throw new RemotingException ("Invalid time value: " + s);
667 if (unit == "D") return TimeSpan.FromDays (val);
668 if (unit == "H") return TimeSpan.FromHours (val);
669 if (unit == "M") return TimeSpan.FromMinutes (val);
670 if (unit == "S") return TimeSpan.FromSeconds (val);
671 if (unit == "MS") return TimeSpan.FromMilliseconds (val);
672 throw new RemotingException ("Invalid time unit: " + unit);
675 void ReadChannel (MiniParser.IAttrList attrs, bool isTemplate)
677 ChannelData channel = new ChannelData ();
679 for (int i=0; i < attrs.Names.Length; ++i)
681 string at = attrs.Names[i];
682 string val = attrs.Values[i];
684 if (at == "ref" && !isTemplate)
685 channel.Ref = val;
686 else if (at == "delayLoadAsClientChannel")
687 channel.DelayLoadAsClientChannel = val;
688 else if (at == "id" && isTemplate)
689 channel.Id = val;
690 else if (at == "type")
691 channel.Type = val;
692 else
693 channel.CustomProperties.Add (at, val);
696 if (isTemplate)
698 if (channel.Id == null) throw new RemotingException ("id attribute is required");
699 if (channel.Type == null) throw new RemotingException ("id attribute is required");
700 RemotingConfiguration.RegisterChannelTemplate (channel);
702 else
703 channelInstances.Add (channel);
705 currentChannel = channel;
708 ProviderData ReadProvider (string name, MiniParser.IAttrList attrs, bool isTemplate)
710 ProviderData prov = (name == "provider") ? new ProviderData () : new FormatterData ();
711 SinkProviderData data = new SinkProviderData ("root");
712 prov.CustomData = data.Children;
714 currentProviderData = new Stack ();
715 currentProviderData.Push (data);
717 for (int i=0; i < attrs.Names.Length; ++i)
719 string at = attrs.Names[i];
720 string val = attrs.Values[i];
722 if (at == "id" && isTemplate)
723 prov.Id = val;
724 else if (at == "type")
725 prov.Type = val;
726 else if (at == "ref" && !isTemplate)
727 prov.Ref = val;
728 else
729 prov.CustomProperties.Add (at, val);
732 if (prov.Id == null && isTemplate) throw new RemotingException ("id attribute is required");
733 return prov;
736 void ReadClientActivated (MiniParser.IAttrList attrs)
738 string type = GetNotNull (attrs, "type");
739 string assm = ExtractAssembly (ref type);
741 if (currentClientUrl == null || currentClientUrl == "")
742 throw new RemotingException ("url attribute is required in client element when it contains activated entries");
744 typeEntries.Add (new ActivatedClientTypeEntry (type, assm, currentClientUrl));
747 void ReadServiceActivated (MiniParser.IAttrList attrs)
749 string type = GetNotNull (attrs, "type");
750 string assm = ExtractAssembly (ref type);
752 typeEntries.Add (new ActivatedServiceTypeEntry (type, assm));
755 void ReadClientWellKnown (MiniParser.IAttrList attrs)
757 string url = GetNotNull (attrs, "url");
758 string type = GetNotNull (attrs, "type");
759 string assm = ExtractAssembly (ref type);
761 typeEntries.Add (new WellKnownClientTypeEntry (type, assm, url));
764 void ReadServiceWellKnown (MiniParser.IAttrList attrs)
766 string objectUri = GetNotNull (attrs, "objectUri");
767 string smode = GetNotNull (attrs, "mode");
768 string type = GetNotNull (attrs, "type");
769 string assm = ExtractAssembly (ref type);
771 WellKnownObjectMode mode;
772 if (smode == "SingleCall") mode = WellKnownObjectMode.SingleCall;
773 else if (smode == "Singleton") mode = WellKnownObjectMode.Singleton;
774 else throw new RemotingException ("wellknown object mode '" + smode + "' is invalid");
776 typeEntries.Add (new WellKnownServiceTypeEntry (type, assm, objectUri, mode));
779 void ReadInteropXml (MiniParser.IAttrList attrs, bool isElement)
781 Type t = Type.GetType (GetNotNull (attrs, "clr"));
782 string[] xmlName = GetNotNull (attrs, "xml").Split (',');
783 string localName = xmlName [0].Trim ();
784 string ns = xmlName.Length > 0 ? xmlName[1].Trim() : null;
786 if (isElement) SoapServices.RegisterInteropXmlElement (localName, ns, t);
787 else SoapServices.RegisterInteropXmlType (localName, ns, t);
790 void ReadPreload (MiniParser.IAttrList attrs)
792 string type = attrs.GetValue ("type");
793 string assm = attrs.GetValue ("assembly");
795 if (type != null && assm != null)
796 throw new RemotingException ("Type and assembly attributes cannot be specified together");
798 if (type != null)
799 SoapServices.PreLoad (Type.GetType (type));
800 else if (assm != null)
801 SoapServices.PreLoad (Assembly.Load (assm));
802 else
803 throw new RemotingException ("Either type or assembly attributes must be specified");
806 string GetNotNull (MiniParser.IAttrList attrs, string name)
808 string value = attrs.GetValue (name);
809 if (value == null || value == "")
810 throw new RemotingException (name + " attribute is required");
811 return value;
814 string ExtractAssembly (ref string type)
816 int i = type.IndexOf (',');
817 if (i == -1) return "";
819 string asm = type.Substring (i+1).Trim();
820 type = type.Substring (0, i).Trim();
821 return asm;
824 public void OnChars (string ch) {}
826 public void OnEndParsing (MiniParser parser)
828 RemotingConfiguration.RegisterChannels (channelInstances, onlyDelayedChannels);
829 if (appName != null) RemotingConfiguration.ApplicationName = appName;
831 if (!onlyDelayedChannels)
832 RemotingConfiguration.RegisterTypes (typeEntries);
837 /*******************************************************************
838 * Internal data structures used by ConfigHandler, to store *
839 * machine.config's remoting related data. *
840 * If having them implemented this way, makes configuration too *
841 * slow, we can use string arrays. *
842 *******************************************************************/
844 internal class ChannelData {
845 internal string Ref;
846 internal string Type;
847 internal string Id;
848 internal string DelayLoadAsClientChannel;
850 ArrayList _serverProviders = new ArrayList ();
851 ArrayList _clientProviders = new ArrayList ();
852 Hashtable _customProperties = new Hashtable ();
854 internal ArrayList ServerProviders {
855 get {
856 if (_serverProviders == null) _serverProviders = new ArrayList ();
857 return _serverProviders;
861 public ArrayList ClientProviders {
862 get {
863 if (_clientProviders == null) _clientProviders = new ArrayList ();
864 return _clientProviders;
868 public Hashtable CustomProperties {
869 get {
870 if (_customProperties == null) _customProperties = new Hashtable ();
871 return _customProperties;
875 public void CopyFrom (ChannelData other)
877 if (Ref == null) Ref = other.Ref;
878 if (Id == null) Id = other.Id;
879 if (Type == null) Type = other.Type;
880 if (DelayLoadAsClientChannel == null) DelayLoadAsClientChannel = other.DelayLoadAsClientChannel;
882 if (other._customProperties != null)
884 foreach (DictionaryEntry entry in other._customProperties)
885 if (!CustomProperties.ContainsKey (entry.Key))
886 CustomProperties [entry.Key] = entry.Value;
889 if (_serverProviders == null && other._serverProviders != null)
891 foreach (ProviderData prov in other._serverProviders)
893 ProviderData np = new ProviderData();
894 np.CopyFrom (prov);
895 ServerProviders.Add (np);
899 if (_clientProviders == null && other._clientProviders != null)
901 foreach (ProviderData prov in other._clientProviders)
903 ProviderData np = new ProviderData();
904 np.CopyFrom (prov);
905 ClientProviders.Add (np);
911 internal class ProviderData {
912 internal string Ref;
913 internal string Type;
914 internal string Id;
916 internal Hashtable CustomProperties = new Hashtable ();
917 internal IList CustomData;
919 public void CopyFrom (ProviderData other)
921 if (Ref == null) Ref = other.Ref;
922 if (Id == null) Id = other.Id;
923 if (Type == null) Type = other.Type;
925 foreach (DictionaryEntry entry in other.CustomProperties)
926 if (!CustomProperties.ContainsKey (entry.Key))
927 CustomProperties [entry.Key] = entry.Value;
929 if (other.CustomData != null)
931 if (CustomData == null) CustomData = new ArrayList ();
932 foreach (SinkProviderData data in other.CustomData)
933 CustomData.Add (data);
938 internal class FormatterData: ProviderData {