2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Runtime.Remoting / RemotingConfiguration.cs
blob46e71422e04baf501f3327fe6cfa3d393355a068
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.Globalization;
35 using System.IO;
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;
41 using Mono.Xml;
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 ();
67 // public properties
68 // At this time the ID will be the application name
69 public static string ApplicationId
71 get
73 applicationID = ApplicationName;
74 return applicationID;
78 public static string ApplicationName
80 get { return applicationName; }
81 set { applicationName = value; }
84 [MonoTODO]
85 public static CustomErrorsModes CustomErrorsMode
87 get { throw new NotImplementedException (); }
88 set { throw new NotImplementedException (); }
91 public static string ProcessId
93 get {
94 if (processGuid == null)
95 processGuid = AppDomain.GetProcessGuid ();
97 return processGuid;
102 // public methods
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);
134 catch (Exception ex)
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);
161 return entries;
165 public static ActivatedServiceTypeEntry[] GetRegisteredActivatedServiceTypes ()
167 lock (channelTemplates)
169 ActivatedServiceTypeEntry[] entries = new ActivatedServiceTypeEntry[activatedServiceEntries.Count];
170 activatedServiceEntries.Values.CopyTo (entries,0);
171 return entries;
175 public static WellKnownClientTypeEntry[] GetRegisteredWellKnownClientTypes ()
177 lock (channelTemplates)
179 WellKnownClientTypeEntry[] entries = new WellKnownClientTypeEntry[wellKnownClientEntries.Count];
180 wellKnownClientEntries.Values.CopyTo (entries,0);
181 return entries;
185 public static WellKnownServiceTypeEntry[] GetRegisteredWellKnownServiceTypes ()
187 lock (channelTemplates)
189 WellKnownServiceTypeEntry[] entries = new WellKnownServiceTypeEntry[wellKnownServiceEntries.Count];
190 wellKnownServiceEntries.Values.CopyTo (entries,0);
191 return entries;
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")
316 continue;
318 if (defaultDelayedConfigRead && channel.DelayLoadAsClientChannel == "true")
319 continue;
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);
367 #if NET_1_1
368 public static bool CustomErrorsEnabled (bool isLocalRequest)
370 if (_errorMode == "off") return false;
371 if (_errorMode == "on") return true;
372 return !isLocalRequest;
374 #endif
376 internal static void SetCustomErrorsMode (string mode)
378 if (mode == null)
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);
387 _errorMode = m;
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;
404 string appName;
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;
427 else
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;
446 catch (Exception ex)
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);
457 return;
460 switch (name)
462 case "application":
463 ValidatePath (name, "system.runtime.remoting");
464 if (attrs.Names.Length > 0)
465 appName = attrs.Values[0];
466 break;
468 case "lifetime":
469 ValidatePath (name, "application");
470 ReadLifetine (attrs);
471 break;
473 case "channels":
474 ValidatePath (name, "system.runtime.remoting", "application");
475 break;
477 case "channel":
478 ValidatePath (name, "channels");
479 if (currentXmlPath.IndexOf ("application") != -1)
480 ReadChannel (attrs, false);
481 else
482 ReadChannel (attrs, true);
483 break;
485 case "serverProviders":
486 ValidatePath (name, "channelSinkProviders", "channel");
487 break;
489 case "clientProviders":
490 ValidatePath (name, "channelSinkProviders", "channel");
491 break;
493 case "provider":
494 case "formatter":
495 ProviderData prov;
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);
519 else
520 ValidatePath (name);
521 break;
523 case "client":
524 ValidatePath (name, "application");
525 currentClientUrl = attrs.GetValue ("url");
526 break;
528 case "service":
529 ValidatePath (name, "application");
530 break;
532 case "wellknown":
533 ValidatePath (name, "client", "service");
534 if (CheckPath ("client"))
535 ReadClientWellKnown (attrs);
536 else
537 ReadServiceWellKnown (attrs);
538 break;
540 case "activated":
541 ValidatePath (name, "client", "service");
542 if (CheckPath ("client"))
543 ReadClientActivated (attrs);
544 else
545 ReadServiceActivated (attrs);
546 break;
548 case "soapInterop":
549 ValidatePath (name, "application");
550 break;
552 case "interopXmlType":
553 ValidatePath (name, "soapInterop");
554 ReadInteropXml (attrs, false);
555 break;
557 case "interopXmlElement":
558 ValidatePath (name, "soapInterop");
559 ReadInteropXml (attrs, false);
560 break;
562 case "preLoad":
563 ValidatePath (name, "soapInterop");
564 ReadPreload (attrs);
565 break;
567 case "debug":
568 ValidatePath (name, "system.runtime.remoting");
569 break;
571 case "channelSinkProviders":
572 ValidatePath (name, "system.runtime.remoting");
573 break;
575 case "customErrors":
576 ValidatePath (name, "system.runtime.remoting");
577 RemotingConfiguration.SetCustomErrorsMode (attrs.GetValue ("mode"));
578 break;
580 default:
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]) {
613 case "leaseTime":
614 LifetimeServices.LeaseTime = ParseTime (attrs.GetValue(i));
615 break;
616 case "sponsorshipTimeout":
617 LifetimeServices.SponsorshipTimeout = ParseTime (attrs.GetValue(i));
618 break;
619 case "renewOnCallTime":
620 LifetimeServices.RenewOnCallTime = ParseTime (attrs.GetValue(i));
621 break;
622 case "leaseManagerPollTime":
623 LifetimeServices.LeaseManagerPollTime = ParseTime (attrs.GetValue(i));
624 break;
625 default:
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' });
637 string unit;
638 if (i == -1)
639 unit = "S";
640 else {
641 unit = s.Substring (i);
642 s = s.Substring (0,i);
644 double val;
646 try {
647 val = double.Parse (s);
649 catch {
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)
671 channel.Ref = val;
672 else if (at == "delayLoadAsClientChannel")
673 channel.DelayLoadAsClientChannel = val;
674 else if (at == "id" && isTemplate)
675 channel.Id = val;
676 else if (at == "type")
677 channel.Type = val;
678 else
679 channel.CustomProperties.Add (at, val);
682 if (isTemplate)
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);
688 else
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)
709 prov.Id = val;
710 else if (at == "type")
711 prov.Type = val;
712 else if (at == "ref" && !isTemplate)
713 prov.Ref = val;
714 else
715 prov.CustomProperties.Add (at, val);
718 if (prov.Id == null && isTemplate) throw new RemotingException ("id attribute is required");
719 return prov;
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");
784 if (type != null)
785 SoapServices.PreLoad (Type.GetType (type));
786 else if (assm != null)
787 SoapServices.PreLoad (Assembly.Load (assm));
788 else
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");
797 return value;
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();
807 return asm;
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 {
831 internal string Ref;
832 internal string Type;
833 internal string Id;
834 internal string DelayLoadAsClientChannel;
836 ArrayList _serverProviders = new ArrayList ();
837 ArrayList _clientProviders = new ArrayList ();
838 Hashtable _customProperties = new Hashtable ();
840 internal ArrayList ServerProviders {
841 get {
842 if (_serverProviders == null) _serverProviders = new ArrayList ();
843 return _serverProviders;
847 public ArrayList ClientProviders {
848 get {
849 if (_clientProviders == null) _clientProviders = new ArrayList ();
850 return _clientProviders;
854 public Hashtable CustomProperties {
855 get {
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();
880 np.CopyFrom (prov);
881 ServerProviders.Add (np);
885 if (_clientProviders == null && other._clientProviders != null)
887 foreach (ProviderData prov in other._clientProviders)
889 ProviderData np = new ProviderData();
890 np.CopyFrom (prov);
891 ClientProviders.Add (np);
897 internal class ProviderData {
898 internal string Ref;
899 internal string Type;
900 internal string Id;
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 {