|
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** File: RemotingConfigParser.cs
**
** Purpose: Parse remoting configuration files.
**
**
===========================================================*/
using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Globalization;
using System.Runtime.Versioning;
namespace System.Runtime.Remoting.Activation {
internal class RemotingXmlConfigFileData
{
// debug settings
internal static volatile bool LoadTypes = false; // indicates whether we should attempt to load types in config files
//
// configuration entry storage classes (in alphabetical order)
// There is one class for each type of entry in a remoting config file.
//
internal class ChannelEntry
{
internal String TypeName;
internal String AssemblyName;
internal Hashtable Properties;
internal bool DelayLoad = false;
internal ArrayList ClientSinkProviders = new ArrayList();
internal ArrayList ServerSinkProviders = new ArrayList();
internal ChannelEntry(String typeName, String assemblyName, Hashtable properties)
{
TypeName = typeName;
AssemblyName = assemblyName;
Properties = properties;
} // ChannelEntry
} // class ChannelEntry
internal class ClientWellKnownEntry
{
internal String TypeName;
internal String AssemblyName;
internal String Url;
internal ClientWellKnownEntry(String typeName, String assemName, String url)
{
TypeName = typeName;
AssemblyName = assemName;
Url = url;
}
} // class ClientWellKnownEntry
internal class ContextAttributeEntry
{
internal String TypeName;
internal String AssemblyName;
internal Hashtable Properties;
internal ContextAttributeEntry(String typeName, String assemName, Hashtable properties)
{
TypeName = typeName;
AssemblyName = assemName;
Properties = properties;
}
} // class ContextAttributeEntry
internal class InteropXmlElementEntry
{
internal String XmlElementName;
internal String XmlElementNamespace;
internal String UrtTypeName;
internal String UrtAssemblyName;
internal InteropXmlElementEntry(String xmlElementName, String xmlElementNamespace,
String urtTypeName, String urtAssemblyName)
{
XmlElementName = xmlElementName;
XmlElementNamespace = xmlElementNamespace;
UrtTypeName = urtTypeName;
UrtAssemblyName = urtAssemblyName;
}
} // class InteropXmlElementEntry
internal class CustomErrorsEntry {
internal CustomErrorsModes Mode;
internal CustomErrorsEntry(CustomErrorsModes mode) {
Mode = mode;
}
}
internal class InteropXmlTypeEntry
{
internal String XmlTypeName;
internal String XmlTypeNamespace;
internal String UrtTypeName;
internal String UrtAssemblyName;
internal InteropXmlTypeEntry(String xmlTypeName, String xmlTypeNamespace,
String urtTypeName, String urtAssemblyName)
{
XmlTypeName = xmlTypeName;
XmlTypeNamespace = xmlTypeNamespace;
UrtTypeName = urtTypeName;
UrtAssemblyName = urtAssemblyName;
}
} // class InteropXmlTypeEntry
internal class LifetimeEntry
{
// If any of these are false, then the corresponding property wasn't specified
// in the config file.
internal bool IsLeaseTimeSet = false;
internal bool IsRenewOnCallTimeSet = false;
internal bool IsSponsorshipTimeoutSet = false;
internal bool IsLeaseManagerPollTimeSet = false;
private TimeSpan _leaseTime;
private TimeSpan _renewOnCallTime;
private TimeSpan _sponsorshipTimeout;
private TimeSpan _leaseManagerPollTime;
internal TimeSpan LeaseTime {
get
{
BCLDebug.Assert(IsLeaseTimeSet == true, "LeaseTime not set");
return _leaseTime;
}
set
{
_leaseTime = value;
IsLeaseTimeSet = true;
}
}
internal TimeSpan RenewOnCallTime {
get
{
BCLDebug.Assert(IsRenewOnCallTimeSet == true, "RenewOnCallTime not set");
return _renewOnCallTime;
}
set
{
_renewOnCallTime = value;
IsRenewOnCallTimeSet = true;
}
}
internal TimeSpan SponsorshipTimeout {
get
{
BCLDebug.Assert(IsSponsorshipTimeoutSet == true, "SponsorShipTimeout not set");
return _sponsorshipTimeout;
}
set
{
_sponsorshipTimeout = value;
IsSponsorshipTimeoutSet = true;
}
}
internal TimeSpan LeaseManagerPollTime {
get
{
BCLDebug.Assert(IsLeaseManagerPollTimeSet == true, "LeaseManagerPollTime not set");
return _leaseManagerPollTime;
}
set
{
_leaseManagerPollTime = value;
IsLeaseManagerPollTimeSet = true;
}
}
} // class LifetimeEntry
internal class PreLoadEntry
{
// If TypeName is null, then all types in the assembly specified
// should be preloaded.
internal String TypeName;
internal String AssemblyName;
public PreLoadEntry(String typeName, String assemblyName)
{
TypeName = typeName;
AssemblyName = assemblyName;
}
} // class PreLoadEntry
internal class RemoteAppEntry
{
internal String AppUri;
internal ArrayList WellKnownObjects = new ArrayList();
internal ArrayList ActivatedObjects = new ArrayList();
internal RemoteAppEntry(String appUri)
{
AppUri = appUri;
}
internal void AddWellKnownEntry(String typeName, String assemName, String url)
{
ClientWellKnownEntry cwke = new ClientWellKnownEntry(typeName, assemName, url);
WellKnownObjects.Add(cwke);
}
internal void AddActivatedEntry(String typeName, String assemName,
ArrayList contextAttributes)
{
TypeEntry te = new TypeEntry(typeName, assemName, contextAttributes);
ActivatedObjects.Add(te);
}
} // class RemoteAppEntry
internal class ServerWellKnownEntry : TypeEntry
{
internal String ObjectURI;
internal WellKnownObjectMode ObjectMode;
internal ServerWellKnownEntry(
String typeName, String assemName, ArrayList contextAttributes,
String objURI, WellKnownObjectMode objMode) :
base(typeName, assemName, contextAttributes)
{
ObjectURI = objURI;
ObjectMode = objMode;
}
} // class ServerWellKnownEntry
internal class SinkProviderEntry
{
internal String TypeName;
internal String AssemblyName;
internal Hashtable Properties;
internal ArrayList ProviderData = new ArrayList(); // array of SinkProviderData structures
internal bool IsFormatter; // Is this a formatter sink provider?
internal SinkProviderEntry(String typeName, String assemName, Hashtable properties,
bool isFormatter)
{
TypeName = typeName;
AssemblyName = assemName;
Properties = properties;
IsFormatter = isFormatter;
}
} // class SinkProviderEntry
internal class TypeEntry
{
internal String TypeName;
internal String AssemblyName;
internal ArrayList ContextAttributes;
internal TypeEntry(String typeName, String assemName,
ArrayList contextAttributes)
{
TypeName = typeName;
AssemblyName = assemName;
ContextAttributes = contextAttributes;
}
} // class TypeEntry
//
// end of configuration entry storage classes
//
//
// configuration data access
//
internal String ApplicationName = null; // application name
internal LifetimeEntry Lifetime = null; // corresponds to top-level lifetime element
internal bool UrlObjRefMode = RemotingConfigHandler.UrlObjRefMode; // should url obj ref's be used?
internal CustomErrorsEntry CustomErrors = null;
internal ArrayList ChannelEntries = new ArrayList();
internal ArrayList InteropXmlElementEntries = new ArrayList();
internal ArrayList InteropXmlTypeEntries = new ArrayList();
internal ArrayList PreLoadEntries = new ArrayList();
internal ArrayList RemoteAppEntries = new ArrayList();
internal ArrayList ServerActivatedEntries = new ArrayList();
internal ArrayList ServerWellKnownEntries = new ArrayList();
//
// end of configuration data access
//
//
// modify configuration data (for multiple entry entities)
//
internal void AddInteropXmlElementEntry(String xmlElementName, String xmlElementNamespace,
String urtTypeName, String urtAssemblyName)
{
TryToLoadTypeIfApplicable(urtTypeName, urtAssemblyName);
InteropXmlElementEntry ixee = new InteropXmlElementEntry(
xmlElementName, xmlElementNamespace, urtTypeName, urtAssemblyName);
InteropXmlElementEntries.Add(ixee);
}
internal void AddInteropXmlTypeEntry(String xmlTypeName, String xmlTypeNamespace,
String urtTypeName, String urtAssemblyName)
{
TryToLoadTypeIfApplicable(urtTypeName, urtAssemblyName);
InteropXmlTypeEntry ixte = new InteropXmlTypeEntry(xmlTypeName, xmlTypeNamespace,
urtTypeName, urtAssemblyName);
InteropXmlTypeEntries.Add(ixte);
}
internal void AddPreLoadEntry(String typeName, String assemblyName)
{
TryToLoadTypeIfApplicable(typeName, assemblyName);
PreLoadEntry ple = new PreLoadEntry(typeName, assemblyName);
PreLoadEntries.Add(ple);
}
internal RemoteAppEntry AddRemoteAppEntry(String appUri)
{
RemoteAppEntry rae = new RemoteAppEntry(appUri);
RemoteAppEntries.Add(rae);
return rae;
}
internal void AddServerActivatedEntry(String typeName, String assemName,
ArrayList contextAttributes)
{
TryToLoadTypeIfApplicable(typeName, assemName);
TypeEntry te = new TypeEntry(typeName, assemName, contextAttributes);
ServerActivatedEntries.Add(te);
}
internal ServerWellKnownEntry AddServerWellKnownEntry(String typeName, String assemName,
ArrayList contextAttributes, String objURI, WellKnownObjectMode objMode)
{
TryToLoadTypeIfApplicable(typeName, assemName);
ServerWellKnownEntry swke = new ServerWellKnownEntry(typeName, assemName,
contextAttributes, objURI, objMode);
ServerWellKnownEntries.Add(swke);
return swke;
}
// debug settings helper
private void TryToLoadTypeIfApplicable(String typeName, String assemblyName)
{
if (!LoadTypes)
return;
Assembly asm = Assembly.Load(assemblyName);
if (asm == null)
{
throw new RemotingException(
Environment.GetResourceString("Remoting_AssemblyLoadFailed",
assemblyName));
}
Type type = asm.GetType(typeName, false, false);
if (type == null)
{
throw new RemotingException(
Environment.GetResourceString("Remoting_BadType",
typeName));
}
}
} // RemotingXmlConfigFileData
internal static class RemotingXmlConfigFileParser
{
// template arrays
private static Hashtable _channelTemplates = CreateSyncCaseInsensitiveHashtable();
private static Hashtable _clientChannelSinkTemplates = CreateSyncCaseInsensitiveHashtable();
private static Hashtable _serverChannelSinkTemplates = CreateSyncCaseInsensitiveHashtable();
private static Hashtable CreateSyncCaseInsensitiveHashtable()
{
return Hashtable.Synchronized(CreateCaseInsensitiveHashtable());
}
private static Hashtable CreateCaseInsensitiveHashtable()
{
return new Hashtable(StringComparer.InvariantCultureIgnoreCase);
}
public static RemotingXmlConfigFileData ParseDefaultConfiguration() {
ConfigNode node;
// <system.runtime.remoting>
ConfigNode rootNode = new ConfigNode("system.runtime.remoting", null);
/*
<application>
<channels>
<channel ref="http client" displayName="http client (delay loaded)" delayLoadAsClientChannel="true" />
<channel ref="tcp client" displayName="tcp client (delay loaded)" delayLoadAsClientChannel="true" />
<channel ref="ipc client" displayName="ipc client (delay loaded)" delayLoadAsClientChannel="true" />
</channels>
</application>
*/
ConfigNode appNode = new ConfigNode("application", rootNode);
rootNode.Children.Add(appNode);
ConfigNode channelsNode = new ConfigNode("channels", appNode);
appNode.Children.Add(channelsNode);
node = new ConfigNode("channel", appNode);
node.Attributes.Add(new DictionaryEntry("ref", "http client"));
node.Attributes.Add(new DictionaryEntry("displayName", "http client (delay loaded)"));
node.Attributes.Add(new DictionaryEntry("delayLoadAsClientChannel", "true"));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", appNode);
node.Attributes.Add(new DictionaryEntry("ref", "tcp client"));
node.Attributes.Add(new DictionaryEntry("displayName", "tcp client (delay loaded)"));
node.Attributes.Add(new DictionaryEntry("delayLoadAsClientChannel", "true"));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", appNode);
node.Attributes.Add(new DictionaryEntry("ref", "ipc client"));
node.Attributes.Add(new DictionaryEntry("displayName", "ipc client (delay loaded)"));
node.Attributes.Add(new DictionaryEntry("delayLoadAsClientChannel", "true"));
channelsNode.Children.Add(node);
/*
<channels>
<channel id="http" type="System.Runtime.Remoting.Channels.Http.HttpChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<channel id="http client" type="System.Runtime.Remoting.Channels.Http.HttpClientChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<channel id="http server" type="System.Runtime.Remoting.Channels.Http.HttpServerChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<channel id="tcp" type="System.Runtime.Remoting.Channels.Tcp.TcpChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<channel id="tcp client" type="System.Runtime.Remoting.Channels.Tcp.TcpClientChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<channel id="tcp server" type="System.Runtime.Remoting.Channels.Tcp.TcpServerChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<channel id="ipc" type="System.Runtime.Remoting.Channels.Ipc.IpcChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<channel id="ipc client" type="System.Runtime.Remoting.Channels.Ipc.IpcClientChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<channel id="ipc server" type="System.Runtime.Remoting.Channels.Ipc.IpcServerChannel, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</channels>
*/
channelsNode = new ConfigNode("channels", rootNode);
rootNode.Children.Add(channelsNode);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "http"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Http.HttpChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "http client"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Http.HttpClientChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "http server"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Http.HttpServerChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "tcp"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Tcp.TcpChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "tcp client"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Tcp.TcpClientChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "tcp server"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Tcp.TcpServerChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "ipc"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Ipc.IpcChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "ipc client"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Ipc.IpcClientChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
node = new ConfigNode("channel", channelsNode);
node.Attributes.Add(new DictionaryEntry("id", "ipc server"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.Ipc.IpcServerChannel, " + AssemblyRef.SystemRuntimeRemoting));
channelsNode.Children.Add(node);
/*
<channelSinkProviders>
<clientProviders>
<formatter id="soap" type="System.Runtime.Remoting.Channels.SoapClientFormatterSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<formatter id="binary" type="System.Runtime.Remoting.Channels.BinaryClientFormatterSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</clientProviders>
<serverProviders>
<formatter id="soap" type="System.Runtime.Remoting.Channels.SoapServerFormatterSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<formatter id="binary" type="System.Runtime.Remoting.Channels.BinaryServerFormatterSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<provider id="wsdl" type="System.Runtime.Remoting.MetadataServices.SdlChannelSinkProvider, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</serverProviders>
</channelSinkProviders>
*/
ConfigNode channelsSinkNode = new ConfigNode("channelSinkProviders", rootNode);
rootNode.Children.Add(channelsSinkNode);
ConfigNode clientProvidersNode = new ConfigNode("clientProviders", channelsSinkNode);
channelsSinkNode.Children.Add(clientProvidersNode);
node = new ConfigNode("formatter", clientProvidersNode);
node.Attributes.Add(new DictionaryEntry("id", "soap"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.SoapClientFormatterSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
clientProvidersNode.Children.Add(node);
node = new ConfigNode("formatter", clientProvidersNode);
node.Attributes.Add(new DictionaryEntry("id", "binary"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.BinaryClientFormatterSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
clientProvidersNode.Children.Add(node);
ConfigNode serverProvidersNode = new ConfigNode("serverProviders", channelsSinkNode);
channelsSinkNode.Children.Add(serverProvidersNode);
node = new ConfigNode("formatter", serverProvidersNode);
node.Attributes.Add(new DictionaryEntry("id", "soap"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.SoapServerFormatterSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
serverProvidersNode.Children.Add(node);
node = new ConfigNode("formatter", serverProvidersNode);
node.Attributes.Add(new DictionaryEntry("id", "binary"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.Channels.BinaryServerFormatterSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
serverProvidersNode.Children.Add(node);
node = new ConfigNode("provider", serverProvidersNode);
node.Attributes.Add(new DictionaryEntry("id", "wsdl"));
node.Attributes.Add(new DictionaryEntry("type", "System.Runtime.Remoting.MetadataServices.SdlChannelSinkProvider, " + AssemblyRef.SystemRuntimeRemoting));
serverProvidersNode.Children.Add(node);
return ParseConfigNode(rootNode);
}
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
public static RemotingXmlConfigFileData ParseConfigFile(String filename)
{
ConfigTreeParser parser = new ConfigTreeParser();
ConfigNode rootNode = parser.Parse(filename, "/configuration/system.runtime.remoting");
return ParseConfigNode(rootNode);
}
private static RemotingXmlConfigFileData ParseConfigNode(ConfigNode rootNode)
{
RemotingXmlConfigFileData configData = new RemotingXmlConfigFileData();
// check to see if this file has a system.runtime.remoting section
if (rootNode == null)
return null;
// process attributes
foreach (DictionaryEntry entry in rootNode.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "version":
{
// we ignore the version attribute because this may be used
// by the configuration system
break;
}
default: break;
} // switch
} // foreach
ConfigNode appNode = null; // "application" node
ConfigNode channelsNode = null; // "channels" node
ConfigNode providerNode = null; // "channelSinkProviders" node
ConfigNode debugNode = null; // "debug" node
ConfigNode customErrorsNode = null; // "customErrors" node
foreach (ConfigNode node in rootNode.Children)
{
switch (node.Name)
{
case "application":
{
// there can only be one application node in a config file
if (appNode != null)
ReportUniqueSectionError(rootNode, appNode, configData);
appNode = node;
break;
} // case "application"
case "channels":
{
if (channelsNode != null)
ReportUniqueSectionError(rootNode, channelsNode, configData);
channelsNode = node;
break;
} // case "channels"
case "channelSinkProviders":
{
if (providerNode != null)
ReportUniqueSectionError(rootNode, providerNode, configData);
providerNode = node;
break;
} // case "channelSinkProviders"
case "debug":
{
if (debugNode != null)
ReportUniqueSectionError(rootNode, debugNode, configData);
debugNode = node;
break;
} // case "debug"
case "customErrors":
{
if (customErrorsNode != null)
ReportUniqueSectionError(rootNode, customErrorsNode, configData);
customErrorsNode = node;
break;
}// case "customErrors"
default: break;
} // switch
} // foreach
if (debugNode != null)
ProcessDebugNode(debugNode, configData);
if (providerNode != null)
ProcessChannelSinkProviderTemplates(providerNode, configData);
if (channelsNode != null)
ProcessChannelTemplates(channelsNode, configData);
if (appNode != null)
ProcessApplicationNode(appNode, configData);
if (customErrorsNode != null)
ProcessCustomErrorsNode(customErrorsNode, configData);
return configData;
} // ParseConfigFile
private static void ReportError(String errorStr, RemotingXmlConfigFileData configData)
{
// <
throw new RemotingException(errorStr);
} // ReportError
// means section must be unique
private static void ReportUniqueSectionError(ConfigNode parent, ConfigNode child,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_NodeMustBeUnique"),
child.Name, parent.Name),
configData);
} // ReportUniqueSectionError
private static void ReportUnknownValueError(ConfigNode node, String value,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_UnknownValue"),
node.Name, value),
configData);
} // ReportUnknownValueError
private static void ReportMissingAttributeError(ConfigNode node, String attributeName,
RemotingXmlConfigFileData configData)
{
ReportMissingAttributeError(node.Name, attributeName, configData);
} // ReportMissingAttributeError
private static void ReportMissingAttributeError(String nodeDescription, String attributeName,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_RequiredXmlAttribute"),
nodeDescription, attributeName),
configData);
} // ReportMissingAttributeError
private static void ReportMissingTypeAttributeError(ConfigNode node, String attributeName,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_MissingTypeAttribute"),
node.Name, attributeName),
configData);
} // ReportMissingAttributeError
private static void ReportMissingXmlTypeAttributeError(ConfigNode node, String attributeName,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_MissingXmlTypeAttribute"),
node.Name, attributeName),
configData);
} // ReportMissingAttributeError
private static void ReportInvalidTimeFormatError(String time,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_InvalidTimeFormat"),
time),
configData);
} // ReportInvalidTypeFormatError
// If nodes can be represented as a template, only a template version
// can have an 'id' attribute
private static void ReportNonTemplateIdAttributeError(ConfigNode node,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_NonTemplateIdAttribute"),
node.Name),
configData);
} // ReportNonTemplateIdAttributeError
private static void ReportTemplateCannotReferenceTemplateError(
ConfigNode node,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_TemplateCannotReferenceTemplate"),
node.Name),
configData);
} // ReportTemplateCannotReferenceTemplateError
private static void ReportUnableToResolveTemplateReferenceError(
ConfigNode node, String referenceName,
RemotingXmlConfigFileData configData)
{
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_UnableToResolveTemplate"),
node.Name, referenceName),
configData);
} // ReportUnableToResolveTemplateReferenceError
private static void ReportAssemblyVersionInfoPresent(
String assemName, String entryDescription,
RemotingXmlConfigFileData configData)
{
// for some entries, version information is not allowed in the assembly name
ReportError(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_VersionPresent"),
assemName, entryDescription),
configData);
} // ReportAssemblyVersionInfoPresent
private static void ProcessDebugNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "loadTypes":
RemotingXmlConfigFileData.LoadTypes =
Convert.ToBoolean((String)entry.Value, CultureInfo.InvariantCulture);
break;
default: break;
} // switch
} // foreach
} // ProcessDebugNode
private static void ProcessApplicationNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
if (key.Equals("name"))
configData.ApplicationName = (String)entry.Value;
}
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "channels": ProcessChannelsNode(childNode, configData); break;
case "client": ProcessClientNode(childNode, configData); break;
case "lifetime": ProcessLifetimeNode(node, childNode, configData); break;
case "service": ProcessServiceNode(childNode, configData); break;
case "soapInterop": ProcessSoapInteropNode(childNode, configData); break;
default: break;
} // switch
} // foreach
} // ProcessApplicationNode
private static void ProcessCustomErrorsNode(ConfigNode node, RemotingXmlConfigFileData configData) {
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
if (key.Equals("mode")) {
string value = (string)entry.Value;
CustomErrorsModes mode = CustomErrorsModes.On;
if (String.Compare(value, "on", StringComparison.OrdinalIgnoreCase) == 0)
mode = CustomErrorsModes.On;
else if (String.Compare(value, "off", StringComparison.OrdinalIgnoreCase) == 0)
mode = CustomErrorsModes.Off;
else if (String.Compare(value, "remoteonly", StringComparison.OrdinalIgnoreCase) == 0)
mode = CustomErrorsModes.RemoteOnly;
else
ReportUnknownValueError(node, value, configData);
configData.CustomErrors = new RemotingXmlConfigFileData.CustomErrorsEntry(mode);
}
}
}
private static void ProcessLifetimeNode(ConfigNode parentNode, ConfigNode node, RemotingXmlConfigFileData configData)
{
if (configData.Lifetime != null)
ReportUniqueSectionError(node, parentNode, configData);
configData.Lifetime = new RemotingXmlConfigFileData.LifetimeEntry();
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "leaseTime":
configData.Lifetime.LeaseTime = ParseTime((String)entry.Value, configData);
break;
case "sponsorshipTimeout":
configData.Lifetime.SponsorshipTimeout = ParseTime((String)entry.Value, configData);
break;
case "renewOnCallTime":
configData.Lifetime.RenewOnCallTime = ParseTime((String)entry.Value, configData);
break;
case "leaseManagerPollTime":
configData.Lifetime.LeaseManagerPollTime = ParseTime((String)entry.Value, configData);
break;
default: break;
} // switch
} // foreach
} // ProcessLifetimeNode
// appears under "application"
private static void ProcessServiceNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "wellknown": ProcessServiceWellKnownNode(childNode, configData); break;
case "activated": ProcessServiceActivatedNode(childNode, configData); break;
default: break;
} // switch
} // foreach
} // ProcessServiceNode
// appears under "application"
private static void ProcessClientNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
String remoteAppUri = null;
// process attributes
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "url": remoteAppUri = (String)entry.Value; break;
case "displayName": break; // displayName is ignored (used by config utility for labelling the application)
default: break;
} // switch
} // foreach attribute
RemotingXmlConfigFileData.RemoteAppEntry remoteApp =
configData.AddRemoteAppEntry(remoteAppUri);
// process child nodes
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "wellknown": ProcessClientWellKnownNode(childNode, configData, remoteApp); break;
case "activated": ProcessClientActivatedNode(childNode, configData, remoteApp); break;
default: break;
} // switch
} // foreach child node
// if there are any activated entries, we require a remote app url.
if ((remoteApp.ActivatedObjects.Count > 0) && (remoteAppUri == null))
ReportMissingAttributeError(node, "url", configData);
} // ProcessClientNode
// appears under "application"
private static void ProcessSoapInteropNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
// process attributes
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "urlObjRef":
{
configData.UrlObjRefMode = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
break;
}
default: break;
} // switch
} // foreach attribute
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "preLoad": ProcessPreLoadNode(childNode, configData); break;
case "interopXmlElement": ProcessInteropXmlElementNode(childNode, configData); break;
case "interopXmlType": ProcessInteropXmlTypeNode(childNode, configData); break;
default: break;
} // switch
}
} // ProcessSoapInteropNode
// appears under "application"
private static void ProcessChannelsNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
foreach (ConfigNode childNode in node.Children)
{
if (childNode.Name.Equals("channel"))
{
RemotingXmlConfigFileData.ChannelEntry channelEntry =
ProcessChannelsChannelNode(childNode, configData, false);
configData.ChannelEntries.Add(channelEntry);
}
} // foreach
} // ProcessInteropNode
// appears under "application/service"
private static void ProcessServiceWellKnownNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
String typeName = null;
String assemName = null;
ArrayList contextAttributes = new ArrayList();
String objectURI = null;
WellKnownObjectMode objectMode = WellKnownObjectMode.Singleton;
bool objectModeFound = false;
// examine attributes
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "displayName": break; // displayName is ignored (used by config utility for labelling the application)
case "mode":
{
String value = (String)entry.Value;
objectModeFound = true;
if (String.CompareOrdinal(value, "Singleton") == 0)
objectMode = WellKnownObjectMode.Singleton;
else
if (String.CompareOrdinal(value, "SingleCall") == 0)
objectMode = WellKnownObjectMode.SingleCall;
else
objectModeFound = false;
break;
} // case "mode"
case "objectUri": objectURI = (String)entry.Value; break;
case "type":
{
RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
break;
} // case "type"
default: break;
} // switch
} // foreach
// examine child nodes
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "contextAttribute":
{
contextAttributes.Add(ProcessContextAttributeNode(childNode, configData));
break;
} // case "contextAttribute"
case "lifetime":
{
// <
break;
} // case "lifetime"
default: break;
} // switch
} // foreach child node
// check for errors
if (!objectModeFound)
{
ReportError(
Environment.GetResourceString("Remoting_Config_MissingWellKnownModeAttribute"),
configData);
}
if ((typeName == null) || (assemName == null))
ReportMissingTypeAttributeError(node, "type", configData);
// objectURI defaults to typeName if not specified
if (objectURI == null)
objectURI = typeName + ".soap";
configData.AddServerWellKnownEntry(typeName, assemName, contextAttributes,
objectURI, objectMode);
} // ProcessServiceWellKnownNode
// appears under "application/service"
private static void ProcessServiceActivatedNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
String typeName = null;
String assemName = null;
ArrayList contextAttributes = new ArrayList();
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "type":
{
RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
break;
} // case "type"
default: break;
} // switch
} // foreach attribute
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "contextAttribute":
{
contextAttributes.Add(ProcessContextAttributeNode(childNode, configData));
break;
} // case "contextattribute"
case "lifetime":
{
// <
break;
} // case "lifetime"
default: break;
} // switch
} // foreach child node
// check for errors
if ((typeName == null) || (assemName == null))
ReportMissingTypeAttributeError(node, "type", configData);
if (CheckAssemblyNameForVersionInfo(assemName))
ReportAssemblyVersionInfoPresent(assemName, "service activated", configData);
configData.AddServerActivatedEntry(typeName, assemName, contextAttributes);
} // ProcessServiceActivatedNode
// appears under "application/client"
private static void ProcessClientWellKnownNode(ConfigNode node, RemotingXmlConfigFileData configData,
RemotingXmlConfigFileData.RemoteAppEntry remoteApp)
{
String typeName = null;
String assemName = null;
String url = null;
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "displayName": break; // displayName is ignored (used by config utility for labelling the application)
case "type":
{
RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
break;
} // case "type"
case "url": url = (String)entry.Value; break;
default: break;
} // switch
} // foreach
// check for errors
if (url == null)
ReportMissingAttributeError("WellKnown client", "url", configData);
if ((typeName == null) || (assemName == null))
ReportMissingTypeAttributeError(node, "type", configData);
if (CheckAssemblyNameForVersionInfo(assemName))
ReportAssemblyVersionInfoPresent(assemName, "client wellknown", configData);
remoteApp.AddWellKnownEntry(typeName, assemName, url);
} // ProcessClientWellKnownNode
// appears under "application/client"
private static void ProcessClientActivatedNode(ConfigNode node, RemotingXmlConfigFileData configData,
RemotingXmlConfigFileData.RemoteAppEntry remoteApp)
{
String typeName = null;
String assemName = null;
ArrayList contextAttributes = new ArrayList();
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "type":
{
RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
break;
} // case "type"
default: break;
} // switch
} // foreach
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "contextAttribute":
{
contextAttributes.Add(ProcessContextAttributeNode(childNode, configData));
break;
} // case "contextAttribute"
default: break;
} // switch
} // foreach child node
// check for errors
if ((typeName == null) || (assemName == null))
ReportMissingTypeAttributeError(node, "type", configData);
remoteApp.AddActivatedEntry(typeName, assemName, contextAttributes);
} // ProcessClientActivatedNode
private static void ProcessInteropXmlElementNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
String xmlElementName = null;
String xmlElementNamespace = null;
String urtTypeName = null;
String urtAssemName = null;
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "xml":
{
RemotingConfigHandler.ParseType((String)entry.Value, out xmlElementName, out xmlElementNamespace);
break;
}
case "clr":
{
RemotingConfigHandler.ParseType((String)entry.Value, out urtTypeName, out urtAssemName);
break;
} // case "clr"
default: break;
} // switch
} // foreach
// check for errors
if ((xmlElementName == null) || (xmlElementNamespace == null))
ReportMissingXmlTypeAttributeError(node, "xml", configData);
if ((urtTypeName == null) || (urtAssemName == null))
ReportMissingTypeAttributeError(node, "clr", configData);
configData.AddInteropXmlElementEntry(xmlElementName, xmlElementNamespace,
urtTypeName, urtAssemName);
} // ProcessInteropNode
private static void ProcessInteropXmlTypeNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
String xmlTypeName = null;
String xmlTypeNamespace = null;
String urtTypeName = null;
String urtAssemName = null;
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "xml":
{
RemotingConfigHandler.ParseType((String)entry.Value, out xmlTypeName, out xmlTypeNamespace);
break;
}
case "clr":
{
RemotingConfigHandler.ParseType((String)entry.Value, out urtTypeName, out urtAssemName);
break;
} // case "type"
default: break;
} // switch
} // foreach
// check for errors
if ((xmlTypeName == null) || (xmlTypeNamespace == null))
ReportMissingXmlTypeAttributeError(node, "xml", configData);
if ((urtTypeName == null) || (urtAssemName == null))
ReportMissingTypeAttributeError(node, "clr", configData);
configData.AddInteropXmlTypeEntry(xmlTypeName, xmlTypeNamespace,
urtTypeName, urtAssemName);
} // ProcessInteropNode
private static void ProcessPreLoadNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
String typeName = null;
String assemblyName = null;
foreach (DictionaryEntry entry in node.Attributes)
{
String key = entry.Key.ToString();
switch (key)
{
case "type":
{
RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemblyName);
break;
}
case "assembly":
{
assemblyName = (String)entry.Value;
break;
} // case "type"
default: break;
} // switch
} // foreach
// check for errors
if (assemblyName == null)
{
ReportError(
Environment.GetResourceString("Remoting_Config_PreloadRequiresTypeOrAssembly"),
configData);
}
configData.AddPreLoadEntry(typeName, assemblyName);
} // ProcessPreLoadNode
private static RemotingXmlConfigFileData.ContextAttributeEntry
ProcessContextAttributeNode(ConfigNode node, RemotingXmlConfigFileData configData)
{
String typeName = null;
String assemName = null;
Hashtable properties = CreateCaseInsensitiveHashtable();
// examine attributes
foreach (DictionaryEntry entry in node.Attributes)
{
String lowercaseKey = ((String)entry.Key).ToLower(CultureInfo.InvariantCulture);
switch (lowercaseKey)
{
case "type":
{
RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
break;
} // case "type"
default:
properties[lowercaseKey] = entry.Value;
break;
} // switch
} // foreach attribute
// check for errors
if ((typeName == null) || (assemName == null))
ReportMissingTypeAttributeError(node, "type", configData);
RemotingXmlConfigFileData.ContextAttributeEntry attributeEntry =
new RemotingXmlConfigFileData.ContextAttributeEntry(
typeName, assemName, properties);
return attributeEntry;
} // ProcessContextAttributeNode
// appears under "application/client"
private static RemotingXmlConfigFileData.ChannelEntry
ProcessChannelsChannelNode(ConfigNode node, RemotingXmlConfigFileData configData,
bool isTemplate)
{
String id = null;
String typeName = null;
String assemName = null;
Hashtable properties = CreateCaseInsensitiveHashtable();
bool delayLoad = false;
RemotingXmlConfigFileData.ChannelEntry channelTemplate = null;
// examine attributes
foreach (DictionaryEntry entry in node.Attributes)
{
String keyStr = (String)entry.Key;
switch (keyStr)
{
case "displayName": break; // displayName is ignored (used by config utility for labelling the application)
case "id":
{
if (!isTemplate)
{
ReportNonTemplateIdAttributeError(node, configData);
}
else
id = ((String)entry.Value).ToLower(CultureInfo.InvariantCulture);
break;
} // case "id"
case "ref":
{
if (isTemplate)
{
ReportTemplateCannotReferenceTemplateError(node, configData);
}
else
{
channelTemplate =
(RemotingXmlConfigFileData.ChannelEntry)_channelTemplates[entry.Value];
if (channelTemplate == null)
{
ReportUnableToResolveTemplateReferenceError(
node, entry.Value.ToString(), configData);
}
else
{
// load template data
typeName = channelTemplate.TypeName;
assemName = channelTemplate.AssemblyName;
foreach (DictionaryEntry param in channelTemplate.Properties)
{
properties[param.Key] = param.Value;
}
}
}
break;
} // case "ref"
case "type":
{
RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
break;
} // case "type"
case "delayLoadAsClientChannel":
{
delayLoad = Convert.ToBoolean((String)entry.Value, CultureInfo.InvariantCulture);
break;
} // case "delayLoadAsClientChannel"
default:
properties[keyStr] = entry.Value;
break;
} // switch
} // foreach attribute
// check for errors
if ((typeName == null) || (assemName == null))
ReportMissingTypeAttributeError(node, "type", configData);
RemotingXmlConfigFileData.ChannelEntry channelEntry =
new RemotingXmlConfigFileData.ChannelEntry(typeName, assemName, properties);
channelEntry.DelayLoad = delayLoad;
// look for sink providers
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "clientProviders":
ProcessSinkProviderNodes(childNode, channelEntry, configData, false);
break;
case "serverProviders":
ProcessSinkProviderNodes(childNode, channelEntry, configData, true);
break;
default: break;
} // switch
} // foreach
// if we reference a template and didn't specify any sink providers, we
// should copy over the providers from the template
if (channelTemplate != null)
{
// <
if (channelEntry.ClientSinkProviders.Count == 0)
{
channelEntry.ClientSinkProviders = channelTemplate.ClientSinkProviders;
}
if (channelEntry.ServerSinkProviders.Count == 0)
{
channelEntry.ServerSinkProviders = channelTemplate.ServerSinkProviders;
}
}
if (isTemplate)
{
_channelTemplates[id] = channelEntry;
return null;
}
else
{
return channelEntry;
}
} // ProcessChannelsChannelNode
//
// process sink provider data
//
private static void ProcessSinkProviderNodes(ConfigNode node,
RemotingXmlConfigFileData.ChannelEntry channelEntry, RemotingXmlConfigFileData configData,
bool isServer)
{
// look for sink providers
foreach (ConfigNode childNode in node.Children)
{
RemotingXmlConfigFileData.SinkProviderEntry entry =
ProcessSinkProviderNode(childNode, configData, false, isServer);
if (isServer)
channelEntry.ServerSinkProviders.Add(entry);
else
channelEntry.ClientSinkProviders.Add(entry);
} // foreach
} // ProcessSinkProviderNodes
private static RemotingXmlConfigFileData.SinkProviderEntry
ProcessSinkProviderNode(ConfigNode node, RemotingXmlConfigFileData configData,
bool isTemplate, bool isServer)
{
bool isFormatter = false;
// Make sure the node is a "formatter" or "provider".
String nodeName = node.Name;
if (nodeName.Equals("formatter"))
isFormatter = true;
else
if (nodeName.Equals("provider"))
isFormatter = false;
else
{
ReportError(
Environment.GetResourceString("Remoting_Config_ProviderNeedsElementName"),
configData);
}
String id = null;
String typeName = null;
String assemName = null;
Hashtable properties = CreateCaseInsensitiveHashtable();
RemotingXmlConfigFileData.SinkProviderEntry template = null;
foreach (DictionaryEntry entry in node.Attributes)
{
String keyStr = (String)entry.Key;
switch (keyStr)
{
case "id":
{
if (!isTemplate)
{
// only templates can have the id attribute
ReportNonTemplateIdAttributeError(node, configData);
}
else
id = (String)entry.Value;
break;
} // case "id"
case "ref":
{
if (isTemplate)
{
ReportTemplateCannotReferenceTemplateError(node, configData);
}
else
{
if (isServer)
{
template = (RemotingXmlConfigFileData.SinkProviderEntry)
_serverChannelSinkTemplates[entry.Value];
}
else
{
template = (RemotingXmlConfigFileData.SinkProviderEntry)
_clientChannelSinkTemplates[entry.Value];
}
if (template == null)
{
ReportUnableToResolveTemplateReferenceError(
node, entry.Value.ToString(), configData);
}
else
{
// load template data
typeName = template.TypeName;
assemName = template.AssemblyName;
foreach (DictionaryEntry param in template.Properties)
{
properties[param.Key] = param.Value;
}
}
}
break;
} // case "ref"
case "type":
{
RemotingConfigHandler.ParseType((String)entry.Value, out typeName, out assemName);
break;
} // case "type"
default:
properties[keyStr] = entry.Value;
break;
} // switch
} // foreach attribute
// check for errors
if ((typeName == null) || (assemName == null))
ReportMissingTypeAttributeError(node, "type", configData);
RemotingXmlConfigFileData.SinkProviderEntry sinkProviderEntry =
new RemotingXmlConfigFileData.SinkProviderEntry(typeName, assemName, properties,
isFormatter);
// start storing sink data
foreach (ConfigNode childNode in node.Children)
{
SinkProviderData providerData =
ProcessSinkProviderData(childNode, configData);
sinkProviderEntry.ProviderData.Add(providerData);
} // foreach
// if we reference a template and didn't specify any provider data, we
// should copy over the provider data from the template
if (template != null)
{
// <
if (sinkProviderEntry.ProviderData.Count == 0)
{
sinkProviderEntry.ProviderData = template.ProviderData;
}
}
if (isTemplate)
{
if (isServer)
_serverChannelSinkTemplates[id] = sinkProviderEntry;
else
_clientChannelSinkTemplates[id] = sinkProviderEntry;
return null;
}
else
{
return sinkProviderEntry;
}
} // ProcessSinkProviderNode
// providerData will already contain an object with the same name as the config node
private static SinkProviderData ProcessSinkProviderData(ConfigNode node,
RemotingXmlConfigFileData configData)
{
SinkProviderData providerData = new SinkProviderData(node.Name);
foreach (ConfigNode childNode in node.Children)
{
SinkProviderData childData = ProcessSinkProviderData(childNode, configData);
providerData.Children.Add(childData);
}
foreach (DictionaryEntry entry in node.Attributes)
{
providerData.Properties[entry.Key] = entry.Value;
}
return providerData;
} // ProcessSinkProviderData
//
// process template nodes
//
private static void ProcessChannelTemplates(ConfigNode node, RemotingXmlConfigFileData configData)
{
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "channel": ProcessChannelsChannelNode(childNode, configData, true); break;
default: break;
} // switch
}
} // ProcessChannelTemplates
private static void ProcessChannelSinkProviderTemplates(ConfigNode node, RemotingXmlConfigFileData configData)
{
foreach (ConfigNode childNode in node.Children)
{
switch (childNode.Name)
{
case "clientProviders": ProcessChannelProviderTemplates(childNode, configData, false); break;
case "serverProviders": ProcessChannelProviderTemplates(childNode, configData, true); break;
default: break;
}
}
} // ProcessChannelSinkProviderTemplates
private static void ProcessChannelProviderTemplates(ConfigNode node, RemotingXmlConfigFileData configData,
bool isServer)
{
foreach (ConfigNode childNode in node.Children)
{
ProcessSinkProviderNode(childNode, configData, true, isServer);
}
} // ProcessClientProviderTemplates
// assembly names aren't supposed to have version information in some places
// so we use this method to make sure that only an assembly name is
// specified.
private static bool CheckAssemblyNameForVersionInfo(String assemName)
{
if (assemName == null)
return false;
// if the assembly name has a comma, we know that version information is present
int index = assemName.IndexOf(',');
return (index != -1);
} // CheckAssemblyNameForVersionInfo
private static TimeSpan ParseTime(String time, RemotingXmlConfigFileData configData)
{
// time formats, e.g.
// 10D -> 10 days
// 10H -> 10 hours
// 10M -> 10 minutes
// 10S -> 10 seconds
// 10MS -> 10 milliseconds
// 10 -> default is seconds: 10 seconds
String specifiedTime = time;
String metric = "s"; // default is seconds
int metricLength = 0;
char lastChar = ' ';
if (time.Length > 0)
lastChar = time[time.Length - 1];
TimeSpan span = TimeSpan.FromSeconds(0);
try
{
if (!Char.IsDigit(lastChar))
{
if (time.Length == 0)
ReportInvalidTimeFormatError(specifiedTime, configData);
time = time.ToLower(CultureInfo.InvariantCulture);
metricLength = 1;
if (time.EndsWith("ms", StringComparison.Ordinal))
metricLength = 2;
metric = time.Substring(time.Length - metricLength, metricLength);
}
int value = Int32.Parse(time.Substring(0, time.Length - metricLength), CultureInfo.InvariantCulture);
switch (metric)
{
case "d": span = TimeSpan.FromDays(value); break;
case "h": span = TimeSpan.FromHours(value); break;
case "m": span = TimeSpan.FromMinutes(value); break;
case "s": span = TimeSpan.FromSeconds(value); break;
case "ms": span = TimeSpan.FromMilliseconds(value); break;
default:
{
ReportInvalidTimeFormatError(specifiedTime, configData);
break;
}
} // switch
}
catch (Exception)
{
ReportInvalidTimeFormatError(specifiedTime, configData);
}
return span;
} // ParseTime
} // class RemotingXmlConfigFileParser
} // namespace
|