The Labs \ Source Viewer \ SSCLI \ System.Diagnostics \ ListenerElement

  1. //------------------------------------------------------------------------------
  2. // <copyright file="ListenerElementsCollection.cs" company="Microsoft Corporation">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System.Configuration;
  16. using System;
  17. using System.Reflection;
  18. using System.Globalization;
  19. using System.Xml;
  20. using System.Collections.Specialized;
  21. using System.Collections;
  22. using System.Security;
  23. using System.Security.Permissions;
  24. namespace System.Diagnostics
  25. {
  26.     [ConfigurationCollection(typeof(ListenerElement))]
  27.     internal class ListenerElementsCollection : ConfigurationElementCollection
  28.     {
  29.        
  30.         public new ListenerElement this[string name]
  31.         {
  32.             get { return (ListenerElement)BaseGet(name); }
  33.         }
  34.        
  35.         public override ConfigurationElementCollectionType CollectionType {
  36.             get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
  37.         }
  38.        
  39.         protected override ConfigurationElement CreateNewElement()
  40.         {
  41.             return new ListenerElement(true);
  42.         }
  43.        
  44.         protected override object GetElementKey(ConfigurationElement element)
  45.         {
  46.             return ((ListenerElement)element).Name;
  47.         }
  48.        
  49.         public TraceListenerCollection GetRuntimeObject()
  50.         {
  51.             TraceListenerCollection listeners = new TraceListenerCollection();
  52.             bool _isDemanded = false;
  53.            
  54.             foreach (ListenerElement element in this) {
  55.                
  56.                 // At some point, we need to pull out adding/removing the 'default' DefaultTraceListener
  57.                 // code from here in favor of adding/not-adding after we load the config (in TraceSource
  58.                 // and in static Trace)
  59.                
  60.                 if (!_isDemanded && !element._isAddedByDefault) {
  61.                     // Do a full damand; This will disable partially trusted code from hooking up listeners
  62.                     new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
  63.                     _isDemanded = true;
  64.                 }
  65.                
  66.                 listeners.Add(element.GetRuntimeObject());
  67.             }
  68.            
  69.             return listeners;
  70.         }
  71.        
  72.         protected override void InitializeDefault()
  73.         {
  74.             InitializeDefaultInternal();
  75.         }
  76.        
  77.         internal void InitializeDefaultInternal()
  78.         {
  79.             ListenerElement defaultListener = new ListenerElement(false);
  80.             defaultListener.Name = "Default";
  81.             defaultListener.TypeName = typeof(DefaultTraceListener).FullName;
  82.             defaultListener._isAddedByDefault = true;
  83.            
  84.             this.BaseAdd(defaultListener);
  85.         }
  86.        
  87.         protected override void BaseAdd(ConfigurationElement element)
  88.         {
  89.             ListenerElement listenerElement = element as ListenerElement;
  90.            
  91.             Debug.Assert((listenerElement != null), "adding elements other than ListenerElement to ListenerElementsCollection?");
  92.            
  93.             if (listenerElement.Name.Equals("Default") && listenerElement.TypeName.Equals(typeof(DefaultTraceListener).FullName))
  94.                 BaseAdd(listenerElement, false);
  95.             else
  96.                 BaseAdd(listenerElement, ThrowOnDuplicate);
  97.         }
  98.     }
  99.    
  100.     // This is the collection used by the sharedListener section. It is only slightly different from ListenerElementsCollection.
  101.     // The differences are that it does not allow remove and clear, and that the ListenerElements it creates do not allow
  102.     // references.
  103.     [ConfigurationCollection(typeof(ListenerElement), AddItemName = "add", CollectionType = ConfigurationElementCollectionType.BasicMap)]
  104.     internal class SharedListenerElementsCollection : ListenerElementsCollection
  105.     {
  106.        
  107.         public override ConfigurationElementCollectionType CollectionType {
  108.             get { return ConfigurationElementCollectionType.BasicMap; }
  109.         }
  110.        
  111.         protected override ConfigurationElement CreateNewElement()
  112.         {
  113.             return new ListenerElement(false);
  114.         }
  115.        
  116.         protected override string ElementName {
  117.             get { return "add"; }
  118.         }
  119.     }
  120.    
  121.     internal class ListenerElement : TypedElement
  122.     {
  123.         private static readonly ConfigurationProperty _propFilter = new ConfigurationProperty("filter", typeof(FilterElement), null, ConfigurationPropertyOptions.None);
  124.         private static readonly ConfigurationProperty _propName = new ConfigurationProperty("name", typeof(string), null, ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
  125.         private static readonly ConfigurationProperty _propOutputOpts = new ConfigurationProperty("traceOutputOptions", typeof(TraceOptions), TraceOptions.None, ConfigurationPropertyOptions.None);
  126.        
  127.         private ConfigurationProperty _propListenerTypeName;
  128.         private bool _allowReferences;
  129.         private Hashtable _attributes;
  130.         internal bool _isAddedByDefault;
  131.        
  132.         static ListenerElement()
  133.         {
  134.         }
  135.        
  136.         public ListenerElement(bool allowReferences) : base(typeof(TraceListener))
  137.         {
  138.             _allowReferences = allowReferences;
  139.            
  140.             ConfigurationPropertyOptions flags = ConfigurationPropertyOptions.None;
  141.             if (!_allowReferences)
  142.                 flags |= ConfigurationPropertyOptions.IsRequired;
  143.            
  144.             _propListenerTypeName = new ConfigurationProperty("type", typeof(string), null, flags);
  145.            
  146.             _properties.Remove("type");
  147.             _properties.Add(_propListenerTypeName);
  148.             _properties.Add(_propFilter);
  149.             _properties.Add(_propName);
  150.             _properties.Add(_propOutputOpts);
  151.         }
  152.        
  153.         public Hashtable Attributes {
  154.             get {
  155.                 if (_attributes == null)
  156.                     _attributes = new Hashtable(StringComparer.OrdinalIgnoreCase);
  157.                 return _attributes;
  158.             }
  159.         }
  160.        
  161.         [ConfigurationProperty("filter")]
  162.         public FilterElement Filter {
  163.             get { return (FilterElement)this[_propFilter]; }
  164.         }
  165.        
  166.         [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
  167.         public string Name {
  168.             get { return (string)this[_propName]; }
  169.             set { this[_propName] = value; }
  170.         }
  171.        
  172.         [ConfigurationProperty("traceOutputOptions", DefaultValue = (TraceOptions)TraceOptions.None)]
  173.         public TraceOptions TraceOutputOptions {
  174.             get { return (TraceOptions)this[_propOutputOpts]; }
  175.             // This is useful when the OM becomes public. In the meantime, this can be utilized via reflection
  176.             set { this[_propOutputOpts] = value; }
  177.         }
  178.        
  179.        
  180.         [ConfigurationProperty("type")]
  181.         public override string TypeName {
  182.             get { return (string)this[_propListenerTypeName]; }
  183.             set { this[_propListenerTypeName] = value; }
  184.         }
  185.        
  186.         public override bool Equals(object compareTo)
  187.         {
  188.             if (this.Name.Equals("Default") && this.TypeName.Equals(typeof(DefaultTraceListener).FullName)) {
  189.                 // This is a workaround to treat all DefaultTraceListener named 'Default' the same.
  190.                 // This is needed for the Config.Save to work properly as otherwise config base layers
  191.                 // above us would run into duplicate 'Default' listener element and perceive it as
  192.                 // error.
  193.                 ListenerElement compareToElem = compareTo as ListenerElement;
  194.                 return (compareToElem != null) && compareToElem.Name.Equals("Default") && compareToElem.TypeName.Equals(typeof(DefaultTraceListener).FullName);
  195.             }
  196.             else
  197.                 return base.Equals(compareTo);
  198.         }
  199.        
  200.         public override int GetHashCode()
  201.         {
  202.             return base.GetHashCode();
  203.         }
  204.        
  205.         public TraceListener GetRuntimeObject()
  206.         {
  207.             if (_runtimeObject != null)
  208.                 return (TraceListener)_runtimeObject;
  209.            
  210.             try {
  211.                 string className = TypeName;
  212.                 if (String.IsNullOrEmpty(className)) {
  213.                     // Look it up in SharedListeners
  214.                     Debug.Assert(_allowReferences, "_allowReferences must be true if type name is null");
  215.                    
  216.                     if (_attributes != null || ElementInformation.Properties[_propFilter.Name].ValueOrigin == PropertyValueOrigin.SetHere || TraceOutputOptions != TraceOptions.None || !String.IsNullOrEmpty(InitData))
  217.                         throw new ConfigurationErrorsException(SR.GetString(SR.Reference_listener_cant_have_properties, Name));
  218.                    
  219.                     if (DiagnosticsConfiguration.SharedListeners == null)
  220.                         throw new ConfigurationErrorsException(SR.GetString(SR.Reference_to_nonexistent_listener, Name));
  221.                    
  222.                     ListenerElement sharedListener = DiagnosticsConfiguration.SharedListeners[Name];
  223.                     if (sharedListener == null)
  224.                         throw new ConfigurationErrorsException(SR.GetString(SR.Reference_to_nonexistent_listener, Name));
  225.                     else {
  226.                         _runtimeObject = sharedListener.GetRuntimeObject();
  227.                         return (TraceListener)_runtimeObject;
  228.                     }
  229.                 }
  230.                 else {
  231.                     // create a new one
  232.                     TraceListener newListener = (TraceListener)BaseGetRuntimeObject();
  233.                     newListener.initializeData = InitData;
  234.                     newListener.Name = Name;
  235.                     newListener.SetAttributes(Attributes);
  236.                     newListener.TraceOutputOptions = TraceOutputOptions;
  237.                    
  238.                     if ((Filter != null) && (Filter.TypeName != null) && (Filter.TypeName.Length != 0))
  239.                         newListener.Filter = Filter.GetRuntimeObject();
  240.                    
  241.                     _runtimeObject = newListener;
  242.                     return newListener;
  243.                 }
  244.             }
  245.             catch (ArgumentException e) {
  246.                 throw new ConfigurationErrorsException(SR.GetString(SR.Could_not_create_listener, Name), e);
  247.             }
  248.         }
  249.        
  250.         protected override bool OnDeserializeUnrecognizedAttribute(string name, string value)
  251.         {
  252.             ConfigurationProperty _propDynamic = new ConfigurationProperty(name, typeof(string), value);
  253.             _properties.Add(_propDynamic);
  254.             base[_propDynamic] = value;
  255.             // Add them to the property bag
  256.             Attributes.Add(name, value);
  257.             return true;
  258.         }
  259.        
  260.         internal void ResetProperties()
  261.         {
  262.             // blow away any UnrecognizedAttributes that we have deserialized earlier
  263.             if (_attributes != null) {
  264.                 _attributes.Clear();
  265.                 _properties.Clear();
  266.                 _properties.Add(_propListenerTypeName);
  267.                 _properties.Add(_propFilter);
  268.                 _properties.Add(_propName);
  269.                 _properties.Add(_propOutputOpts);
  270.             }
  271.         }
  272.        
  273.         internal TraceListener RefreshRuntimeObject(TraceListener listener)
  274.         {
  275.             _runtimeObject = null;
  276.             try {
  277.                 string className = TypeName;
  278.                 if (String.IsNullOrEmpty(className)) {
  279.                     // Look it up in SharedListeners and ask the sharedListener to refresh.
  280.                     Debug.Assert(_allowReferences, "_allowReferences must be true if type name is null");
  281.                    
  282.                     if (_attributes != null || ElementInformation.Properties[_propFilter.Name].ValueOrigin == PropertyValueOrigin.SetHere || TraceOutputOptions != TraceOptions.None || !String.IsNullOrEmpty(InitData))
  283.                         throw new ConfigurationErrorsException(SR.GetString(SR.Reference_listener_cant_have_properties, Name));
  284.                    
  285.                     if (DiagnosticsConfiguration.SharedListeners == null)
  286.                         throw new ConfigurationErrorsException(SR.GetString(SR.Reference_to_nonexistent_listener, Name));
  287.                    
  288.                     ListenerElement sharedListener = DiagnosticsConfiguration.SharedListeners[Name];
  289.                     if (sharedListener == null)
  290.                         throw new ConfigurationErrorsException(SR.GetString(SR.Reference_to_nonexistent_listener, Name));
  291.                     else {
  292.                         _runtimeObject = sharedListener.RefreshRuntimeObject(listener);
  293.                         return (TraceListener)_runtimeObject;
  294.                     }
  295.                 }
  296.                 else {
  297.                     // We're the element with the type and initializeData info. First see if those two are the same as they were.
  298.                     // If not, create a whole new object, otherwise, just update the other properties.
  299.                     if (Type.GetType(className) != listener.GetType() || InitData != listener.initializeData) {
  300.                         // type or initdata changed
  301.                         return GetRuntimeObject();
  302.                     }
  303.                     else {
  304.                         listener.SetAttributes(Attributes);
  305.                         listener.TraceOutputOptions = TraceOutputOptions;
  306.                        
  307.                         if (ElementInformation.Properties[_propFilter.Name].ValueOrigin == PropertyValueOrigin.SetHere)
  308.                             listener.Filter = Filter.RefreshRuntimeObject(listener.Filter);
  309.                         else
  310.                             listener.Filter = null;
  311.                        
  312.                         _runtimeObject = listener;
  313.                         return listener;
  314.                     }
  315.                 }
  316.             }
  317.             catch (ArgumentException e) {
  318.                 throw new ConfigurationErrorsException(SR.GetString(SR.Could_not_create_listener, Name), e);
  319.             }
  320.            
  321.         }
  322.        
  323.     }
  324. }

Developer Fusion