/*******************************************************************************
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
* this file except in compliance with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file.
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* *****************************************************************************
* __ _ _ ___
* ( )( \/\/ )/ __)
* /__\ \ / \__ \
* (_)(_) \/\/ (___/
*
* AWS SDK for .NET
*
*/
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using Amazon.Util;
using System.Xml;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Xml.Linq;
namespace Amazon
{
///
/// Root AWS config section
///
internal class AWSSection : ConfigurationSection
{
private const string loggingKey = "logging";
private const string defaultsKey = "defaults";
private const string endpointDefinitionKey = "endpointDefinition";
private const string regionKey = "region";
private const string proxy = "proxy";
private const string profileNameKey = "profileName";
private const string profilesLocationKey = "profilesLocation";
private const string correctForClockSkewKey = "correctForClockSkew";
private const string useSdkCacheKey = "useSdkCache";
private const string applicationNameKey = "applicationName";
private const string csmConfigKey = "csmConfig";
[ConfigurationProperty(loggingKey)]
public LoggingSection Logging
{
get { return (LoggingSection)this[loggingKey]; }
set { this[loggingKey] = value; }
}
[ConfigurationProperty(csmConfigKey)]
public CSMSection CSMConfig
{
get { return (CSMSection)this[csmConfigKey]; }
set { this[csmConfigKey] = value; }
}
[ConfigurationProperty(endpointDefinitionKey)]
public string EndpointDefinition
{
get { return (string)this[endpointDefinitionKey]; }
set { this[endpointDefinitionKey] = value; }
}
[ConfigurationProperty(regionKey)]
public string Region
{
get { return (string)this[regionKey]; }
set { this[regionKey] = value; }
}
[ConfigurationProperty(profileNameKey)]
public string ProfileName
{
get { return (string)this[profileNameKey]; }
set { this[profileNameKey] = value; }
}
[ConfigurationProperty(profilesLocationKey)]
public string ProfilesLocation
{
get { return (string)this[profilesLocationKey]; }
set { this[profilesLocationKey] = value; }
}
[ConfigurationProperty(useSdkCacheKey)]
public bool? UseSdkCache
{
get { return (bool?)this[useSdkCacheKey]; }
set { this[useSdkCacheKey] = value; }
}
[ConfigurationProperty(correctForClockSkewKey)]
public bool? CorrectForClockSkew
{
get { return (bool?)this[correctForClockSkewKey]; }
set { this[correctForClockSkewKey] = value; }
}
[ConfigurationProperty(applicationNameKey)]
public string ApplicationName
{
get { return (string)this[applicationNameKey]; }
set { this[applicationNameKey] = value; }
}
///
/// Gets and sets the proxy settings for the SDK to use.
///
[ConfigurationProperty(proxy)]
public ProxySection Proxy
{
get { return (ProxySection)this[proxy]; }
set { this[proxy] = value; }
}
private IDictionary _serviceSections = null;
public IDictionary ServiceSections
{
get
{
if (_serviceSections == null)
_serviceSections = new Dictionary(StringComparer.Ordinal);
return _serviceSections;
}
set
{
_serviceSections = value;
}
}
protected override bool OnDeserializeUnrecognizedElement(string elementName, System.Xml.XmlReader reader)
{
var section = (XElement)XElement.ReadFrom(reader);
ServiceSections[elementName] = section;
return true;
}
internal string Serialize(string name)
{
try
{
string basicXml = this.SerializeSection(null, name, ConfigurationSaveMode.Full);
XmlDocument doc = new XmlDocument();
doc.LoadXml(basicXml);
using (var textWriter = new StringWriter(CultureInfo.InvariantCulture))
{
CleanUpNodes(doc);
doc.Save(textWriter);
return textWriter.ToString();
}
}
catch (Exception e)
{
return e.ToString();
}
}
internal static void CleanUpNodes(XmlNode node)
{
foreach (XmlNode child in node.ChildNodes)
{
var toRemove = child.Attributes.Cast().Where(at => string.IsNullOrEmpty(at.Value)).ToList();
foreach (var rem in toRemove) child.Attributes.Remove(rem);
CleanUpNodes(child);
}
}
public override bool IsReadOnly()
{
return false;
}
}
#region Basic sections
///
/// Settings for configuring a proxy for the SDK to use.
///
internal class ProxySection : WritableConfigurationElement
{
private const string hostSectionKey = "host";
private const string portSectionKey = "port";
private const string usernameSectionKey = "username";
private const string passwordSectionKey = "password";
private const string bypasslistSectionKey = "bypassList";
private const string bypassOnLocalSectionKey = "bypassOnLocal";
private const char bypasslistSectionSeparator = ';';
///
/// Gets and sets the host name or IP address of the proxy server.
///
[ConfigurationProperty(hostSectionKey)]
public string Host
{
get { return (string)this[hostSectionKey]; }
set { this[hostSectionKey] = value; }
}
///
/// Gets and sets the port number of the proxy.
///
[ConfigurationProperty(portSectionKey)]
public int? Port
{
get { return (int?)this[portSectionKey]; }
set { this[portSectionKey] = value; }
}
///
/// Gets and sets the username to authenticate with the proxy server.
///
[ConfigurationProperty(usernameSectionKey)]
public string Username
{
get { return (string)this[usernameSectionKey]; }
set { this[usernameSectionKey] = value; }
}
///
/// Gets and sets the password to authenticate with the proxy server.
///
[ConfigurationProperty(passwordSectionKey)]
public string Password
{
get { return (string)this[passwordSectionKey]; }
set { this[passwordSectionKey] = value; }
}
///
/// Gets and set the proxy bypass list. A set of semi-colon
/// delimited regular expressions denoting the addresses that
/// should bypass the proxy.
///
[ConfigurationProperty(bypasslistSectionKey)]
public string[] BypassList
{
get
{
var bypassList = (string)this[bypasslistSectionKey];
if (string.IsNullOrEmpty(bypassList))
return new string[0];
return bypassList.Split(new char[] { bypasslistSectionSeparator },
StringSplitOptions.RemoveEmptyEntries);
}
set
{
this[bypasslistSectionKey] = value == null ? null
: string.Join(bypasslistSectionSeparator.ToString(), value);
}
}
///
/// Gets and sets the proxy option to bypass local addresses.
///
[ConfigurationProperty(bypassOnLocalSectionKey)]
public bool? BypassOnLocal
{
get { return (bool?)this[bypassOnLocalSectionKey]; }
set { this[bypassOnLocalSectionKey] = value; }
}
}
///
/// Logging section
///
internal class LoggingSection : WritableConfigurationElement
{
private const string logToKey = "logTo";
private const string logResponsesKey = "logResponses";
private const string logResponsesSizeLimitKey = "logResponsesSizeLimit";
private const string logMetricsKey = "logMetrics";
private const string logMetricsFormatKey = "logMetricsFormat";
private const string logMetricsCustomFormatterKey = "logMetricsCustomFormatter";
[ConfigurationProperty(logToKey)]
public LoggingOptions LogTo
{
get { return (LoggingOptions)this[logToKey]; }
set { this[logToKey] = value; }
}
[ConfigurationProperty(logResponsesKey)]
public ResponseLoggingOption LogResponses
{
get { return (ResponseLoggingOption)this[logResponsesKey]; }
set { this[logResponsesKey] = value; }
}
[ConfigurationProperty(logResponsesSizeLimitKey)]
public int? LogResponsesSizeLimit
{
get { return (int?)this[logResponsesSizeLimitKey]; }
set { this[logResponsesKey] = value; }
}
[ConfigurationProperty(logMetricsKey)]
public bool? LogMetrics
{
get { return (bool?)this[logMetricsKey]; }
set { this[logMetricsKey] = value; }
}
[ConfigurationProperty(logMetricsFormatKey)]
public LogMetricsFormatOption LogMetricsFormat
{
get { return (LogMetricsFormatOption)this[logMetricsFormatKey]; }
set { this[logMetricsFormatKey] = value; }
}
[TypeConverter(typeof(TypeNameConverter))]
[ConfigurationProperty(logMetricsCustomFormatterKey)]
public Type LogMetricsCustomFormatter
{
get { return (Type)this[logMetricsCustomFormatterKey]; }
set { this[logMetricsCustomFormatterKey] = value; }
}
}
internal class CSMSection : WritableConfigurationElement
{
private const string csmEnabledKey = "csmEnabled";
private const string csmClientIdKey = "csmClientId";
private const string csmPortKey = "csmPort";
[ConfigurationProperty(csmEnabledKey)]
public bool? CSMEnabled
{
get { return (bool)this[csmEnabledKey]; }
set { this[csmEnabledKey] = value; }
}
[ConfigurationProperty(csmPortKey)]
public int? CSMPort
{
get { return (int?)this[csmPortKey]; }
set { this[csmPortKey] = value; }
}
[ConfigurationProperty(csmClientIdKey)]
public string CSMClientId
{
get { return (string)this[csmClientIdKey]; }
set { this[csmClientIdKey] = value; }
}
}
#endregion
#region Abstract helper classes
///
/// Easy-to-use generic collection
///
///
public abstract class WritableConfigurationElementCollection : ConfigurationElementCollection
where T : SerializableConfigurationElement, new()
{
protected abstract string ItemPropertyName { get; }
protected override ConfigurationElement CreateNewElement()
{
return new T();
}
protected override ConfigurationElement CreateNewElement(string elementName)
{
return new T();
}
protected override object GetElementKey(ConfigurationElement element)
{
return element;
}
protected override string ElementName { get { return string.Empty; } }
protected override bool IsElementName(string elementName)
{
return (string.Equals(elementName, ItemPropertyName, StringComparison.Ordinal));
}
public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMapAlternate; } }
public override bool IsReadOnly()
{
return false;
}
protected WritableConfigurationElementCollection() : base() { }
public void Add(T t)
{
this.BaseAdd(t);
}
public void Add(T[] ts)
{
foreach (var t in ts)
{
Add(t);
}
}
protected override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey)
{
if (writer == null)
return base.SerializeElement(writer, serializeCollectionKey);
for (int i = 0; i < this.Count; i++)
{
var item = BaseGet(i) as SerializableConfigurationElement;
writer.WriteStartElement(ItemPropertyName);
item.SerializeElement(writer, serializeCollectionKey);
writer.WriteEndElement();
}
return (Count > 0);
}
public List Items { get { return this.Cast().ToList(); } }
}
///
/// Configuration element that serializes properly when used with collections
///
public abstract class SerializableConfigurationElement : WritableConfigurationElement
{
new public bool SerializeElement(XmlWriter writer, bool serializeCollectionKey)
{
return base.SerializeElement(writer, serializeCollectionKey);
}
}
///
/// ConfigurationElement class which returns false for IsReadOnly
///
public abstract class WritableConfigurationElement : ConfigurationElement
{
public override bool IsReadOnly()
{
return false;
}
}
#endregion
}