2 // System.Runtime.Remoting.RemotingConfiguration.cs
4 // Author: Jaime Anguiano Olarra (jaime@gnome.org)
5 // Lluis Sanchez Gual (lluis@ideary.com)
7 // (C) 2002, Jaime Anguiano Olarra
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:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
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.
34 using System
.Globalization
;
36 using System
.Reflection
;
37 using System
.Collections
;
38 using System
.Runtime
.Remoting
.Activation
;
39 using System
.Runtime
.Remoting
.Channels
;
40 using System
.Runtime
.Remoting
.Lifetime
;
43 namespace System
.Runtime
.Remoting
45 [System
.Runtime
.InteropServices
.ComVisible (true)]
46 public static class RemotingConfiguration
49 static string applicationID
= null;
50 static string applicationName
= null;
51 // static string configFile = "";
52 // static SmallXmlParser parser = null;
53 static string processGuid
= null;
54 static bool defaultConfigRead
= false;
55 static bool defaultDelayedConfigRead
= false;
56 static string _errorMode
;
58 static Hashtable wellKnownClientEntries
= new Hashtable();
59 static Hashtable activatedClientEntries
= new Hashtable();
60 static Hashtable wellKnownServiceEntries
= new Hashtable();
61 static Hashtable activatedServiceEntries
= new Hashtable();
63 static Hashtable channelTemplates
= new Hashtable ();
64 static Hashtable clientProviderTemplates
= new Hashtable ();
65 static Hashtable serverProviderTemplates
= new Hashtable ();
68 // At this time the ID will be the application name
69 public static string ApplicationId
73 applicationID
= ApplicationName
;
78 public static string ApplicationName
80 get { return applicationName; }
81 set { applicationName = value; }
85 public static CustomErrorsModes CustomErrorsMode
87 get { throw new NotImplementedException (); }
88 set { throw new NotImplementedException (); }
91 public static string ProcessId
94 if (processGuid
== null)
95 processGuid
= AppDomain
.GetProcessGuid ();
104 [MonoTODO ("ensureSecurity support has not been implemented")]
105 public static void Configure (string filename
, bool ensureSecurity
)
107 lock (channelTemplates
) {
108 if (!defaultConfigRead
) {
109 ReadConfigFile (Environment
.GetMachineConfigPath ());
110 defaultConfigRead
= true;
113 if (filename
!= null)
114 ReadConfigFile (filename
);
118 [Obsolete ("Use Configure(String,Boolean)")]
119 public static void Configure (string filename
)
121 Configure (filename
, false);
124 private static void ReadConfigFile (string filename
)
128 SmallXmlParser parser
= new SmallXmlParser ();
129 using (TextReader rreader
= new StreamReader (filename
)) {
130 ConfigHandler handler
= new ConfigHandler (false);
131 parser
.Parse (rreader
, handler
);
136 throw new RemotingException ("Configuration file '" + filename
+ "' could not be loaded: " + ex
.Message
, ex
);
140 internal static void LoadDefaultDelayedChannels ()
142 lock (channelTemplates
)
144 if (defaultDelayedConfigRead
|| defaultConfigRead
) return;
146 SmallXmlParser parser
= new SmallXmlParser ();
147 using (TextReader rreader
= new StreamReader (Environment
.GetMachineConfigPath ())) {
148 ConfigHandler handler
= new ConfigHandler (true);
149 parser
.Parse (rreader
, handler
);
151 defaultDelayedConfigRead
= true;
155 public static ActivatedClientTypeEntry
[] GetRegisteredActivatedClientTypes ()
157 lock (channelTemplates
)
159 ActivatedClientTypeEntry
[] entries
= new ActivatedClientTypeEntry
[activatedClientEntries
.Count
];
160 activatedClientEntries
.Values
.CopyTo (entries
,0);
165 public static ActivatedServiceTypeEntry
[] GetRegisteredActivatedServiceTypes ()
167 lock (channelTemplates
)
169 ActivatedServiceTypeEntry
[] entries
= new ActivatedServiceTypeEntry
[activatedServiceEntries
.Count
];
170 activatedServiceEntries
.Values
.CopyTo (entries
,0);
175 public static WellKnownClientTypeEntry
[] GetRegisteredWellKnownClientTypes ()
177 lock (channelTemplates
)
179 WellKnownClientTypeEntry
[] entries
= new WellKnownClientTypeEntry
[wellKnownClientEntries
.Count
];
180 wellKnownClientEntries
.Values
.CopyTo (entries
,0);
185 public static WellKnownServiceTypeEntry
[] GetRegisteredWellKnownServiceTypes ()
187 lock (channelTemplates
)
189 WellKnownServiceTypeEntry
[] entries
= new WellKnownServiceTypeEntry
[wellKnownServiceEntries
.Count
];
190 wellKnownServiceEntries
.Values
.CopyTo (entries
,0);
195 public static bool IsActivationAllowed (Type svrType
)
197 lock (channelTemplates
)
199 return activatedServiceEntries
.ContainsKey (svrType
);
203 public static ActivatedClientTypeEntry
IsRemotelyActivatedClientType (Type svrType
)
205 lock (channelTemplates
)
207 return activatedClientEntries
[svrType
] as ActivatedClientTypeEntry
;
211 public static ActivatedClientTypeEntry
IsRemotelyActivatedClientType (string typeName
, string assemblyName
)
213 return IsRemotelyActivatedClientType (Assembly
.Load(assemblyName
).GetType (typeName
));
216 public static WellKnownClientTypeEntry
IsWellKnownClientType (Type svrType
)
218 lock (channelTemplates
)
220 return wellKnownClientEntries
[svrType
] as WellKnownClientTypeEntry
;
224 public static WellKnownClientTypeEntry
IsWellKnownClientType (string typeName
, string assemblyName
)
226 return IsWellKnownClientType (Assembly
.Load(assemblyName
).GetType (typeName
));
229 public static void RegisterActivatedClientType (ActivatedClientTypeEntry entry
)
231 lock (channelTemplates
)
233 if (wellKnownClientEntries
.ContainsKey (entry
.ObjectType
) || activatedClientEntries
.ContainsKey (entry
.ObjectType
))
234 throw new RemotingException ("Attempt to redirect activation of type '" + entry
.ObjectType
.FullName
+ "' which is already redirected.");
236 activatedClientEntries
[entry
.ObjectType
] = entry
;
237 ActivationServices
.EnableProxyActivation (entry
.ObjectType
, true);
241 public static void RegisterActivatedClientType (Type type
, string appUrl
)
243 if (type
== null) throw new ArgumentNullException ("type");
244 if (appUrl
== null) throw new ArgumentNullException ("appUrl");
246 RegisterActivatedClientType (new ActivatedClientTypeEntry (type
, appUrl
));
249 public static void RegisterActivatedServiceType (ActivatedServiceTypeEntry entry
)
251 lock (channelTemplates
)
253 activatedServiceEntries
.Add (entry
.ObjectType
, entry
);
257 public static void RegisterActivatedServiceType (Type type
)
259 RegisterActivatedServiceType (new ActivatedServiceTypeEntry (type
));
262 public static void RegisterWellKnownClientType (Type type
, string objectUrl
)
264 if (type
== null) throw new ArgumentNullException ("type");
265 if (objectUrl
== null) throw new ArgumentNullException ("objectUrl");
267 RegisterWellKnownClientType (new WellKnownClientTypeEntry (type
, objectUrl
));
270 public static void RegisterWellKnownClientType (WellKnownClientTypeEntry entry
)
272 lock (channelTemplates
)
274 if (wellKnownClientEntries
.ContainsKey (entry
.ObjectType
) || activatedClientEntries
.ContainsKey (entry
.ObjectType
))
275 throw new RemotingException ("Attempt to redirect activation of type '" + entry
.ObjectType
.FullName
+ "' which is already redirected.");
277 wellKnownClientEntries
[entry
.ObjectType
] = entry
;
278 ActivationServices
.EnableProxyActivation (entry
.ObjectType
, true);
282 public static void RegisterWellKnownServiceType (Type type
, string objectUri
, WellKnownObjectMode mode
)
284 RegisterWellKnownServiceType (new WellKnownServiceTypeEntry (type
, objectUri
, mode
));
287 public static void RegisterWellKnownServiceType (WellKnownServiceTypeEntry entry
)
289 lock (channelTemplates
)
291 wellKnownServiceEntries
[entry
.ObjectUri
] = entry
;
292 RemotingServices
.CreateWellKnownServerIdentity (entry
.ObjectType
, entry
.ObjectUri
, entry
.Mode
);
296 internal static void RegisterChannelTemplate (ChannelData channel
)
298 channelTemplates
[channel
.Id
] = channel
;
301 internal static void RegisterClientProviderTemplate (ProviderData prov
)
303 clientProviderTemplates
[prov
.Id
] = prov
;
306 internal static void RegisterServerProviderTemplate (ProviderData prov
)
308 serverProviderTemplates
[prov
.Id
] = prov
;
311 internal static void RegisterChannels (ArrayList channels
, bool onlyDelayed
)
313 foreach (ChannelData channel
in channels
)
315 if (onlyDelayed
&& channel
.DelayLoadAsClientChannel
!= "true")
318 if (defaultDelayedConfigRead
&& channel
.DelayLoadAsClientChannel
== "true")
321 if (channel
.Ref
!= null)
323 ChannelData template
= (ChannelData
) channelTemplates
[channel
.Ref
];
324 if (template
== null) throw new RemotingException ("Channel template '" + channel
.Ref
+ "' not found");
325 channel
.CopyFrom (template
);
328 foreach (ProviderData prov
in channel
.ServerProviders
)
330 if (prov
.Ref
!= null)
332 ProviderData template
= (ProviderData
) serverProviderTemplates
[prov
.Ref
];
333 if (template
== null) throw new RemotingException ("Provider template '" + prov
.Ref
+ "' not found");
334 prov
.CopyFrom (template
);
338 foreach (ProviderData prov
in channel
.ClientProviders
)
340 if (prov
.Ref
!= null)
342 ProviderData template
= (ProviderData
) clientProviderTemplates
[prov
.Ref
];
343 if (template
== null) throw new RemotingException ("Provider template '" + prov
.Ref
+ "' not found");
344 prov
.CopyFrom (template
);
348 ChannelServices
.RegisterChannelConfig (channel
);
352 internal static void RegisterTypes (ArrayList types
)
354 foreach (TypeEntry type
in types
)
356 if (type
is ActivatedClientTypeEntry
)
357 RegisterActivatedClientType ((ActivatedClientTypeEntry
)type
);
358 else if (type
is ActivatedServiceTypeEntry
)
359 RegisterActivatedServiceType ((ActivatedServiceTypeEntry
)type
);
360 else if (type
is WellKnownClientTypeEntry
)
361 RegisterWellKnownClientType ((WellKnownClientTypeEntry
)type
);
362 else if (type
is WellKnownServiceTypeEntry
)
363 RegisterWellKnownServiceType ((WellKnownServiceTypeEntry
)type
);
368 public static bool CustomErrorsEnabled (bool isLocalRequest
)
370 if (_errorMode
== "off") return false;
371 if (_errorMode
== "on") return true;
372 return !isLocalRequest
;
376 internal static void SetCustomErrorsMode (string mode
)
379 throw new RemotingException ("mode attribute is required");
381 // the mode is case insensitive
382 string m
= mode
.ToLower ();
384 if (m
!= "on" && m
!= "off" && m
!= "remoteonly")
385 throw new RemotingException ("Invalid custom error mode: " + mode
);
391 /***************************************************************
392 * Internal classes used by RemotingConfiguration.Configure () *
393 ***************************************************************/
395 internal class ConfigHandler
: SmallXmlParser
.IContentHandler
397 ArrayList typeEntries
= new ArrayList ();
398 ArrayList channelInstances
= new ArrayList ();
400 ChannelData currentChannel
= null;
401 Stack currentProviderData
= null;
403 string currentClientUrl
= null;
406 string currentXmlPath
= "";
407 bool onlyDelayedChannels
;
409 public ConfigHandler (bool onlyDelayedChannels
)
411 this.onlyDelayedChannels
= onlyDelayedChannels
;
414 void ValidatePath (string element
, params string[] paths
)
416 foreach (string path
in paths
)
417 if (CheckPath (path
)) return;
419 throw new RemotingException ("Element " + element
+ " not allowed in this context");
422 bool CheckPath (string path
)
424 CompareInfo ci
= CultureInfo
.InvariantCulture
.CompareInfo
;
425 if (ci
.IsPrefix (path
, "/", CompareOptions
.Ordinal
))
426 return path
== currentXmlPath
;
428 return ci
.IsSuffix (currentXmlPath
, path
, CompareOptions
.Ordinal
);
431 public void OnStartParsing (SmallXmlParser parser
) {}
433 public void OnProcessingInstruction (string name
, string text
) {}
435 public void OnIgnorableWhitespace (string s
) {}
437 public void OnStartElement (string name
, SmallXmlParser
.IAttrList attrs
)
441 if (currentXmlPath
.StartsWith ("/configuration/system.runtime.remoting"))
442 ParseElement (name
, attrs
);
444 currentXmlPath
+= "/" + name
;
448 throw new RemotingException ("Error in element " + name
+ ": " + ex
.Message
, ex
);
452 public void ParseElement (string name
, SmallXmlParser
.IAttrList attrs
)
454 if (currentProviderData
!= null)
456 ReadCustomProviderData (name
, attrs
);
463 ValidatePath (name
, "system.runtime.remoting");
464 if (attrs
.Names
.Length
> 0)
465 appName
= attrs
.Values
[0];
469 ValidatePath (name
, "application");
470 ReadLifetine (attrs
);
474 ValidatePath (name
, "system.runtime.remoting", "application");
478 ValidatePath (name
, "channels");
479 if (currentXmlPath
.IndexOf ("application") != -1)
480 ReadChannel (attrs
, false);
482 ReadChannel (attrs
, true);
485 case "serverProviders":
486 ValidatePath (name
, "channelSinkProviders", "channel");
489 case "clientProviders":
490 ValidatePath (name
, "channelSinkProviders", "channel");
497 if (CheckPath ("application/channels/channel/serverProviders") ||
498 CheckPath ("channels/channel/serverProviders"))
500 prov
= ReadProvider (name
, attrs
, false);
501 currentChannel
.ServerProviders
.Add (prov
);
503 else if (CheckPath ("application/channels/channel/clientProviders") ||
504 CheckPath ("channels/channel/clientProviders"))
506 prov
= ReadProvider (name
, attrs
, false);
507 currentChannel
.ClientProviders
.Add (prov
);
509 else if (CheckPath ("channelSinkProviders/serverProviders"))
511 prov
= ReadProvider (name
, attrs
, true);
512 RemotingConfiguration
.RegisterServerProviderTemplate (prov
);
514 else if (CheckPath ("channelSinkProviders/clientProviders"))
516 prov
= ReadProvider (name
, attrs
, true);
517 RemotingConfiguration
.RegisterClientProviderTemplate (prov
);
524 ValidatePath (name
, "application");
525 currentClientUrl
= attrs
.GetValue ("url");
529 ValidatePath (name
, "application");
533 ValidatePath (name
, "client", "service");
534 if (CheckPath ("client"))
535 ReadClientWellKnown (attrs
);
537 ReadServiceWellKnown (attrs
);
541 ValidatePath (name
, "client", "service");
542 if (CheckPath ("client"))
543 ReadClientActivated (attrs
);
545 ReadServiceActivated (attrs
);
549 ValidatePath (name
, "application");
552 case "interopXmlType":
553 ValidatePath (name
, "soapInterop");
554 ReadInteropXml (attrs
, false);
557 case "interopXmlElement":
558 ValidatePath (name
, "soapInterop");
559 ReadInteropXml (attrs
, false);
563 ValidatePath (name
, "soapInterop");
568 ValidatePath (name
, "system.runtime.remoting");
571 case "channelSinkProviders":
572 ValidatePath (name
, "system.runtime.remoting");
576 ValidatePath (name
, "system.runtime.remoting");
577 RemotingConfiguration
.SetCustomErrorsMode (attrs
.GetValue ("mode"));
581 throw new RemotingException ("Element '" + name
+ "' is not valid in system.remoting.configuration section");
585 public void OnEndElement (string name
)
587 if (currentProviderData
!= null)
589 currentProviderData
.Pop ();
590 if (currentProviderData
.Count
== 0)
591 currentProviderData
= null;
594 currentXmlPath
= currentXmlPath
.Substring (0, currentXmlPath
.Length
- name
.Length
- 1);
597 void ReadCustomProviderData (string name
, SmallXmlParser
.IAttrList attrs
)
599 SinkProviderData parent
= (SinkProviderData
) currentProviderData
.Peek ();
601 SinkProviderData data
= new SinkProviderData (name
);
602 for (int i
=0; i
< attrs
.Names
.Length
; ++i
)
603 data
.Properties
[attrs
.Names
[i
]] = attrs
.GetValue (i
);
605 parent
.Children
.Add (data
);
606 currentProviderData
.Push (data
);
609 void ReadLifetine (SmallXmlParser
.IAttrList attrs
)
611 for (int i
=0; i
< attrs
.Names
.Length
; ++i
) {
612 switch (attrs
.Names
[i
]) {
614 LifetimeServices
.LeaseTime
= ParseTime (attrs
.GetValue(i
));
616 case "sponsorshipTimeout":
617 LifetimeServices
.SponsorshipTimeout
= ParseTime (attrs
.GetValue(i
));
619 case "renewOnCallTime":
620 LifetimeServices
.RenewOnCallTime
= ParseTime (attrs
.GetValue(i
));
622 case "leaseManagerPollTime":
623 LifetimeServices
.LeaseManagerPollTime
= ParseTime (attrs
.GetValue(i
));
626 throw new RemotingException ("Invalid attribute: " + attrs
.Names
[i
]);
631 TimeSpan
ParseTime (string s
)
633 if (s
== "" || s
== null) throw new RemotingException ("Invalid time value");
635 int i
= s
.IndexOfAny (new char[] { 'D','H','M','S' }
);
641 unit
= s
.Substring (i
);
642 s
= s
.Substring (0,i
);
647 val
= double.Parse (s
);
650 throw new RemotingException ("Invalid time value: " + s
);
653 if (unit
== "D") return TimeSpan
.FromDays (val
);
654 if (unit
== "H") return TimeSpan
.FromHours (val
);
655 if (unit
== "M") return TimeSpan
.FromMinutes (val
);
656 if (unit
== "S") return TimeSpan
.FromSeconds (val
);
657 if (unit
== "MS") return TimeSpan
.FromMilliseconds (val
);
658 throw new RemotingException ("Invalid time unit: " + unit
);
661 void ReadChannel (SmallXmlParser
.IAttrList attrs
, bool isTemplate
)
663 ChannelData channel
= new ChannelData ();
665 for (int i
=0; i
< attrs
.Names
.Length
; ++i
)
667 string at
= attrs
.Names
[i
];
668 string val
= attrs
.Values
[i
];
670 if (at
== "ref" && !isTemplate
)
672 else if (at
== "delayLoadAsClientChannel")
673 channel
.DelayLoadAsClientChannel
= val
;
674 else if (at
== "id" && isTemplate
)
676 else if (at
== "type")
679 channel
.CustomProperties
.Add (at
, val
);
684 if (channel
.Id
== null) throw new RemotingException ("id attribute is required");
685 if (channel
.Type
== null) throw new RemotingException ("id attribute is required");
686 RemotingConfiguration
.RegisterChannelTemplate (channel
);
689 channelInstances
.Add (channel
);
691 currentChannel
= channel
;
694 ProviderData
ReadProvider (string name
, SmallXmlParser
.IAttrList attrs
, bool isTemplate
)
696 ProviderData prov
= (name
== "provider") ? new ProviderData () : new FormatterData ();
697 SinkProviderData data
= new SinkProviderData ("root");
698 prov
.CustomData
= data
.Children
;
700 currentProviderData
= new Stack ();
701 currentProviderData
.Push (data
);
703 for (int i
=0; i
< attrs
.Names
.Length
; ++i
)
705 string at
= attrs
.Names
[i
];
706 string val
= attrs
.Values
[i
];
708 if (at
== "id" && isTemplate
)
710 else if (at
== "type")
712 else if (at
== "ref" && !isTemplate
)
715 prov
.CustomProperties
.Add (at
, val
);
718 if (prov
.Id
== null && isTemplate
) throw new RemotingException ("id attribute is required");
722 void ReadClientActivated (SmallXmlParser
.IAttrList attrs
)
724 string type
= GetNotNull (attrs
, "type");
725 string assm
= ExtractAssembly (ref type
);
727 if (currentClientUrl
== null || currentClientUrl
== "")
728 throw new RemotingException ("url attribute is required in client element when it contains activated entries");
730 typeEntries
.Add (new ActivatedClientTypeEntry (type
, assm
, currentClientUrl
));
733 void ReadServiceActivated (SmallXmlParser
.IAttrList attrs
)
735 string type
= GetNotNull (attrs
, "type");
736 string assm
= ExtractAssembly (ref type
);
738 typeEntries
.Add (new ActivatedServiceTypeEntry (type
, assm
));
741 void ReadClientWellKnown (SmallXmlParser
.IAttrList attrs
)
743 string url
= GetNotNull (attrs
, "url");
744 string type
= GetNotNull (attrs
, "type");
745 string assm
= ExtractAssembly (ref type
);
747 typeEntries
.Add (new WellKnownClientTypeEntry (type
, assm
, url
));
750 void ReadServiceWellKnown (SmallXmlParser
.IAttrList attrs
)
752 string objectUri
= GetNotNull (attrs
, "objectUri");
753 string smode
= GetNotNull (attrs
, "mode");
754 string type
= GetNotNull (attrs
, "type");
755 string assm
= ExtractAssembly (ref type
);
757 WellKnownObjectMode mode
;
758 if (smode
== "SingleCall") mode
= WellKnownObjectMode
.SingleCall
;
759 else if (smode
== "Singleton") mode
= WellKnownObjectMode
.Singleton
;
760 else throw new RemotingException ("wellknown object mode '" + smode
+ "' is invalid");
762 typeEntries
.Add (new WellKnownServiceTypeEntry (type
, assm
, objectUri
, mode
));
765 void ReadInteropXml (SmallXmlParser
.IAttrList attrs
, bool isElement
)
767 Type t
= Type
.GetType (GetNotNull (attrs
, "clr"));
768 string[] xmlName
= GetNotNull (attrs
, "xml").Split (',');
769 string localName
= xmlName
[0].Trim ();
770 string ns
= xmlName
.Length
> 0 ? xmlName
[1].Trim() : null;
772 if (isElement
) SoapServices
.RegisterInteropXmlElement (localName
, ns
, t
);
773 else SoapServices
.RegisterInteropXmlType (localName
, ns
, t
);
776 void ReadPreload (SmallXmlParser
.IAttrList attrs
)
778 string type
= attrs
.GetValue ("type");
779 string assm
= attrs
.GetValue ("assembly");
781 if (type
!= null && assm
!= null)
782 throw new RemotingException ("Type and assembly attributes cannot be specified together");
785 SoapServices
.PreLoad (Type
.GetType (type
));
786 else if (assm
!= null)
787 SoapServices
.PreLoad (Assembly
.Load (assm
));
789 throw new RemotingException ("Either type or assembly attributes must be specified");
792 string GetNotNull (SmallXmlParser
.IAttrList attrs
, string name
)
794 string value = attrs
.GetValue (name
);
795 if (value == null || value == "")
796 throw new RemotingException (name
+ " attribute is required");
800 string ExtractAssembly (ref string type
)
802 int i
= type
.IndexOf (',');
803 if (i
== -1) return "";
805 string asm
= type
.Substring (i
+1).Trim();
806 type
= type
.Substring (0, i
).Trim();
810 public void OnChars (string ch
) {}
812 public void OnEndParsing (SmallXmlParser parser
)
814 RemotingConfiguration
.RegisterChannels (channelInstances
, onlyDelayedChannels
);
815 if (appName
!= null) RemotingConfiguration
.ApplicationName
= appName
;
817 if (!onlyDelayedChannels
)
818 RemotingConfiguration
.RegisterTypes (typeEntries
);
823 /*******************************************************************
824 * Internal data structures used by ConfigHandler, to store *
825 * machine.config's remoting related data. *
826 * If having them implemented this way, makes configuration too *
827 * slow, we can use string arrays. *
828 *******************************************************************/
830 internal class ChannelData
{
832 internal string Type
;
834 internal string DelayLoadAsClientChannel
;
836 ArrayList _serverProviders
= new ArrayList ();
837 ArrayList _clientProviders
= new ArrayList ();
838 Hashtable _customProperties
= new Hashtable ();
840 internal ArrayList ServerProviders
{
842 if (_serverProviders
== null) _serverProviders
= new ArrayList ();
843 return _serverProviders
;
847 public ArrayList ClientProviders
{
849 if (_clientProviders
== null) _clientProviders
= new ArrayList ();
850 return _clientProviders
;
854 public Hashtable CustomProperties
{
856 if (_customProperties
== null) _customProperties
= new Hashtable ();
857 return _customProperties
;
861 public void CopyFrom (ChannelData other
)
863 if (Ref
== null) Ref
= other
.Ref
;
864 if (Id
== null) Id
= other
.Id
;
865 if (Type
== null) Type
= other
.Type
;
866 if (DelayLoadAsClientChannel
== null) DelayLoadAsClientChannel
= other
.DelayLoadAsClientChannel
;
868 if (other
._customProperties
!= null)
870 foreach (DictionaryEntry entry
in other
._customProperties
)
871 if (!CustomProperties
.ContainsKey (entry
.Key
))
872 CustomProperties
[entry
.Key
] = entry
.Value
;
875 if (_serverProviders
== null && other
._serverProviders
!= null)
877 foreach (ProviderData prov
in other
._serverProviders
)
879 ProviderData np
= new ProviderData();
881 ServerProviders
.Add (np
);
885 if (_clientProviders
== null && other
._clientProviders
!= null)
887 foreach (ProviderData prov
in other
._clientProviders
)
889 ProviderData np
= new ProviderData();
891 ClientProviders
.Add (np
);
897 internal class ProviderData
{
899 internal string Type
;
902 internal Hashtable CustomProperties
= new Hashtable ();
903 internal IList CustomData
;
905 public void CopyFrom (ProviderData other
)
907 if (Ref
== null) Ref
= other
.Ref
;
908 if (Id
== null) Id
= other
.Id
;
909 if (Type
== null) Type
= other
.Type
;
911 foreach (DictionaryEntry entry
in other
.CustomProperties
)
912 if (!CustomProperties
.ContainsKey (entry
.Key
))
913 CustomProperties
[entry
.Key
] = entry
.Value
;
915 if (other
.CustomData
!= null)
917 if (CustomData
== null) CustomData
= new ArrayList ();
918 foreach (SinkProviderData data
in other
.CustomData
)
919 CustomData
.Add (data
);
924 internal class FormatterData
: ProviderData
{