1 // 2 // Copyright (c) ZeroC, Inc. All rights reserved. 3 // 4 5 using System; 6 using System.Collections.Generic; 7 8 namespace Ice 9 { 10 11 public interface PropertiesAdminUpdateCallback 12 { updated(Dictionary<string, string> changes)13 void updated(Dictionary<string, string> changes); 14 } 15 16 public interface NativePropertiesAdmin 17 { 18 [Obsolete("This method is deprecated. Use addUpdateCallback(System.Action<Dictionary<string, string>> callback) instead.")] addUpdateCallback(PropertiesAdminUpdateCallback callback)19 void addUpdateCallback(PropertiesAdminUpdateCallback callback); 20 21 [Obsolete("This method is deprecated. Use removeUpdateCallback(System.Action<Dictionary<string, string>> callback) instead.")] removeUpdateCallback(PropertiesAdminUpdateCallback callback)22 void removeUpdateCallback(PropertiesAdminUpdateCallback callback); 23 addUpdateCallback(System.Action<Dictionary<string, string>> callback)24 void addUpdateCallback(System.Action<Dictionary<string, string>> callback); 25 removeUpdateCallback(System.Action<Dictionary<string, string>> callback)26 void removeUpdateCallback(System.Action<Dictionary<string, string>> callback); 27 } 28 29 } 30 31 namespace IceInternal 32 { 33 sealed class PropertiesAdminI : Ice.PropertiesAdminDisp_, Ice.NativePropertiesAdmin 34 { PropertiesAdminI(Instance instance)35 internal PropertiesAdminI(Instance instance) 36 { 37 _properties = instance.initializationData().properties; 38 _logger = instance.initializationData().logger; 39 } 40 41 public override string getProperty(string name, Ice.Current current)42 getProperty(string name, Ice.Current current) 43 { 44 return _properties.getProperty(name); 45 } 46 47 public override Dictionary<string, string> getPropertiesForPrefix(string name, Ice.Current current)48 getPropertiesForPrefix(string name, Ice.Current current) 49 { 50 return _properties.getPropertiesForPrefix(name); 51 } 52 53 public override void setProperties(Dictionary<string, string> props, Ice.Current current)54 setProperties(Dictionary<string, string> props, Ice.Current current) 55 { 56 lock(this) 57 { 58 Dictionary<string, string> old = _properties.getPropertiesForPrefix(""); 59 int traceLevel = _properties.getPropertyAsInt("Ice.Trace.Admin.Properties"); 60 61 // 62 // Compute the difference between the new property set and the existing property set: 63 // 64 // 1) Any properties in the new set that were not defined in the existing set. 65 // 66 // 2) Any properties that appear in both sets but with different values. 67 // 68 // 3) Any properties not present in the new set but present in the existing set. 69 // In other words, the property has been removed. 70 // 71 Dictionary<string, string> added = new Dictionary<string, string>(); 72 Dictionary<string, string> changed = new Dictionary<string, string>(); 73 Dictionary<string, string> removed = new Dictionary<string, string>(); 74 foreach(KeyValuePair<string, string> e in props) 75 { 76 string key = e.Key; 77 string value = e.Value; 78 if(!old.ContainsKey(key)) 79 { 80 if(value.Length > 0) 81 { 82 // 83 // This property is new. 84 // 85 added.Add(key, value); 86 } 87 } 88 else 89 { 90 string v; 91 if(!old.TryGetValue(key, out v) || !value.Equals(v)) 92 { 93 if(value.Length == 0) 94 { 95 // 96 // This property was removed. 97 // 98 removed.Add(key, value); 99 } 100 else 101 { 102 // 103 // This property has changed. 104 // 105 changed.Add(key, value); 106 } 107 } 108 109 old.Remove(key); 110 } 111 } 112 113 if(traceLevel > 0 && (added.Count > 0 || changed.Count > 0 || removed.Count > 0)) 114 { 115 System.Text.StringBuilder message = new System.Text.StringBuilder("Summary of property changes"); 116 117 if(added.Count > 0) 118 { 119 message.Append("\nNew properties:"); 120 foreach(KeyValuePair<string, string> e in added) 121 { 122 message.Append("\n "); 123 message.Append(e.Key); 124 if(traceLevel > 1) 125 { 126 message.Append(" = "); 127 message.Append(e.Value); 128 } 129 } 130 } 131 132 if(changed.Count > 0) 133 { 134 message.Append("\nChanged properties:"); 135 foreach(KeyValuePair<string, string> e in changed) 136 { 137 message.Append("\n "); 138 message.Append(e.Key); 139 if(traceLevel > 1) 140 { 141 message.Append(" = "); 142 message.Append(e.Value); 143 message.Append(" (old value = "); 144 message.Append(_properties.getProperty(e.Key)); 145 message.Append(")"); 146 } 147 } 148 } 149 150 if(removed.Count > 0) 151 { 152 message.Append("\nRemoved properties:"); 153 foreach(KeyValuePair<string, string> e in removed) 154 { 155 message.Append("\n "); 156 message.Append(e.Key); 157 } 158 } 159 160 _logger.trace(_traceCategory, message.ToString()); 161 } 162 163 // 164 // Update the property set. 165 // 166 167 foreach(KeyValuePair<string, string> e in added) 168 { 169 _properties.setProperty(e.Key, e.Value); 170 } 171 172 foreach(KeyValuePair<string, string> e in changed) 173 { 174 _properties.setProperty(e.Key, e.Value); 175 } 176 177 foreach(KeyValuePair<string, string> e in removed) 178 { 179 _properties.setProperty(e.Key, ""); 180 } 181 182 if(_deprecatedUpdateCallbacks.Count > 0 || _updateCallbacks.Count > 0) 183 { 184 Dictionary<string, string> changes = new Dictionary<string, string>(added); 185 foreach(KeyValuePair<string, string> e in changed) 186 { 187 changes.Add(e.Key, e.Value); 188 } 189 foreach(KeyValuePair<string, string> e in removed) 190 { 191 changes.Add(e.Key, e.Value); 192 } 193 194 // Copy callbacks to allow callbacks to update callbacks 195 foreach(var callback in new List<Ice.PropertiesAdminUpdateCallback>(_deprecatedUpdateCallbacks)) 196 { 197 try 198 { 199 callback.updated(changes); 200 } 201 catch(Exception ex) 202 { 203 if(_properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 1) 204 { 205 _logger.warning("properties admin update callback raised unexpected exception:\n" + ex); 206 } 207 } 208 } 209 // Copy callbacks to allow callbacks to update callbacks 210 foreach(var callback in new List<System.Action<Dictionary<string, string>>>(_updateCallbacks)) 211 { 212 try 213 { 214 callback(changes); 215 } 216 catch(Exception ex) 217 { 218 if(_properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 1) 219 { 220 _logger.warning("properties admin update callback raised unexpected exception:\n" + ex); 221 } 222 } 223 } 224 } 225 } 226 } 227 addUpdateCallback(Ice.PropertiesAdminUpdateCallback cb)228 public void addUpdateCallback(Ice.PropertiesAdminUpdateCallback cb) 229 { 230 lock(this) 231 { 232 _deprecatedUpdateCallbacks.Add(cb); 233 } 234 } 235 removeUpdateCallback(Ice.PropertiesAdminUpdateCallback cb)236 public void removeUpdateCallback(Ice.PropertiesAdminUpdateCallback cb) 237 { 238 lock(this) 239 { 240 _deprecatedUpdateCallbacks.Remove(cb); 241 } 242 } 243 addUpdateCallback(System.Action<Dictionary<string, string>> cb)244 public void addUpdateCallback(System.Action<Dictionary<string, string>> cb) 245 { 246 lock(this) 247 { 248 _updateCallbacks.Add(cb); 249 } 250 } 251 removeUpdateCallback(System.Action<Dictionary<string, string>> cb)252 public void removeUpdateCallback(System.Action<Dictionary<string, string>> cb) 253 { 254 lock(this) 255 { 256 _updateCallbacks.Remove(cb); 257 } 258 } 259 260 private readonly Ice.Properties _properties; 261 private readonly Ice.Logger _logger; 262 private List<Ice.PropertiesAdminUpdateCallback> _deprecatedUpdateCallbacks = 263 new List<Ice.PropertiesAdminUpdateCallback>(); 264 private List<System.Action<Dictionary<string, string>>> _updateCallbacks = 265 new List<System.Action<Dictionary<string, string>>>(); 266 267 private static readonly string _traceCategory = "Admin.Properties"; 268 } 269 } 270