Example #1
0
 internal static void Add(List <PropertyUpdateXML> updates, ProviderPropertyDefinition pdef, object value, PropertyUpdateOperation op)
 {
     updates.Add(new PropertyUpdateXML
     {
         Operation = op,
         Property  = PropertyXML.Create(pdef, value)
     });
 }
Example #2
0
        private void UpdateSharedObject(PropertyChangedPayload data)
        {
            Debug.Assert(this.client.CheckAccess());

            ObjectEntry entry = null;

            try
            {
                if (!this.TryGetValue(data.ObjectId, out entry))
                {
                    // Received update for an object we are not tracking
                    Debug.WriteLine("[PropertyChanged] Missing shared object for update in incoming event.");
                    return;
                }

                SharedProperty property = entry.IsDynamic ? entry.Properties[data.PropertyName] : entry.Properties[data.PropertyIndex];

                // In case of dynamic properties, this could be the first time this property is seen
                if (property == null && entry.IsDynamic)
                {
                    property = new SharedProperty()
                    {
                        Attributes   = new SharedAttributes(),
                        Index        = (short)entry.Properties.Count,
                        Name         = data.PropertyName,
                        ETag         = new ETag(this.client.ClientId),
                        PropertyType = data.PropertyType
                    };
                    entry.Properties.Add(property.Index, property);
                }

                // Ignore changes for given object, add to list
                entry.IgnoreChanges = true;

                // Don't apply update if we made it locally
                bool applyUpdate      = data.ClientId != this.client.ClientId;
                bool conflictDetected = false;

                PropertyUpdateOperation matchingUpdate = property.LocalUpdates.Where(x => x.Payload.Equals(data)).FirstOrDefault();
                if (matchingUpdate != null)
                {
                    // Remove update from pending list
                    Debug.WriteLine("[PropertyChanged] Received acknowledgement of matching property update");
                    if (matchingUpdate.ReapplyUpdate)
                    {
                        applyUpdate = true;
                    }
                    property.LocalUpdates.Remove(matchingUpdate);
                }
                // Check for conflict, but won't stop us from applying update
                conflictDetected = data.IsConflict(property.LocalUpdates) &&
                                   !property.IsServerAppliedProperty() && (property.Attributes.ConcurrencyAttribute != ConcurrencyPolicy.Overwrite);

                if (applyUpdate)
                {
                    // Mark pending updates to re-apply if we are applying a change from another endpoint
                    if (data.ClientId != this.client.ClientId)
                    {
                        property.LocalUpdates.ForEach(x => x.ReapplyUpdate = true);
                    }
                    if (entry.IsDynamic)
                    {
                        var dictionary = entry.Object as IDictionary <string, object>;
                        if (dictionary == null)
                        {
                            throw new ArgumentException("Dictionary is null");
                        }

                        // Insert up-to-date value for property
                        dictionary[data.PropertyName] = Json.ReadObject(DynamicTypeMapping.Instance.GetTypeFromValue(data.PropertyType), data.PropertyValue);
                    }
                    else
                    {
                        Json.AssignProperty(entry.Object, property.Name, data.PropertyValue);
                    }
                    property.Value = data.PropertyValue;
                }
                property.ETag = data.ETag;

                if (conflictDetected)
                {
                    Debug.WriteLine("[PropertyChanged] Conflict detected on property update");
                    IEnumerable <PropertyChangedPayload> rejectedUpdates = property.LocalUpdates.Select(x => x.Payload);
                    if (property.Attributes.ConcurrencyAttribute == ConcurrencyPolicy.RejectAndNotify)
                    {
                        var notify = new ConcurrencyUpdateRejectedEventArgs(entry.Object, property.Name, rejectedUpdates.Select(x => Json.ReadProperty(entry.Object, property.Name, x.PropertyValue)));
                        this.client.RaiseError(notify);
                    }
                    property.LocalUpdates.Clear();
                }
            }
            finally
            {
                if (entry != null)
                {
                    entry.IgnoreChanges = false;
                }
            }
        }
Example #3
0
 internal bool IsConflict(PropertyUpdateOperation other)
 {
     return (this.ObjectId == other.Payload.ObjectId)
            && (this.PropertyIndex == other.Payload.PropertyIndex)
            && (this.ClientId != other.Payload.ClientId);
 }
Example #4
0
        internal bool TryApplyChange(ProviderPropertyDefinition pdef, ConfigurableObject targetObject, PropertyUpdateOperation op)
        {
            object obj = null;

            if (this.TryGetValue(pdef, out obj))
            {
                Exception ex = null;
                try
                {
                    if (op == PropertyUpdateOperation.Replace)
                    {
                        object obj2 = targetObject[pdef];
                        if ((!object.Equals(obj, pdef.DefaultValue) || obj2 != null) && !object.Equals(obj2, obj))
                        {
                            if (pdef == ADObjectSchema.ExchangeVersion)
                            {
                                targetObject.SetExchangeVersion((ExchangeObjectVersion)obj);
                            }
                            else
                            {
                                targetObject[pdef] = obj;
                            }
                        }
                    }
                    else
                    {
                        MultiValuedPropertyBase multiValuedPropertyBase  = obj as MultiValuedPropertyBase;
                        MultiValuedPropertyBase multiValuedPropertyBase2 = targetObject[pdef] as MultiValuedPropertyBase;
                        if (multiValuedPropertyBase != null && multiValuedPropertyBase2 != null)
                        {
                            foreach (object item in ((IEnumerable)multiValuedPropertyBase))
                            {
                                switch (op)
                                {
                                case PropertyUpdateOperation.AddValues:
                                    multiValuedPropertyBase2.Add(item);
                                    break;

                                case PropertyUpdateOperation.RemoveValues:
                                    multiValuedPropertyBase2.Remove(item);
                                    break;
                                }
                            }
                        }
                    }
                    return(true);
                }
                catch (DataValidationException ex2)
                {
                    ex = ex2;
                }
                catch (ArgumentException ex3)
                {
                    ex = ex3;
                }
                catch (FormatException ex4)
                {
                    ex = ex4;
                }
                catch (LocalizedException ex5)
                {
                    ex = ex5;
                }
                if (ex != null)
                {
                    MrsTracer.Common.Warning("Property {0} could not be set to '{1}', error {2}", new object[]
                    {
                        pdef.Name,
                        obj,
                        CommonUtils.FullExceptionMessage(ex)
                    });
                    return(false);
                }
                return(false);
            }
            return(false);
        }