Commits

Olemis Lang committed c3ff0b4

FLiOOPS.NET: Importing previous Serialization, Logging and WCF code.

  • Participants

Comments (0)

Files changed (25)

+syntax: glob
+
+# Backup files left behind by the Emacs editor.
+*~
+# Lock files used by the Emacs editor.
+.\#*
+# Temporary files used by the vim editor.
+.*.swp
+# A hidden file created by the Mac OS X Finder.
+.DS_Store
+# Temporary folders
+**/temp
+**/temp/*
+# SVN entries and temp files
+**/.svn/*
+**/*.tmp
+# Build and dist dirs
+**/obj/**
+**/Debug/**
+# MSVS test results
+**/TestResults/**
+TestResults/**

FLiOOPS.Core/FLiOOPS.Core.csproj

+ďťż<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{7F300232-D477-4400-A6C5-387089805167}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>FLiOOPS.Core</RootNamespace>
+    <AssemblyName>FLiOOPS.Core</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Web" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Serialize.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\UploadHelper\UploadHelper.csproj">
+      <Project>{02FBD52C-B997-4D18-9E2C-81B5AE8EFB30}</Project>
+      <Name>UploadHelper</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

FLiOOPS.Core/Properties/AssemblyInfo.cs

+ďťżusing System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("FLiOOPS.Core")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("FLiOOPS project")]
+[assembly: AssemblyProduct("FLiOOPS.Core")]
+[assembly: AssemblyCopyright("Copyright Š FLiOOPS project 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("eb8a8238-dc1f-4146-839c-c2864282831c")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

FLiOOPS.Core/Serialize.cs

+ďťżusing System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Web;
+using System.Xml.Serialization;
+using System.Xml.Xsl;
+using Krystalware.UploadHelper;
+using System.Xml;
+
+namespace FLiOOPS.Serialization
+{
+    public abstract class ObjectSerializer
+    {
+        virtual protected bool HandleProperty(PropertyInfo pi, object value)
+        {
+            if (value == null)
+                return false;
+            foreach (Attribute attr in pi.GetCustomAttributes(true))
+                if (attr is XmlIgnoreAttribute)
+                    return false;
+                else if (attr is OmitIfValueAttribute &&
+                        value.Equals((attr as OmitIfValueAttribute).Value))
+                    return false;
+            return true;
+        }
+
+        public abstract void Serialize(TextWriter textWriter, Object o);
+        public abstract void Serialize(Stream stream, Object o);
+        public abstract object Deserialize(Type T,  Stream stream);
+        public abstract object Deserialize(Type T,  TextReader textReader);
+        public abstract string GetContentType();
+        
+        public T Deserialize<T>(Stream stream) where T : class
+        {
+            return Deserialize(typeof(T), stream) as T;
+        }
+        public T Deserialize<T>(TextReader textReader) where T : class 
+        {
+            return Deserialize(typeof(T), textReader) as T;
+        }
+
+    }
+    
+    /// <summary>
+    /// Handle object serialization using URL encode MIME formatting.
+    /// </summary>
+    public class UrlEncodeSerializer : ObjectSerializer
+    {
+        public override void Serialize(TextWriter textWriter, Object o)
+        {
+            bool first = true;
+            foreach (PropertyInfo pi in o.GetType().GetProperties())
+            {
+                object value = pi.GetValue(o, null);
+                if (HandleProperty(pi, value))
+                {
+                    if (!first)
+                        textWriter.Write("&");
+                    textWriter.Write(HttpUtility.UrlEncode(pi.Name));
+                    textWriter.Write("=");
+                    textWriter.Write(
+                        HttpUtility.UrlEncode(pi.GetValue(o, null).ToString()));
+                    first = false;
+                }
+            }
+        }
+        public override void Serialize(Stream stream, Object o)
+        {
+            using (StreamWriter sw = new StreamWriter(stream, Encoding.GetEncoding("ascii")))
+            {
+                Serialize(sw, o);
+            }
+        }
+        public override object Deserialize(Type T, Stream stream) 
+        {
+            using (StreamReader sr = new StreamReader(stream, Encoding.GetEncoding("ascii")))
+            {
+                return Deserialize(T, sr);
+            }
+        }
+        public override object Deserialize(Type T, TextReader textReader) 
+        {
+            throw new NotImplementedException("URL-encode deserialization not implemented");
+        }
+        public override string GetContentType()
+        {
+            return "application/x-www-form-urlencoded";
+        }
+    }
+
+    /// <summary>
+    /// Handle object serialization using Multipart Form MIME formatting.
+    /// </summary>
+    /// <remarks>
+    /// If used to submit data to a web site then <c>ContentType</c> header must 
+    /// be previously set to <c>"multipart/form-data; boundary=" + <paramref name="boundary"/></c>.
+    /// </remarks>
+    public class MultipartFormSerializer : ObjectSerializer
+    {
+        /// <param name="boundary">
+        /// Value of boundary used to delimit message parts. By default 
+        /// it's set to <c>"----------" + DateTime.Now.Ticks.ToString("x")</c>
+        /// </param>
+        public string boundary { get; set; }
+        public bool nameIsFilename { get; set; }
+        Action<long> _notifyLength = IGNORE_DUMMY.notifyLength;
+
+        /// <param name="notifyLength">
+        /// Delegate to be called to notify the caller about content length.
+        /// Useful e.g. to update headers in HTTP requests.
+        /// </param>
+        public Action<long> notifyLength
+        {
+            get { return _notifyLength; }
+            set { _notifyLength = value; }
+        }
+
+        public MultipartFormSerializer() : base() { }
+        public MultipartFormSerializer(string boundary) : base() 
+        {
+            this.boundary = boundary;
+        }
+        public MultipartFormSerializer(string boundary, Action<long> notifyLength)
+            : base()
+        {
+            this.boundary = boundary;
+            this.notifyLength = notifyLength;
+        }
+
+        private static bool isStream(Type t)
+        {
+            return t == typeof(Stream) || t.IsSubclassOf(typeof(Stream));
+        }
+
+        /// <summary>
+        /// Serialize this object using RFC 1867 Multipart Form MIME
+        /// </summary>
+        /// <param name="stream">Target output stream.</param>
+        /// <param name="o">Object to serialize.</param>
+        public override void Serialize(Stream stream, Object o)
+        {
+            List<MimePart> mimeParts = new List<MimePart>();
+            
+            try
+            {
+                int nameIndex = 0;
+
+                foreach (PropertyInfo pi in o.GetType().GetProperties())
+                {
+                    object value = pi.GetValue(o, null);
+                    if (HandleProperty(pi, value))
+                    {
+                        Stream [] attachments = null;
+                        if (isStream(pi.PropertyType))
+                            attachments = new Stream[] { value as Stream };
+                        else if (pi.PropertyType.IsArray && isStream(pi.PropertyType.GetElementType()))
+                            attachments = (Stream[]) value;
+                        if (attachments != null)
+                        {
+                            foreach (Stream a in attachments)
+                            {
+                                // Files to upload
+                                StreamMimePart part = new StreamMimePart();
+
+                                string filename = "";
+
+                                try
+                                {
+                                    // Try to retrieve FileName property to identify this file
+                                    filename = (string) a.GetType().GetProperty("Name").GetValue(a, null);
+                                }
+                                catch (Exception) {
+                                    filename = "file" + nameIndex++;
+                                }
+
+                                part.Headers["Content-Disposition"] = "form-data; name=\"" +
+                                    ((nameIsFilename) ? filename : pi.Name) + 
+                                    "\"; filename=\"" + filename + "\"";
+                                part.Headers["Content-Type"] = "application/octet-stream";
+                                part.Headers["Content-Transfer-Encoding"] = "binary";
+
+                                part.SetStream(a as Stream);
+
+                                mimeParts.Add(part);
+                            }
+                        }
+                        else
+                        {
+                            // Form value
+                            StringMimePart part = new StringMimePart();
+
+                            part.Headers["Content-Disposition"] = "form-data; name=\"" + pi.Name + "\"";
+                            part.StringData = value.ToString();
+
+                            mimeParts.Insert(0, part);
+                        }
+                    }
+                }
+
+                if (boundary == null) 
+                    boundary = GenerateBoundary();
+                //req.ContentType = "multipart/form-data; boundary=" + boundary;
+
+                long contentLength = 0;
+
+                byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");
+
+                foreach (MimePart part in mimeParts)
+                {
+                    contentLength += part.GenerateHeaderFooterData(boundary);
+                }
+
+                //req.ContentLength = contentLength + _footer.Length;
+                notifyLength(contentLength + _footer.Length);
+
+                byte[] buffer = new byte[2048];
+                byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
+                int read;
+
+                using (stream)
+                {
+                    foreach (MimePart part in mimeParts)
+                    {
+                        stream.Write(part.Header, 0, part.Header.Length);
+
+                        while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0)
+                            stream.Write(buffer, 0, read);
+
+                        part.Data.Dispose();
+
+                        stream.Write(afterFile, 0, afterFile.Length);
+                    }
+
+                    stream.Write(_footer, 0, _footer.Length);
+                }
+            }
+            catch
+            {
+                foreach (MimePart part in mimeParts)
+                    if (part.Data != null)
+                        part.Data.Dispose();
+
+                throw;
+            }
+        }
+        public override void Serialize(TextWriter textWriter, Object o)
+        {
+            throw new NotImplementedException("RFC 1867 TextReader serialization not implemented");
+        }
+        public override object Deserialize(Type T, Stream stream) 
+        {
+            using (StreamReader sr = new StreamReader(stream, Encoding.GetEncoding("ascii")))
+            {
+                return Deserialize(T, sr);
+            }
+        }
+        public override object Deserialize(Type T, TextReader textReader) 
+        {
+            throw new NotImplementedException("RFC 1867 deserialization not implemented");
+        }
+        public override string GetContentType()
+        {
+            if (boundary == null)
+                boundary = GenerateBoundary();
+            return "multipart/form-data; boundary=" + boundary;
+        }
+
+        #region Internal methods
+
+        private class IgnoreContentLength
+        {
+            public void notifyLength(long length) { }
+        }
+
+        private static IgnoreContentLength IGNORE_DUMMY = new IgnoreContentLength();
+
+        public static string GenerateBoundary()
+        { return "----------" + DateTime.Now.Ticks.ToString("x");  }
+
+        #endregion
+
+    }
+
+    /// <summary>
+    /// A serializer that handles custom XML serialization by applying 
+    /// XSL transformation before standard deserialization and 
+    /// after standard serialization, respectively .
+    /// </summary>
+    public class XsltSerializer : ObjectSerializer
+    {
+        /// <summary>
+        /// Apply this transformation before deserializing object.
+        /// </summary>
+        public XslCompiledTransform readTx { get; set; }
+        /// <summary>
+        /// Apply this transformation after serializing object.
+        /// </summary>
+        public XslCompiledTransform writeTx { get; set; }
+
+        public override void Serialize(TextWriter textWriter, object o)
+        {
+            using (XmlWriter xw = XmlWriter.Create(textWriter))
+            {
+                Serialize(xw, o);
+            }
+        }
+
+        public override void Serialize(Stream stream, object o)
+        {
+            using (XmlWriter xw = XmlWriter.Create(stream))
+            {
+                Serialize(xw, o);
+            }
+        }
+
+        public virtual void Serialize(XmlWriter xmlWriter, object o)
+        {
+            using (Stream ms = new MemoryStream())
+            using (TextWriter tw = new StreamWriter(ms, Encoding.UTF8))
+            using (XmlTextReader xr = new XmlTextReader(ms))
+            {
+                XmlSerializer xs = new XmlSerializer(o.GetType());
+                xs.Serialize(tw, o);
+                ms.Seek(0, SeekOrigin.Begin);
+                writeTx.Transform(xr, xmlWriter);
+            }
+        }
+
+        public virtual T Deserialize<T>(XmlReader xmlReader) where T: class
+        {
+            return Deserialize(typeof(T), xmlReader) as T;
+        }
+
+        public virtual object Deserialize(Type T, XmlReader xmlReader)
+        {
+            using (Stream ms = new MemoryStream())
+            using (XmlWriter xw = new XmlTextWriter(ms, Encoding.UTF8))
+            {
+                readTx.Transform(xmlReader, xw);
+                ms.Seek(0, SeekOrigin.Begin);
+                XmlSerializer xs = new XmlSerializer(T);
+                return xs.Deserialize(ms);
+            }
+        }
+
+        public override object Deserialize(Type T, Stream stream) 
+        {
+            using (XmlReader xr = XmlReader.Create(stream))
+            {
+                return Deserialize(T, xr);
+            }
+        }
+        public override object Deserialize(Type T, TextReader textReader) 
+        {
+            using (XmlReader xr = XmlReader.Create(textReader))
+            {
+                return Deserialize(T, xr);
+            }
+        }
+
+        public override string GetContentType()
+        {
+            return "application/xml";
+        }
+    }
+
+    [AttributeUsage(AttributeTargets.Property,
+       AllowMultiple = false,
+       Inherited = true)]
+    public class OmitIfValueAttribute : Attribute
+    {
+        public object Value { get; set; }
+
+        public OmitIfValueAttribute(object value)
+        {
+            this.Value = value;
+        }
+    }
+}

FLiOOPS.Logging/Core.cs

+ďťżusing ComLib.Configuration;
+using ComLib.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace FLiOOPS.Logging
+{
+    /// <summary>
+    /// Flags used to decide what to do when overwriting something.
+    /// </summary>
+    enum OverwriteMode { 
+        /// <summary>
+        /// Clear all values. Existing values in container 
+        /// object <b>have to</b> be removed.
+        /// </summary>
+        CLEAR, 
+        /// <summary>
+        /// Do nothing if target already exists.
+        /// </summary>
+        IGNORE, 
+        /// <summary>
+        /// Overwrite target if it already exists.
+        /// </summary>
+        OVERWRITE };
+
+    /// <summary>
+    /// Interface implemented by classes that setup a whole 
+    /// logging environment containing multiple log sources,
+    /// by following a well-known strategy (e.g. by reading 
+    /// rules found in a configuration file)
+    /// </summary>
+    public interface ILogSetup
+    {
+        /// <summary>
+        /// Setup the logging environment by following 
+        /// the default strategy. Previous configuration 
+        /// will be lost after calling this method.
+        /// </summary>
+        /// <exception cref="System.Configuration.ConfigurationException">
+        /// A configuration error may be raised (e.g. configuration 
+        /// data has invalid characters or wrong format).
+        /// </exception>
+        void DefaultSetup();
+        /// <summary>
+        /// Setup the logging environment by following 
+        /// the default strategy, but customize the procedure 
+        /// according to the options supplied in.
+        /// </summary>
+        /// <param name="options">
+        /// A dictionary containing custom options to consider
+        /// at setup time. 
+        /// </param>
+        /// <exception cref="System.Configuration.ConfigurationException">
+        /// A configuration error may be raised (e.g. configuration 
+        /// data has invalid characters or wrong format).
+        /// </exception>
+        /// <remarks>
+        /// So far the following key|value pairs supported in 
+        /// <paramref name="options"/> have special meaning :
+        /// 
+        /// <list type="bullet">
+        /// <item>
+        ///     <term>overwrite</term>
+        ///     <description>
+        ///     Overwrite mode (<see cref="FLiOOPS.Logging.OverwriteMode"/>).
+        ///     Defaults to <value>FLiOOPS.Logging.OverwriteMode.CLEAR</value>.
+        ///     </description>
+        /// </item>
+        /// </list>
+        /// 
+        /// Options specific to particular instances 
+        /// implementing this interface <b>should</b> 
+        /// start with an underscore (e.g. <b>_</b>) in order 
+        /// to avoid conflicts.
+        /// </remarks>
+        /// <see cref="System.Collections.Generic.IDictionary"/>
+        void CustomSetup(IDictionary<object, object> options);
+        /// <summary>
+        /// Load custom logging rules from an external configuration 
+        /// source (e.g. configuration file).
+        /// </summary>
+        /// <param name="config">
+        /// Configuration source used to read logging setup rules.
+        /// </param>
+        void Load(IConfigSection config);
+    }
+
+    public class EnhancedLogEvent : LogEvent
+    {
+        public new LogLevel Level 
+        {
+            get { return base.Level; }
+            set { base.Level = value; }
+        }
+        public new object Message 
+        {
+            get { return base.Message; }
+            set { base.Message = value; }
+        }
+        public new string FinalMessage 
+        {
+            get { return base.FinalMessage; }
+            set { base.FinalMessage = value; }
+        }
+        public new Exception Error 
+        {
+            get { return base.Error; }
+            set { base.Error = value; }
+        }
+        public new object[] Args 
+        {
+            get { return base.Args; }
+            set { base.Args = value; }
+        }
+        public new string Computer 
+        {
+            get { return base.Computer; }
+            set { base.Computer = value; }
+        }
+        public new DateTime CreateTime
+        {
+            get { return base.CreateTime; }
+            set { base.CreateTime = value; }
+        }
+        public new string ThreadName 
+        {
+            get { return base.ThreadName; }
+            set { base.ThreadName = value; }
+        }
+        public new string UserName 
+        {
+            get { return base.UserName; }
+            set { base.UserName = value; }
+        }
+        public new Exception Ex 
+        {
+            get { return base.Ex; }
+            set { base.Ex = value; }
+        }
+        public new Type LogType 
+        {
+            get { return base.LogType; }
+            set { base.LogType = value; }
+        }
+
+        public EnhancedLogEvent(LogEvent logEvent) 
+            : base()
+        {
+            Type thisType = this.GetType();
+            foreach (FieldInfo fi in typeof(LogEvent).GetFields())
+            {
+                PropertyInfo pi = thisType.GetProperty(fi.Name);
+                pi.SetValue(this, fi.GetValue(logEvent), null);
+            }
+        }
+    }
+}

FLiOOPS.Logging/FLiOOPS.Logging.csproj

+ďťż<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{E470C80B-360D-4A2C-8520-0A1E9E87BC95}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>FLiOOPS.Logging</RootNamespace>
+    <AssemblyName>FLiOOPS.Logging</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="CommonLibrary, Version=0.9.4.4, Culture=neutral, processorArchitecture=MSIL" />
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Core.cs" />
+    <Compile Include="LogCollection.cs" />
+    <Compile Include="LogFmt.cs" />
+    <Compile Include="LogLevelDispatch.cs" />
+    <Compile Include="LogUtils.cs" />
+    <Compile Include="PyLogging.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Lib\CommonLibrary.dll" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

FLiOOPS.Logging/Lib/CommonLibrary.dll

Binary file added.

FLiOOPS.Logging/LogCollection.cs

+ďťżusing ComLib.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace FLiOOPS.Logging
+{
+    public class LogCollection : LogBase
+    {
+        public ICollection<EnhancedLogEvent> Events { get; set; }
+        
+        public override void Log(LogEvent logEvent)
+        {
+            Events.Add(new EnhancedLogEvent(logEvent));
+        }
+    }
+}

FLiOOPS.Logging/LogFmt.cs

+ďťżusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace FLiOOPS.Logging
+{
+    /// <summary>
+    /// Formatter instances are used to convert a LogRecord to text.
+    /// <para>
+    /// Formatters need to know how a LogRecord is constructed. They are
+    /// responsible for converting a LogRecord to (usually) a string which can
+    /// be interpreted by either a human or an external system. The base Formatter
+    /// allows a formatting string to be specified. If none is supplied, the
+    /// default value of "%s(message)\\n" is used.
+    /// </para>
+    /// <para>
+    /// The Formatter can be initialized with a format string which makes use of
+    /// knowledge of the LogRecord attributes - e.g. the default value mentioned
+    /// above makes use of the fact that the user's message and arguments are pre-
+    /// formatted into a LogRecord's message attribute. Currently, the useful
+    /// attributes in a LogRecord are described by:
+    /// </para>
+    /// <list type="bullet">
+    /// <item>
+    ///     <term>
+    ///     %(name)s
+    ///     </term>
+    ///     <description>
+    ///     Name of the logger (logging channel)
+    ///     </description>
+    /// </item>
+    ///
+    /// <item>
+    ///     <term>
+    ///     %(levelno)s
+    ///     </term>
+    ///     <description>
+    ///     Numeric logging level for the message (DEBUG, INFO,
+    ///     WARNING, ERROR, CRITICAL)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(levelname)s
+    ///     </term>
+    ///     <description>
+    ///     Text logging level for the message ("DEBUG", "INFO",
+    ///     "WARNING", "ERROR", "CRITICAL")
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(pathname)s
+    ///     </term>
+    ///     <description>
+    ///     Full pathname of the source file where the logging
+    ///     call was issued (if available)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(filename)s
+    ///     </term>
+    ///     <description>
+    ///     Filename portion of pathname
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(module)s
+    ///     </term>
+    ///     <description>
+    ///     Module (name portion of filename)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(lineno)d
+    ///     </term>
+    ///     <description>
+    ///     Source line number where the logging call was issued
+    ///     (if available)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(funcName)s
+    ///     </term>
+    ///     <description>
+    ///     Function name
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(created)f
+    ///     </term>
+    ///     <description>
+    ///     Time when the LogRecord was created (time.time()
+    ///     return value)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(asctime)s         
+    ///     </term>
+    ///     <description>
+    ///     Textual time when the LogRecord was created
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(msecs)d           
+    ///     </term>
+    ///     <description>
+    ///     Millisecond portion of the creation time
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(relativeCreated)d 
+    ///     </term>
+    ///     <description>
+    ///     Time in milliseconds when the LogRecord was created,
+    ///     relative to the time the logging module was loaded
+    ///     (typically at application startup time)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(thread)d
+    ///     </term>
+    ///     <description>
+    ///     Thread ID (if available)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(threadName)s
+    ///     </term>
+    ///     <description>
+    ///     Thread name (if available)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(process)d
+    ///     </term>
+    ///     <description>
+    ///     Process ID (if available)
+    ///     </description>
+    /// </item>
+    ///     
+    /// <item>
+    ///     <term>
+    ///     %(message)s
+    ///     </term>
+    ///     <description>
+    ///     The result of record.getMessage(), computed just as
+    ///     the record is emitted
+    ///     </description>
+    /// </item>
+    /// </list>
+    /// </summary>
+    interface ILogFormatter
+    {
+    }
+
+    /// <summary>
+    /// Default log formatter.
+    /// </summary>
+    class LogFormatter : ILogFormatter
+    { }
+}

FLiOOPS.Logging/LogLevelDispatch.cs

+ďťżusing ComLib.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace FLiOOPS.Logging
+{
+    public class LogLevelDispatch : LogBase, ILogMulti
+    {
+        public LogLevelDispatch(string name, ILog logger)
+            : base(name)
+        {
+            (this as ILogMulti).Replace(logger);
+        }
+
+        public LogLevelDispatch(string name, List<ILog> loggers)
+            : base(name)
+        {
+            ILogMulti multi = (this as ILogMulti);
+            foreach (ILog logger in loggers)
+                multi.Replace(logger);
+        }
+
+        protected IDictionary<LogLevel, ILog> sources = new Dictionary<LogLevel, ILog>();
+        /// <summary>
+        /// Raise exceptions if no logger is bound to log level.
+        /// </summary>
+        public bool Noisy { get; set; }
+
+        #region ILogMulti Members
+
+        void ILogMulti.Append(ILog logger)
+        {
+            (this as ILogMulti).Replace(logger);
+        }
+
+        void ILogMulti.Clear()
+        {
+            sources.Clear();
+        }
+
+        int ILogMulti.Count
+        {
+            get { return sources.Count; }
+        }
+
+        void ILogMulti.Replace(ILog logger)
+        {
+            logger.Level = this.Level;
+            sources[LogHelper.GetLogLevel(logger.Name)] = logger;
+        }
+
+        ILog ILogMulti.this[int index]
+        {
+            get { return sources[(LogLevel)index]; }
+        }
+
+        ILog ILogMulti.this[string loggerName]
+        {
+            get { return sources[LogHelper.GetLogLevel(loggerName)]; }
+        }
+
+        #endregion
+
+        #region ILog overrides
+
+        public override LogLevel Level
+        {
+            get
+            {
+                return base.Level;
+            }
+            set
+            {
+                base.Level = value;
+                foreach (ILog logger in sources.Values)
+                    logger.Level = value;
+            }
+        }
+
+        #endregion
+
+        public override void Log(LogEvent logEvent)
+        {
+            ILog logger = null;
+            if (sources.TryGetValue(logEvent.Level, out logger))
+                logger.Log(logEvent);
+            else if (Noisy)
+                throw new InvalidOperationException(string.Format(
+                    "Logger {0} There's no logger registered for log level {1}", 
+                    Name, logEvent.Level.ToString()));
+        }
+    }
+}

FLiOOPS.Logging/LogUtils.cs

+ďťżusing ComLib.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace FLiOOPS.Logging
+{
+    class LogPlaceHolder
+    {
+    }
+
+    /// <summary>
+    /// Access the global <c>ComLib.Logging.Logger</c> 
+    /// using an instance.
+    /// </summary>
+    /// <remarks>
+    /// <b>IMPORTANT</b> Never add this logger to any other 
+    /// logger hierarchy accessible from <c>ComLib.Logging.Logger</c>.
+    /// If you do that your logging code will enter an 
+    /// infinite loop.
+    /// </remarks>
+    class GlobalLogger : LogBase, ILogMulti
+    {
+        public GlobalLogger() {}
+        
+        #region ILogMulti Members
+
+        /// <summary>
+        /// Add a log source to the global logging hierarchy.
+        /// </summary>
+        /// <param name="logger">
+        /// An instance of <see cref="ComLib.Logging.ILogMulti"/> 
+        /// to be added directly as a child of <see cref="ComLib.Logging.Logger"/>
+        /// </param>
+        /// <exception cref="System.ArgumentException">
+        /// If <paramref name="logger"/> is not an instance of 
+        /// <see cref="ComLib.Logging.ILogMulti"/> .
+        /// </exception>
+        void  ILogMulti.Append(ILog logger)
+        {
+ 	        if (!(logger is ILogMulti))
+                throw new ArgumentException(
+                    "Only instances of ComLib.Logging.ILogMulti are allowed", 
+                    "logger");
+            Logger.Add(logger as ILogMulti);
+        }
+
+        /// <summary>
+        /// Forward this call to <see cref="ComLib.Logging.Logger.Clear()"/>
+        /// </summary>
+        void  ILogMulti.Clear()
+        {
+ 	        Logger.Clear();
+        }
+
+        /// <summary>
+        /// Forward this call to <see cref="ComLib.Logging.Logger.Count"/>
+        /// </summary>
+        int  ILogMulti.Count
+        {
+	        get { return Logger.Count; }
+        }
+
+        /// <summary>
+        /// Replace all loggers with a specified logger.
+        /// </summary>
+        /// <param name="logger">
+        /// An instance of 
+        /// </param>
+        /// <exception cref="System.ArgumentException"></exception>
+        void  ILogMulti.Replace(ILog logger)
+        {
+ 	        if (!(logger is ILogMulti))
+                throw new ArgumentException(
+                    "Only instances of ComLib.Logging.ILogMulti are allowed", 
+                    "logger");
+            Logger.Clear();
+            Logger.Add(logger as ILogMulti);
+        }
+
+        /// <summary>
+        /// Retrieve a children of global <see cref="ComLib.Logging.Logger"/>
+        /// by position.
+        /// </summary>
+        /// <param name="index">
+        /// Target logger index.
+        /// </param>
+        /// <returns>
+        /// The child of <see cref="ComLib.Logging.Logger"/> at 
+        /// the given <paramref name="index"/>. It will always be 
+        /// an instance of <see cref="ComLib.Logging.ILogMulti"/>
+        /// </returns>
+        ILog  ILogMulti.this[int index]
+        {
+	        get { return Logger.Get(index); }
+        }
+
+        /// <summary>
+        /// Retrieve a children of global <see cref="ComLib.Logging.Logger"/>
+        /// by name.
+        /// </summary>
+        /// <param name="loggerName">
+        /// Target logger name.
+        /// </param>
+        /// <returns>
+        /// The child of <see cref="ComLib.Logging.Logger"/> named 
+        /// as <paramref name="loggerName"/>. It will always be 
+        /// an instance of <see cref="ComLib.Logging.ILogMulti"/>
+        /// </returns>
+        ILog  ILogMulti.this[string loggerName]
+        {
+	        get { return Logger.Get(loggerName); }
+        }
+
+        #endregion
+
+        #region ILog Members
+
+        /// <summary>
+        /// Builds a log event by calling 
+        /// <see cref="ComLib.Logging.LogBase.BuildLogEvent(LogLevel , object , Exception , object[] )"/>.
+        /// </summary>
+        /// <param name="level">Logging level <see cref="ComLib.Logging.LogLevel"/></param>
+        /// <param name="message">Display message</param>
+        /// <param name="ex">Exception notified in the logs</param>
+        /// <param name="args">Extra arguments to include in log entry</param>
+        /// <returns>Log event containing all data supplied in.</returns>
+        LogEvent  ILog.BuildLogEvent(LogLevel level, object message, Exception ex, object[] args)
+        {
+ 	        return base.BuildLogEvent(level, message, ex, args);
+        }
+
+        void  ILog.Debug(object message, Exception exception, object[] args)
+        {
+ 	        Logger.Debug(message, exception, args);
+        }
+
+        void  ILog.Debug(object message, Exception exception)
+        {
+ 	        Logger.Debug(message, exception);
+        }
+
+        void  ILog.Debug(object message)
+        {
+ 	        Logger.Debug(message);
+        }
+
+        void  ILog.Error(object message, Exception exception, object[] args)
+        {
+ 	        Logger.Error(message, exception, args);
+        }
+
+        void  ILog.Error(object message, Exception exception)
+        {
+ 	        Logger.Error(message, exception);
+        }
+
+        void  ILog.Error(object message)
+        {
+ 	        Logger.Error(message);
+        }
+
+        void  ILog.Fatal(object message, Exception exception, object[] args)
+        {
+ 	        Logger.Fatal(message, exception, args);
+        }
+
+        void  ILog.Fatal(object message, Exception exception)
+        {
+ 	        Logger.Fatal(message, exception);
+        }
+
+        void  ILog.Fatal(object message)
+        {
+ 	        Logger.Fatal(message);
+        }
+
+        void  ILog.Flush()
+        {
+ 	        Logger.Flush();
+        }
+
+        void  ILog.Info(object message, Exception exception, object[] args)
+        {
+ 	        Logger.Info(message, exception, args);
+        }
+
+        void  ILog.Info(object message, Exception exception)
+        {
+ 	        Logger.Info(message, exception);
+        }
+
+        void  ILog.Info(object message)
+        {
+ 	        Logger.Info(message);
+        }
+
+        bool  ILog.IsDebugEnabled
+        {
+	        get { return Logger.IsDebugEnabled; }
+        }
+
+        bool  ILog.IsEnabled(LogLevel level)
+        {
+ 	        return Logger.Default.IsEnabled(level);
+        }
+
+        bool  ILog.IsErrorEnabled
+        {
+	        get { return Logger.IsErrorEnabled; }
+        }
+
+        bool  ILog.IsFatalEnabled
+        {
+	        get { return Logger.IsFatalEnabled; }
+        }
+
+        bool  ILog.IsInfoEnabled
+        {
+	        get { return Logger.IsInfoEnabled; }
+        }
+
+        bool  ILog.IsWarnEnabled
+        {
+	        get { return Logger.IsWarnEnabled; }
+        }
+
+        /// <summary>
+        /// Get / set the default logger's log level.
+        /// </summary>
+        LogLevel  ILog.Level
+        {
+	          get 
+	        { 
+		        return Logger.Default.Level;
+	        }
+	          set 
+	        { 
+		        Logger.Default.Level = value; 
+	        }
+        }
+
+        void  ILog.Log(LogLevel level, object message, Exception ex, object[] args)
+        {
+ 	        Logger.Log(level, message, ex, args);
+        }
+
+        void  ILog.Log(LogLevel level, object message, Exception exception)
+        {
+ 	        Logger.Log(level, message, exception);
+        }
+
+        void  ILog.Log(LogLevel level, object message)
+        {
+ 	        Logger.Log(level, message);
+        }
+
+        void  ILog.Log(LogEvent logEvent)
+        {
+ 	        Logger.Log(logEvent.Level, logEvent.Message, logEvent.Error, logEvent.Args);
+        }
+
+        void  ILog.Message(object message, Exception exception, object[] args)
+        {
+ 	        Logger.Message(message, exception, args);
+        }
+
+        void  ILog.Message(object message, Exception exception)
+        {
+ 	        Logger.Message(message, exception);
+        }
+
+        void  ILog.Message(object message)
+        {
+ 	        Logger.Message(message);
+        }
+
+        string  ILog.Name
+        {
+	        get { return "global"; }
+        }
+
+        void  ILog.ShutDown()
+        {
+ 	        Logger.ShutDown();
+        }
+
+        void  ILog.Warn(object message, Exception exception, object[] args)
+        {
+ 	        Logger.Warn(message, exception, args);
+        }
+
+        void  ILog.Warn(object message, Exception exception)
+        {
+ 	        Logger.Warn(message, exception);
+        }
+
+        void  ILog.Warn(object message)
+        {
+ 	        Logger.Warn(message);
+        }
+
+        #endregion
+
+        public override void Log(LogEvent logEvent) {
+            // TODO: Should implement this ???
+        }
+    }
+
+    /// <summary>
+    /// Helper methods for logging.
+    /// </summary>
+    class LoggerUtils
+    {
+        /// <summary>
+        /// Get a logger with the specified name (channel name), creating it
+        /// if it doesn't yet exist. 
+        /// <para>
+        /// If a <see cref="LogPlaceHolder"/> existed for the specified name (i.e. the logger
+        /// didn't exist but a child of it did), replace it with the created
+        /// logger and fix up the parent/child references which pointed to the
+        /// placeholder to now point to the logger.
+        /// </para>
+        /// </summary>
+        /// <param name="qn">
+        /// This name is a dot-separated hierarchical
+        /// name, such as <c>"a"</c>, <c>"a.b"</c>, <c>"a.b.c"</c> or similar.
+        /// </param>
+        /// <returns>
+        /// The target instance of <see cref="ComLib.Logging.ILog"/>
+        /// at the requested position in the logging hierarchy.
+        /// </returns>
+        /// <remarks>
+        /// Lookup is started from the global default logger (i.e. 
+        /// <c>ComLib.Logging.Logger.Default</c>).
+        /// </remarks>
+        public static ILog getLogger(string qn)
+        {
+            return getLogger(new GlobalLogger(), qn);
+        }
+        /// <summary>
+        /// Get a logger with the specified name (channel name), creating it
+        /// if it doesn't yet exist. 
+        /// <para>
+        /// If a <see cref="PlaceHolder"/> existed for the specified name (i.e. the logger
+        /// didn't exist but a child of it did), replace it with the created
+        /// logger and fix up the parent/child references which pointed to the
+        /// placeholder to now point to the logger.
+        /// </para>
+        /// </summary>
+        /// <param name="qn">
+        /// This name is a dot-separated hierarchical
+        /// name, such as <c>"a"</c>, <c>"a.b"</c>, <c>"a.b.c"</c> or similar.
+        /// </param>
+        /// <param name="root">
+        /// The root logger. Input qualified name (i.e. <paramref name="qn"/>)
+        /// will be considered to be the logger path relative to this logger.
+        /// </param>
+        /// <returns>
+        /// The target instance of <see cref="ComLib.Logging.ILog"/>
+        /// at the requested position in the logging hierarchy relative 
+        /// to the <paramref name="root"/> logger.
+        /// </returns>
+        public static ILog getLogger(ILogMulti root, string qn)
+        {
+            ILog result = root[qn];
+            if (result == null)
+            {
+                result = new LogMulti(qn, new List<ILog>());
+                root.Append(result);
+                _fixup_parents(root, result);
+            }
+            return result;
+        }
+
+        // Former Python code borrowed from stdlib !!!
+
+        //rv = None
+        //_acquireLock()
+        //try:
+        //    if name in self.loggerDict:
+        //        rv = self.loggerDict[name]
+        //        if isinstance(rv, PlaceHolder):
+        //            ph = rv
+        //            rv = _loggerClass(name)
+        //            rv.manager = self
+        //            self.loggerDict[name] = rv
+        //            self._fixupChildren(ph, rv)
+        //            self._fixupParents(rv)
+        //    else:
+        //        rv = _loggerClass(name)
+        //        rv.manager = self
+        //        self.loggerDict[name] = rv
+        //        self._fixupParents(rv)
+        //finally:
+        //    _releaseLock()
+        //return rv
+
+        
+        private static void _fixup_parents(ILogMulti root, ILog target)
+        {
+
+        }
+    }
+}

FLiOOPS.Logging/Properties/AssemblyInfo.cs

+ďťżusing System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("FLiOOPS.Logging")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("FLiOOPS project")]
+[assembly: AssemblyProduct("FLiOOPS.Logging")]
+[assembly: AssemblyCopyright("Copyright Š FLiOOPS project 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("4b179b56-e4ff-4511-b5bc-e52f1add9799")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

FLiOOPS.Logging/PyLogging.cs

+ďťżusing ComLib.Configuration;
+using ComLib.Logging;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace FLiOOPS.Logging
+{
+    /// <summary>
+    /// A logging setup implementation that mimics the rules 
+    /// considered by Python standard <code>logging</code> module. 
+    /// However, under some circumstances it can go beyond 
+    /// this specification and sometimes it may adopt .NET-specific 
+    /// rules and notations. This means that even if it will always 
+    /// be inspired in Python implementation, it is not designed 
+    /// to be interoperable with Python logging configuration files
+    /// (e.g. because of different object loading mechanisms, 
+    /// syntax and semantics).
+    /// </summary>
+    /// <remarks>
+    /// Python logging API is documented and available at this address
+    /// http://www.python.org/dev/peps/pep-0282 .
+    /// </remarks>
+    class PythonLoggingSetup : ILogSetup
+    {
+        protected IConfigSection section = null;
+        protected static Dictionary<object, object> default_opts {
+            get
+            {
+                return new Dictionary<object,object>()
+                    {
+                        {"overwrite", OverwriteMode.CLEAR}
+                    };
+            }
+        }
+
+        #region ILogSetup Members
+
+        /// <summary>
+        /// Install the equivalent of Python logging setup
+        /// globally.
+        /// </summary>
+        /// <remarks>
+        /// If no configuration source has been bound to this 
+        /// instance (<see cref="PythonLoggingSetup.Load(ComLib.Configuration.IConfigSection)"/>) 
+        /// then install the equivalent of Python default logging 
+        /// setup globally. Otherwise, it considers sections 
+        /// rules to recreate a custom logging environment.
+        /// </remarks>
+        /// <exception cref="System.Configuration.ConfigurationException">
+        /// A configuration error is raised is a name used for 
+        /// cross-reference purposes cannot be resolved.
+        /// </exception>
+        void ILogSetup.DefaultSetup()
+        {
+            (this as ILogSetup).CustomSetup(
+                new Dictionary<object, object>() {
+                    {"overwrite" , OverwriteMode.CLEAR}
+                });
+        }
+
+        /// <summary>
+        /// Install the equivalent of Python logging setup
+        /// globally.
+        /// </summary>
+        /// <param name="options">
+        /// This class does not define specific options.
+        /// See <seealso cref="ILogSetup.CustomSetup(IDictionary{object, object})"/>
+        /// for standard options.
+        /// </param>
+        /// <remarks>
+        /// The process may leave the loggers hierarchy in an 
+        /// partial intermediate state if e.g. an exception is 
+        /// raised during the configuration process.
+        /// <para>
+        /// If <c>"overwrite"</c> entry in <paramref name="options"/> 
+        /// is set to <see cref="OverwriteMode.CLEAR"/> then there 
+        /// will be no side effects. This means that the whole 
+        /// configuration will be applied if the method returns 
+        /// successfully.
+        /// </para>
+        /// <para>
+        /// If <c>"overwrite"</c> entry in <paramref name="options"/> 
+        /// is set to <see cref="OverwriteMode.OVERWRITE"/> 
+        /// or <see cref="OverwriteMode.IGNORE"/> this
+        /// method will try to apply so many rules as possible. 
+        /// This means that only part of the configuration 
+        /// may be applied if the method raises an exception.
+        /// </para>
+        /// </remarks>
+        void ILogSetup.CustomSetup(IDictionary<object, object> options)
+        {
+            object modename;
+            OverwriteMode mode = OverwriteMode.CLEAR;
+            if (options.TryGetValue("overwrite", out modename))
+                mode = (OverwriteMode)Enum.Parse(typeof(OverwriteMode), (string)modename);
+            options["overwrite"] = (int) mode;
+            if (section == null)
+                default_setup(options);
+            else
+                section_setup(options);
+        }
+        
+        /// <summary>
+        /// Load logging setup rules from configuration source.
+        /// </summary>
+        /// <param name="config">
+        /// Its sections are used to build log sources and arrange 
+        /// them in such a way that a consistent hierarchy of loggers 
+        /// may be built using a single method call.
+        /// </param>
+        void ILogSetup.Load(IConfigSection config)
+        {
+            section = config;
+        }
+
+        #endregion
+
+        #region Internal methods
+
+        /// <summary>
+        /// Setup logging in a way similar to Python root 
+        /// logger default configuration. Basically this means 
+        /// you'll end up with an empty <c>"root"</c> logger 
+        /// installed.
+        /// </summary>
+        /// <param name="options">
+        /// Supported options listed below (see 
+        /// <seealso cref="ILogSetup.CustomSetup(IDictionary{object, object})"/>
+        /// for further details).
+        /// 
+        /// <list type="table">
+        /// <item>
+        ///     <term>overwrite</term>
+        ///     <description>
+        ///     Flag to control whether to overwrite existing loggers.
+        ///     <seealso cref="OverwriteMode"/>
+        ///     </description>
+        /// </item>
+        /// </list>
+        /// 
+        /// </param>
+        protected virtual void default_setup(IDictionary<object, object> options)
+        {
+            OverwriteMode mode = (OverwriteMode)options["overwrite"];
+            bool overwrite = true;
+            switch (mode)
+            { 
+                case OverwriteMode.CLEAR:
+                    Logger.Clear();
+                    break;
+                case OverwriteMode.OVERWRITE:
+                    break;
+                case OverwriteMode.IGNORE:
+                    overwrite = Logger.Get("root") == null;
+                    break;
+            }
+            if (overwrite)
+            {
+                LogMulti root = new LogMulti("default", new List<ILog>());
+                Logger.Add(root);
+                root.Name = "root";
+                Logger.Add(root);
+            }
+        }
+
+        /// <summary>
+        /// Setup logging using custom configuration data.
+        /// </summary>
+        protected virtual void section_setup(IDictionary<object, object> options)
+        {
+            IDictionary<string, ILogFormatter> flist = _create_formatters();
+            IDictionary<string, ILog> hlist = _install_handlers(flist);
+            _install_loggers(hlist, options);
+        }
+
+        /// <summary>
+        /// Create and install loggers specified in configuration source.
+        /// </summary>
+        /// <param name="hlist">
+        /// List of (previously loaded 
+        /// <see cref="PythonLoggingSetup._install_handlers(IDictionary<string, LogFormatter>)"/>) 
+        /// log sources.
+        /// </param>
+        /// <param name="options">
+        /// Custom options <seealso cref="PythonLoggingSetup.CustomSetup()"/>.
+        /// </param>
+        /// <remarks>
+        /// Partial configuration may happen if exception is raised.
+        /// </remarks>
+        protected virtual void _install_loggers(IDictionary<string, ILog> hlist, 
+            IDictionary<object, object> options)
+        {
+            // Configure the root first
+            string[] llist = section.GetDefault("loggers", "keys", "")
+                .Trim().Split(new char[] {','})
+                .Distinct()
+                .Where(x => !x.Equals("root"))
+                .Select(x => x.Trim()).ToArray();
+            string sectname = "logger_root";
+            OverwriteMode overwrite = (OverwriteMode)options["overwrite"];
+            ILogMulti root = (overwrite == OverwriteMode.CLEAR)?
+                new LogMulti("default", new List<ILog>(llist.Length)) :
+                Logger.Default;
+            ILog log = root;
+            if (section.Contains(sectname, "level"))
+            {
+                try
+                {
+                    root.Level = LogHelper.GetLogLevel(section.Get<string>(sectname, "level"));
+                }
+                catch (Exception exc)
+                { 
+                    throw new ConfigurationException("Invalid logging level name", exc);
+                }
+            }
+            
+            string[] hids = section.GetDefault<string>(sectname, "handlers", "")
+                .Split(new char[] {','}).Distinct().Select(x => x.Trim()).ToArray();
+            switch (overwrite)
+            {
+                case OverwriteMode.CLEAR:
+                case OverwriteMode.OVERWRITE:
+                    foreach (ILog source in hids.Select(x => hlist[x]))
+                        root.Append(source);
+                    break;
+                case OverwriteMode.IGNORE:
+                    foreach (string hand in hids)
+                        if (root[hand] == null)
+                            root.Append(hlist[hand]);
+                    break;
+            }
+
+            // and now the others...
+            foreach (string lognm in llist)
+            {
+                sectname = "logger_" + lognm;
+                try
+                {
+                    string qn = section.Get<string>(sectname, "qualname");
+                }
+                catch (KeyNotFoundException exc)
+                { 
+                    throw new ConfigurationException("Logger qualified name missing in " + lognm,
+                        exc);
+                }
+                
+                // TODO: Does ILog support propagation control
+                //if "propagate" in opts:
+                //    propagate = cp.getint(sectname, "propagate")
+                //else:
+                //    propagate = 1
+            }
+
+    // Former Python code borrowed from stdlib !!! 
+
+    //for log in llist:
+    //    logger = logging.getLogger(qn)
+    //    if qn in existing:
+    //        i = existing.index(qn)
+    //        prefixed = qn + "."
+    //        pflen = len(prefixed)
+    //        num_existing = len(existing)
+    //        i = i + 1 # look at the entry after qn
+    //        while (i < num_existing) and (existing[i][:pflen] == prefixed):
+    //            child_loggers.append(existing[i])
+    //            i = i + 1
+    //        existing.remove(qn)
+    //    if "level" in opts:
+    //        level = cp.get(sectname, "level")
+    //        logger.setLevel(logging._levelNames[level])
+    //    for h in logger.handlers[:]:
+    //        logger.removeHandler(h)
+    //    logger.propagate = propagate
+    //    logger.disabled = 0
+    //    hlist = cp.get(sectname, "handlers")
+    //    if len(hlist):
+    //        hlist = string.split(hlist, ",")
+    //        hlist = _strip_spaces(hlist)
+    //        for hand in hlist:
+    //            logger.addHandler(handlers[hand])
+
+    //#Disable any old loggers. There's no point deleting
+    //#them as other threads may continue to hold references
+    //#and by disabling them, you stop them doing any logging.
+    //#However, don't disable children of named loggers, as that's
+    //#probably not what was intended by the user.
+    //for log in existing:
+    //    logger = root.manager.loggerDict[log]
+    //    if log in child_loggers:
+    //        logger.level = logging.NOTSET
+    //        logger.handlers = []
+    //        logger.propagate = 1
+    //    elif disable_existing_loggers:
+    //        logger.disabled = 1
+        }
+
+        /// <summary>
+        /// Install and return log sources
+        /// </summary>
+        /// <param name="flist">
+        /// Formatters list (<seealso cref="PythonLoggingSetup._create_formatters()"/>)
+        /// </param>
+        /// <returns>
+        /// A list of log sources setup according to rules read 
+        /// from configuration source. May be null if no log 
+        /// source is defined.
+        /// </returns>
+        protected virtual IDictionary<string, ILog> _install_handlers(
+            IDictionary<string, ILogFormatter> flist)
+        {
+            string[] hlist = section.GetDefault<string>("handlers", "keys", "")
+                .Trim().Split(new char[] { ',' }).Select(x => x.Trim()).ToArray();
+            if (hlist.Length == 0)
+                return null;
+            IDictionary<string, ILog> handlers = new Dictionary<string, ILog>(hlist.Length);
+
+            // TODO: ???
+            // fixups = [] #for inter-handler references
+
+            foreach (string hand in hlist)
+            {
+                string sectname = "handler_" + hand;
+                string klass = section.GetDefault<string>(sectname, "class", "");
+                string fmt = section.GetDefault<string>(sectname, "formatter", "");
+                object[] args = section.GetDefault<string>(sectname, "args", "")
+                    .Trim().Split(new char[] { ',' }).Select(x => _resolve(x.Trim(), null)).ToArray();
+
+                ILog source = _resolve(klass, null, args) as ILog;
+                // FIXME: Name readonly !!!
+                //source.Name = hand;
+
+                string levelname = section.GetDefault<string>(sectname, "level", "");
+                LogLevel level = LogLevel.Info;
+                try
+                {
+                    level = LogHelper.GetLogLevel(levelname);
+                }
+                catch (Exception)
+                { }
+                source.Level = level;
+                if (!string.IsNullOrEmpty(fmt))
+                    try
+                    {
+                        ILogFormatter f = flist[fmt];
+                        // TODO: Bind the formatter to this log source.
+                    }
+                    catch (KeyNotFoundException exc)
+                    {
+                        throw new ConfigurationException("Unknown formatter name: " + fmt, exc);
+                    }
+
+                // TODO: What about this MemoryHandler stuff ?
+                //if issubclass(klass, logging.handlers.MemoryHandler):
+                //    if "target" in opts:
+                //        target = cp.get(sectname,"target")
+                //    else:
+                //        target = ""
+                //    if len(target): #the target handler may not be loaded yet, so keep for later...
+                //        fixups.append((h, target))
+
+                handlers[hand] = source;
+            }
+
+            // TODO: Follow-up to the previous handlers stuff
+            //#now all handlers are loaded, fixup inter-handler references...
+            //for h, t in fixups:
+            //    h.setTarget(handlers[t])
+
+            return handlers;
+        }
+
+        // TODO: Assign correct value
+        const string DEFAULT_FMTSTR = "";
+        const string DEFAULT_DATESTR = "";
+
+        /// <summary>
+        /// Create and return formatters
+        /// </summary>
+        /// <returns>Dictionary mapping formatters using identifiers</returns>
+        protected virtual IDictionary<string, ILogFormatter> _create_formatters()
+        { 
+            string  flist = section.GetDefault<string>("formatters", "keys", "");
+            flist = flist.Trim();
+            if (string.IsNullOrEmpty(flist))
+                return null;
+            string[] fids = flist.Split(new char[] {','}).Select(x => x.Trim()).ToArray();
+            IDictionary<string, ILogFormatter> formatters = 
+                new Dictionary<string, ILogFormatter>(fids.Length);
+            foreach (string form in fids)
+            {
+                string sectname = "formatter_" + form;
+                string fs = section.GetDefault<string>(sectname, "format", 
+                    DEFAULT_FMTSTR);
+                string dfs = section.GetDefault<string>(sectname, "datefmt", 
+                    DEFAULT_DATESTR);
+                string fmtcls = section.GetDefault<string>(sectname, "class", "");
+                
+                // TODO: Finish
+                //ILogFormatter logfmt = _resolve(fmtcls, typeof(), fs, dfs) as ILogFormatter;
+                //formatters[form] = logfmt;
+            }
+            return formatters;
+        }
+
+        /// <summary>
+        /// Instantiate an object specified in a configuration file.
+        /// </summary>
+        /// <param name="typename">
+        /// Full name of the target type that should be instantiated.
+        /// Used to lookup the type definition following .NET built-in 
+        /// Fully Qualified Type Names syntax.
+        /// </param>
+        /// <param name="deftype">
+        /// Default type used in case <paramref name="typename"/> is 
+        /// <c>null</c> or <c>string.Empty</c> .
+        /// </param>
+        /// <param name="args">
+        /// Objects array used to identify a constructor which will be
+        /// invoked by supplying them in as positional arguments.
+        /// </param>
+        /// <returns>
+        /// <c>Object</c> instance obtained after invoking the 
+        /// corresponding constructor of the target <paramref name="typename"/>
+        /// or default type (i.e. <paramref name="deftype"/>).
+        /// </returns>
+        protected virtual object _resolve(string typename, Type deftype, params object[] args)
+        {
+            Type target;
+            
+            if (string.IsNullOrEmpty(typename))
+            {
+                target = deftype;
+            }
+            // TODO: Load and instantiate object using `target` type
+            return null;
+        }
+
+        #endregion
+    }
+}
+ďťż
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FLiOOPS.Logging", "FLiOOPS.Logging\FLiOOPS.Logging.csproj", "{E470C80B-360D-4A2C-8520-0A1E9E87BC95}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FLiOOPS.Wcf", "FLiOOPS.Wcf\FLiOOPS.Wcf.csproj", "{6ED38C41-4F21-41F4-9971-1E26FE859CAB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UploadHelper", "UploadHelper\UploadHelper.csproj", "{02FBD52C-B997-4D18-9E2C-81B5AE8EFB30}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FLiOOPS.Core", "FLiOOPS.Core\FLiOOPS.Core.csproj", "{7F300232-D477-4400-A6C5-387089805167}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E470C80B-360D-4A2C-8520-0A1E9E87BC95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E470C80B-360D-4A2C-8520-0A1E9E87BC95}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E470C80B-360D-4A2C-8520-0A1E9E87BC95}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E470C80B-360D-4A2C-8520-0A1E9E87BC95}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6ED38C41-4F21-41F4-9971-1E26FE859CAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6ED38C41-4F21-41F4-9971-1E26FE859CAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6ED38C41-4F21-41F4-9971-1E26FE859CAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6ED38C41-4F21-41F4-9971-1E26FE859CAB}.Release|Any CPU.Build.0 = Release|Any CPU
+		{02FBD52C-B997-4D18-9E2C-81B5AE8EFB30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{02FBD52C-B997-4D18-9E2C-81B5AE8EFB30}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{02FBD52C-B997-4D18-9E2C-81B5AE8EFB30}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{02FBD52C-B997-4D18-9E2C-81B5AE8EFB30}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7F300232-D477-4400-A6C5-387089805167}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7F300232-D477-4400-A6C5-387089805167}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7F300232-D477-4400-A6C5-387089805167}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7F300232-D477-4400-A6C5-387089805167}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

FLiOOPS.NET.suo

Binary file added.

FLiOOPS.Wcf/FLiOOPS.Wcf.csproj

+ďťż<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{6ED38C41-4F21-41F4-9971-1E26FE859CAB}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>FLiOOPS.Wcf</RootNamespace>
+    <AssemblyName>FLiOOPS.Wcf</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.configuration" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Runtime.Serialization">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.ServiceModel">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>