コード例 #1
0
        public void MergeAddToExistingAttribute()
        {
            UpdateImpl up = new UpdateImpl(null, null);
            ICollection <ConnectorAttribute> actual;
            ICollection <ConnectorAttribute> baseAttrs = CollectionUtil.NewSet <ConnectorAttribute>();
            ICollection <ConnectorAttribute> expected  = CollectionUtil.NewSet <ConnectorAttribute>();
            ICollection <ConnectorAttribute> changeset = CollectionUtil.NewSet <ConnectorAttribute>();
            // attempt to add a value to an attribute..
            ConnectorAttribute battr = ConnectorAttributeBuilder.Build("abc", 1);
            ConnectorAttribute cattr = ConnectorAttributeBuilder.Build("abc", 2);

            baseAttrs.Add(battr);
            changeset.Add(cattr);
            expected.Add(ConnectorAttributeBuilder.Build("abc", 1, 2));
            actual = up.Merge(changeset, baseAttrs, true);
            Assert.IsTrue(AreEqual(expected, actual));
        }
コード例 #2
0
        public void TestSimplifyNoAndNoOrNoLeaf()
        {
            Filter a =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("a", "a"));
            Filter b =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("b", "b"));
            Filter c =
                FilterBuilder.EndsWith(ConnectorAttributeBuilder.Build("c", "c"));
            Filter d =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("d", "d"));

            Filter filter =
                FilterBuilder.And(
                    FilterBuilder.Or(a, b),
                    FilterBuilder.Or(c, d));
            IList <String> results =
                new NoAndNoOrNoEndsWithTranslator().Translate(filter);

            Assert.AreEqual(2, results.Count);
            Assert.AreEqual("( CONTAINS a a )",
                            results[0]);
            Assert.AreEqual("( CONTAINS b b )",
                            results[1]);

            a =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("a", "a"));
            b =
                FilterBuilder.EndsWith(ConnectorAttributeBuilder.Build("b", "b"));
            c =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("c", "c"));
            d =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("d", "d"));
            filter =
                FilterBuilder.And(
                    FilterBuilder.Or(a, b),
                    FilterBuilder.Or(c, d));
            results =
                new NoAndNoOrNoEndsWithTranslator().Translate(filter);
            Assert.AreEqual(2, results.Count);
            Assert.AreEqual("( CONTAINS c c )",
                            results[0]);
            Assert.AreEqual("( CONTAINS d d )",
                            results[1]);
        }
コード例 #3
0
        public virtual void TestSearch2()
        {
            ConnectorFacade search = GetFacade();

            for (int i = 0; i < 100; i++)
            {
                ICollection <ConnectorAttribute> co = GetTestCreateConnectorObject(string.Format("TEST{0:D5}", i));
                co.Add(ConnectorAttributeBuilder.Build("sortKey", i));
                search.Create(ObjectClass.ACCOUNT, co, null);
            }

            OperationOptionsBuilder builder = new OperationOptionsBuilder {
                PageSize = 10, SortKeys = new[] { new SortKey("sortKey", false) }
            };
            SearchResult result = null;

            ICollection <ConnectorObject> resultSet = new HashSet <ConnectorObject>();
            int pageIndex = 0;
            int index     = 101;

            while ((result = search.Search(ObjectClass.ACCOUNT, FilterBuilder.StartsWith(ConnectorAttributeBuilder.Build(Name.NAME, "TEST")), new ResultsHandler()
            {
                Handle = connectorObject =>
                {
                    int?idx = ConnectorAttributeUtil.GetIntegerValue(connectorObject.GetAttributeByName("sortKey"));
                    Assert.IsTrue(idx < index);
                    if (idx != null)
                    {
                        index = (int)idx;
                    }
                    resultSet.Add(connectorObject);
                    return(true);
                }
            }, builder.Build())).PagedResultsCookie != null)
            {
                builder = new OperationOptionsBuilder(builder.Build())
                {
                    PagedResultsCookie = result.PagedResultsCookie
                };
                Assert.AreEqual(10 * ++pageIndex, resultSet.Count);
            }
            Assert.AreEqual(9, pageIndex);
            Assert.AreEqual(100, resultSet.Count);
        }
コード例 #4
0
        public void TestGetSingleValue()
        {
            object             TEST_VALUE = 1L;
            ConnectorAttribute attr       = ConnectorAttributeBuilder.Build("long", TEST_VALUE);
            object             value      = ConnectorAttributeUtil.GetSingleValue(attr);

            Assert.AreEqual(TEST_VALUE, value);

            // test null
            attr  = ConnectorAttributeBuilder.Build("long");
            value = ConnectorAttributeUtil.GetSingleValue(attr);
            Assert.IsNull(value);
            // test empty
            attr  = ConnectorAttributeBuilder.Build("long", new List <object>());
            value = ConnectorAttributeUtil.GetSingleValue(attr);
            Assert.IsNull(value);
            // test illegal argument exception
            ConnectorAttributeUtil.GetSingleValue(ConnectorAttributeBuilder.Build("bob", 1, 2, 3));
        }
コード例 #5
0
        public void TestSimplifyNoAnd()
        {
            Filter a =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("a", "a"));
            Filter b =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("b", "b"));
            Filter c =
                FilterBuilder.EndsWith(ConnectorAttributeBuilder.Build("c", "c"));
            Filter d =
                FilterBuilder.Contains(ConnectorAttributeBuilder.Build("d", "d"));

            Filter filter =
                FilterBuilder.And(
                    FilterBuilder.Or(a, b),
                    FilterBuilder.Or(c, d));
            String expected = "( | ( CONTAINS a a ) ( CONTAINS b b ) )";
            String actual   =
                TranslateSingle(new NoAndTranslator(), filter);

            Assert.AreEqual(expected, actual);
        }
コード例 #6
0
        private ConnectorAttribute NormalizeSmtpAddressAttribute(ConnectorAttribute attribute)
        {
            if (attribute.Value == null)
            {
                return(attribute);
            }

            IList <object> normValues = new List <object>();
            bool           normalized = false;

            foreach (object val in attribute.Value)
            {
                string strVal = val as string;
                if (strVal != null)
                {
                    string[] split = strVal.Split(':');
                    if (split.Length == 2)
                    {
                        // it contains delimiter, use the second part
                        normValues.Add(split[1]);
                        normalized = true;
                    }
                    else
                    {
                        // put the original value
                        normValues.Add(val);
                    }
                }
            }

            if (normalized)
            {
                // build the attribute again
                return(ConnectorAttributeBuilder.Build(attribute.Name, normValues));
            }
            else
            {
                return(attribute);
            }
        }
コード例 #7
0
        /// <summary>
        /// Attribute normalizer
        /// </summary>
        /// <param name="oclass">Object class</param>
        /// <param name="attribute">Attribute to be normalized</param>
        /// <returns>Normalized attribute</returns>
        public override ConnectorAttribute NormalizeAttribute(ObjectClass oclass, ConnectorAttribute attribute)
        {
            // normalize the attribute using AD connector first
            attribute = base.NormalizeAttribute(oclass, attribute);

            // normalize external mail value
            if (attribute.Name == AttExternalMail && attribute.Value != null)
            {
                IList <object> normAttributes = new List <object>();
                bool           normalized     = false;
                foreach (object val in attribute.Value)
                {
                    string strVal = val as string;
                    if (strVal != null)
                    {
                        string[] split = strVal.Split(':');
                        if (split.Length == 2)
                        {
                            // it contains delimiter, use the second part
                            normAttributes.Add(split[1]);
                            normalized = true;
                        }
                        else
                        {
                            // put the original value
                            normAttributes.Add(val);
                        }
                    }
                }

                if (normalized)
                {
                    // build the attribute again
                    return(ConnectorAttributeBuilder.Build(attribute.Name, normAttributes));
                }
            }

            // return the original attribute
            return(attribute);
        }
コード例 #8
0
        /// <summary>
        /// Renames the connector attribute to new name; transforms value by keeping Common Name only
        /// </summary>
        /// <param name="cattribute">ConnectorAttribute to be renamed</param>
        /// <param name="newName">New attribute name</param>
        /// <returns>Renamed and transformed ConnectorAttribute</returns>
        /// <exception cref="ArgumentNullException">If some of the params is null</exception>
        internal static ConnectorAttribute ExtractCommonName(ConnectorAttribute cattribute, string newName)
        {
            Assertions.NullCheck(cattribute, "cattribute");
            Assertions.NullCheck(newName, "newName");

            var attBuilder = new ConnectorAttributeBuilder();

            if (cattribute.Value != null)
            {
                ICollection <object> convertedValues = new List <object>();
                foreach (object oldValue in cattribute.Value)
                {
                    if (oldValue != null)       // should be always the case
                    {
                        convertedValues.Add(ExtractCommonName(oldValue.ToString()));
                    }
                }
                attBuilder.AddValue(convertedValues);
            }
            attBuilder.Name = newName;
            return(attBuilder.Build());
        }
コード例 #9
0
ファイル: Sample.cs プロジェクト: yelloweiffel/openicf
        public virtual void Sync(ObjectClass objectClass, SyncToken token, SyncResultsHandler handler,
                                 OperationOptions options)
        {
            if (ObjectClass.ALL.Equals(objectClass))
            {
                //
            }
            else if (ObjectClass.ACCOUNT.Equals(objectClass))
            {
                var builder = new ConnectorObjectBuilder();
                builder.SetUid("3f50eca0-f5e9-11e3-a3ac-0800200c9a66");
                builder.SetName("Foo");
                builder.AddAttribute(ConnectorAttributeBuilder.BuildEnabled(true));

                var deltaBuilder = new SyncDeltaBuilder
                {
                    Object    = builder.Build(),
                    DeltaType = SyncDeltaType.CREATE,
                    Token     = new SyncToken(10)
                };

                foreach (SyncDelta connectorObject in CollectionUtil.NewSet(deltaBuilder.Build()))
                {
                    if (!handler.Handle(connectorObject))
                    {
                        // Stop iterating because the handler stopped processing
                        break;
                    }
                }
            }
            else
            {
                Trace.TraceWarning("Sync of type {0} is not supported",
                                   _configuration.ConnectorMessages.Format(objectClass.GetDisplayNameKey(),
                                                                           objectClass.GetObjectClassValue()));
                throw new NotSupportedException("Sync of type" + objectClass.GetObjectClassValue() + " is not supported");
            }
            ((SyncTokenResultsHandler)handler).HandleResult(new SyncToken(10));
        }
コード例 #10
0
        public void TestDictionaryAttribute()
        {
            Dictionary <object, object> map1 = new Dictionary <object, object>();

            map1["string"] = "OK";

            Dictionary <object, object> map2 = new Dictionary <object, object>();

            map2["map1"] = map1;
            map2["list"] = new List <int> {
                1, 2, 3
            };

            Dictionary <object, object> map3 = new Dictionary <object, object>();

            map3["map2"] = map2;

            Dictionary <object, object> map4 = new Dictionary <object, object>();

            map4["map3"] = map3;

            ConnectorAttributeBuilder.Build("map", map4);
        }
コード例 #11
0
        static TstAbstractConnector()
        {
            bool enabled = true;

            for (int i = 0; i < 100; i++)
            {
                ConnectorObjectBuilder builder = new ConnectorObjectBuilder();
                builder.SetUid(Convert.ToString(i));
                builder.SetName(string.Format("user{0:D3}", i));
                builder.AddAttribute(ConnectorAttributeBuilder.BuildEnabled(enabled));
                IDictionary <string, object> mapAttribute = new Dictionary <string, object>();
                mapAttribute["email"]   = "*****@*****.**";
                mapAttribute["primary"] = true;
                mapAttribute["usage"]   = new List <String>()
                {
                    "home", "work"
                };
                builder.AddAttribute("emails", mapAttribute);
                ConnectorObject co = builder.Build();
                collection[co.Name.GetNameValue()] = co;
                enabled = !enabled;
            }
        }
コード例 #12
0
ファイル: Sample.cs プロジェクト: yelloweiffel/openicf
        public virtual void ExecuteQuery(ObjectClass objectClass, string query, ResultsHandler handler,
                                         OperationOptions options)
        {
            var builder = new ConnectorObjectBuilder();

            builder.SetUid("3f50eca0-f5e9-11e3-a3ac-0800200c9a66");
            builder.SetName("Foo");
            builder.AddAttribute(ConnectorAttributeBuilder.BuildEnabled(true));

            foreach (ConnectorObject connectorObject in CollectionUtil.NewSet(builder.Build()))
            {
                if (!handler.Handle(connectorObject))
                {
                    // Stop iterating because the handler stopped processing
                    break;
                }
            }
            if (options.PageSize != null && 0 < options.PageSize)
            {
                Trace.TraceInformation("Paged Search was requested");
                ((SearchResultsHandler)handler).HandleResult(new SearchResult("0", 0));
            }
        }
コード例 #13
0
        public void TestAttributeTypeMap()
        {
            ConnectorPoolManager.Dispose();
            ConnectorInfoManager manager = GetConnectorInfoManager();
            ConnectorInfo        info1   = FindConnectorInfo(manager, "1.0.0.0", "org.identityconnectors.testconnector.TstStatefulConnector");

            Assert.IsNotNull(info1);

            APIConfiguration config = info1.CreateDefaultAPIConfiguration();

            config.ConnectorPoolConfiguration.MinIdle = 0;
            config.ConnectorPoolConfiguration.MaxIdle = 0;

            ConnectorFacade facade = ConnectorFacadeFactory.GetInstance().NewInstance(config);

            HashSet <ConnectorAttribute> createAttributes = new HashSet <ConnectorAttribute>();
            IDictionary <string, object> mapAttribute     = new Dictionary <string, object>();

            mapAttribute["email"]   = "*****@*****.**";
            mapAttribute["primary"] = true;
            mapAttribute["usage"]   = new List <String>()
            {
                "home", "work"
            };
            createAttributes.Add(ConnectorAttributeBuilder.Build("emails", mapAttribute));

            Uid uid = facade.Create(ObjectClass.ACCOUNT, createAttributes, null);

            Assert.AreEqual(uid.GetUidValue(), "*****@*****.**");

            ConnectorObject co    = facade.GetObject(ObjectClass.ACCOUNT, new Uid("0"), null);
            object          value = ConnectorAttributeUtil.GetSingleValue(co.GetAttributeByName("emails"));

            Assert.IsTrue(value is IDictionary);
            Assert.IsTrue(((IDictionary)value)["usage"] is IList);
        }
コード例 #14
0
        public void TestPagedSearch()
        {
            ConnectorPoolManager.Dispose();
            ConnectorInfoManager manager = GetConnectorInfoManager();
            ConnectorInfo        info1   = FindConnectorInfo(manager, "1.0.0.0", "org.identityconnectors.testconnector.TstStatefulPoolableConnector");

            Assert.IsNotNull(info1);

            APIConfiguration config = info1.CreateDefaultAPIConfiguration();

            config.ProducerBufferSize = 0;

            config.ConnectorPoolConfiguration.MinIdle = 1;
            config.ConnectorPoolConfiguration.MaxIdle = 2;
            config.ResultsHandlerConfiguration.FilteredResultsHandlerInValidationMode = true;           // for paged searches, the filtered results handler should be either disabled or put into validation mode

            ConnectorFacade facade1 = ConnectorFacadeFactory.GetInstance().NewInstance(config);

            OperationOptionsBuilder builder = new OperationOptionsBuilder();

            builder.PageSize = 10;
            builder.SetSortKeys(new ICF.SortKey(Name.NAME, true));

            SearchResult searchResult = null;
            ISet <Uid>   UIDs         = new HashSet <Uid>();

            int iteration = 0;

            do
            {
                if (null != searchResult)
                {
                    builder.PagedResultsCookie = searchResult.PagedResultsCookie;
                }

                int size = 0;
                searchResult = facade1.Search(ObjectClass.ACCOUNT, null, new ResultsHandler()
                {
                    Handle = obj =>
                    {
                        if (size >= 10)
                        {
                            Assert.Fail("More then 10 objects was handled!");
                        }
                        size++;
                        if (UIDs.Contains(obj.Uid))
                        {
                            Assert.Fail("Duplicate Entry in results");
                        }
                        return(UIDs.Add(obj.Uid));
                    }
                }, builder.Build());
                iteration++;
                Assert.IsNotNull(searchResult);
                Assert.AreEqual(searchResult.RemainingPagedResults, 100 - (iteration * 10));
            } while (searchResult.PagedResultsCookie != null);

            // Search with paged results offset

            builder                    = new OperationOptionsBuilder();
            builder.PageSize           = 10;
            builder.PagedResultsOffset = 5;
            builder.SetSortKeys(new ICF.SortKey(Name.NAME, true));

            searchResult = null;

            UIDs.Clear();
            Filter filter = FilterBuilder.EqualTo(ConnectorAttributeBuilder.BuildEnabled(true));

            iteration = 0;
            do
            {
                if (null != searchResult)
                {
                    builder.PagedResultsCookie = searchResult.PagedResultsCookie;
                }

                int size = 0;
                searchResult = facade1.Search(ObjectClass.ACCOUNT, filter, new ResultsHandler()
                {
                    Handle = obj =>
                    {
                        if (size >= 10)
                        {
                            Assert.Fail("More then 10 objects was handled!");
                        }
                        size++;
                        if (UIDs.Contains(obj.Uid))
                        {
                            Assert.Fail("Duplicate Entry in results");
                        }
                        return(UIDs.Add(obj.Uid));
                    }
                }, builder.Build());
                iteration++;
                Assert.IsNotNull(searchResult);
                Assert.AreEqual(searchResult.RemainingPagedResults, Math.Max(50 - (iteration * 15), 0));
            } while (searchResult.PagedResultsCookie != null);
        }
コード例 #15
0
        public void TestBasics()
        {
            ConnectorAttribute attribute =
                ConnectorAttributeBuilder.Build("att-name", "att-value");
            ConnectorAttribute attribute2 =
                ConnectorAttributeBuilder.Build("att-name2", "att-value2");
            AllFiltersTranslator translator = new
                                              AllFiltersTranslator();

            {
                Filter filter =
                    FilterBuilder.Contains(attribute);
                String expected = "( CONTAINS att-name att-value )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            {
                Filter filter =
                    FilterBuilder.EndsWith(attribute);
                String expected = "( ENDS-WITH att-name att-value )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            {
                Filter filter =
                    FilterBuilder.EqualTo(attribute);
                String expected = "( = att-name [att-value] )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            {
                Filter filter =
                    FilterBuilder.GreaterThan(attribute);
                String expected = "( > att-name att-value )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            {
                Filter filter =
                    FilterBuilder.GreaterThanOrEqualTo(attribute);
                String expected = "( >= att-name att-value )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            {
                Filter filter =
                    FilterBuilder.LessThan(attribute);
                String expected = "( < att-name att-value )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            {
                Filter filter =
                    FilterBuilder.LessThanOrEqualTo(attribute);
                String expected = "( <= att-name att-value )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            {
                Filter filter =
                    FilterBuilder.StartsWith(attribute);
                String expected = "( STARTS-WITH att-name att-value )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            {
                Filter filter =
                    FilterBuilder.ContainsAllValues(attribute);
                String expected = "( CONTAINS-ALL-VALUES " + attribute + " )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter   = FilterBuilder.Not(filter);
                expected = "( ! " + expected + " )";
                actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            //and
            {
                Filter left =
                    FilterBuilder.Contains(attribute);
                Filter right =
                    FilterBuilder.Contains(attribute2);
                String expectedLeft  = "( CONTAINS att-name att-value )";
                String expectedRight = "( CONTAINS att-name2 att-value2 )";
                Filter filter        =
                    FilterBuilder.And(left, right);
                String expected =
                    "( & " + expectedLeft + " " + expectedRight + " )";
                String actual =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter        = FilterBuilder.Not(filter);
                expectedLeft  = "( ! " + expectedLeft + " )";
                expectedRight = "( ! " + expectedRight + " )";
                expected      =
                    "( | " + expectedLeft + " " + expectedRight + " )";
                actual =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            //or
            {
                Filter left =
                    FilterBuilder.Contains(attribute);
                Filter right =
                    FilterBuilder.Contains(attribute2);
                String expectedLeft  = "( CONTAINS att-name att-value )";
                String expectedRight = "( CONTAINS att-name2 att-value2 )";
                Filter filter        =
                    FilterBuilder.Or(left, right);
                String expected =
                    "( | " + expectedLeft + " " + expectedRight + " )";
                String actual =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);

                filter        = FilterBuilder.Not(filter);
                expectedLeft  = "( ! " + expectedLeft + " )";
                expectedRight = "( ! " + expectedRight + " )";
                expected      =
                    "( & " + expectedLeft + " " + expectedRight + " )";
                actual =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }

            //double-negative
            {
                Filter filter =
                    FilterBuilder.Contains(attribute);
                filter = FilterBuilder.Not(filter);
                filter = FilterBuilder.Not(filter);
                String expected = "( CONTAINS att-name att-value )";
                String actual   =
                    TranslateSingle(translator, filter);
                Assert.AreEqual(expected, actual);
            }
        }
コード例 #16
0
 public void TestUpdateTimeOut()
 {
     GetFacade().Update(Test, new Uid("TIMEOUT"),
                        CollectionUtil.NewSet(ConnectorAttributeBuilder.Build("null")), null);
     Assert.Fail();
 }
コード例 #17
0
        /// <summary>
        /// Process the Hashtable result and convert it to a SyncDelta object
        /// ready to be processed by the sync handler
        /// </summary>
        /// <remarks>
        /// The result Hashtable must follow a specific format and contain the following key/value:
        ///
        /// "Token": (Object) token object (could be Integer, Date, String), [!! could be null]
        /// "DeltaType": (String) ("CREATE|UPDATE|CREATE_OR_UPDATE"|"DELETE"),
        /// "Uid": (String) uid  (uid of the entry),
        /// "PreviousUid": (String) previous uid (This is for rename ops),
        /// "Object": Hashtable(String,List) of attributes name/values describing the object
        /// "ObjectClass": (String) must be set if Operation = DELETE and Object = null
        /// </remarks>
        /// <param name="result"></param>
        /// <returns></returns>
        public Object Process(Hashtable result)
        {
            var syncbld = new SyncDeltaBuilder();
            var cobld   = new ConnectorObjectBuilder();
            Uid uid;

            // SyncToken
            // Mandatory here
            if (result.ContainsKey(SyncTokenKeyName))
            {
                syncbld.Token = result[SyncTokenKeyName] == null ? new SyncToken(0L) : new SyncToken(result[SyncTokenKeyName]);
            }
            else
            {
                throw new ArgumentException("SyncToken is missing in Sync result");
            }

            // SyncDelta
            // Mandatory here
            if (isValidKeyAndValue(result, DeltaTypeKeyName))
            {
                var op = result[DeltaTypeKeyName];
                if (SyncDeltaType.CREATE.ToString().Equals(op as String, StringComparison.OrdinalIgnoreCase))
                {
                    syncbld.DeltaType = SyncDeltaType.CREATE;
                }
                else if (SyncDeltaType.UPDATE.ToString().Equals(op as String, StringComparison.OrdinalIgnoreCase))
                {
                    syncbld.DeltaType = SyncDeltaType.UPDATE;
                }
                else if (SyncDeltaType.DELETE.ToString().Equals(op as String, StringComparison.OrdinalIgnoreCase))
                {
                    syncbld.DeltaType = SyncDeltaType.DELETE;
                }
                else if (SyncDeltaType.CREATE_OR_UPDATE.ToString().Equals(op as String, StringComparison.OrdinalIgnoreCase))
                {
                    syncbld.DeltaType = SyncDeltaType.CREATE_OR_UPDATE;
                }
                else
                {
                    throw new ArgumentException("Unrecognized DeltaType in Sync result");
                }
            }
            else
            {
                throw new ArgumentException("DeltaType is missing in Sync result");
            }

            // Uid
            // Mandatory
            if (isValidKeyAndValue(result, UidKeyName))
            {
                var value = result[UidKeyName];
                if (value is String)
                {
                    uid = new Uid(value as String);
                }
                else if (value is Uid)
                {
                    uid = value as Uid;
                }
                else
                {
                    throw new ArgumentException("Unrecognized Uid in Sync result");
                }
                syncbld.Uid = uid;
                cobld.SetUid(uid);
            }
            else
            {
                throw new ArgumentException("Uid is missing in Sync result");
            }

            // PreviousUid
            // Not valid if DELETE
            if (isValidKeyAndValue(result, PreviousUidKeyName))
            {
                var value = result[PreviousUidKeyName];
                Uid previousUid;
                if (value is String)
                {
                    previousUid = new Uid(value as String);
                }
                else if (value is Uid)
                {
                    previousUid = value as Uid;
                }
                else
                {
                    throw new ArgumentException("Unrecognized PreviousUid in Sync result");
                }
                syncbld.PreviousUid = previousUid;
            }
            if (syncbld.PreviousUid != null && syncbld.DeltaType == SyncDeltaType.DELETE)
            {
                throw new ArgumentException("PreviousUid can only be specified for Create or Update.");
            }

            // Connector object
            // Mandatory unless DELETE
            if (result.ContainsKey(ConnectorObjectKeyName) && result[ConnectorObjectKeyName] is Hashtable)
            {
                var attrs = result[ConnectorObjectKeyName] as Hashtable;

                if (!attrs.ContainsKey(Name.NAME))
                {
                    throw new ArgumentException("The Object must contain a Name");
                }

                foreach (DictionaryEntry attr in attrs)
                {
                    var attrName  = attr.Key as String;
                    var attrValue = attr.Value;

                    if (Name.NAME.Equals(attrName))
                    {
                        cobld.SetName(attrValue as String);
                    }
                    else if (Uid.NAME.Equals((attrName)))
                    {
                        if (!uid.GetUidValue().Equals(attrValue))
                        {
                            throw new ArgumentException("Uid from Object is different than Uid from Sync result");
                        }
                    }
                    else if (OperationalAttributes.ENABLE_NAME.Equals((attrName)))
                    {
                        cobld.AddAttribute(ConnectorAttributeBuilder.BuildEnabled(attr.Value is bool && (bool)attr.Value));
                    }
                    else
                    {
                        if (attrValue == null)
                        {
                            cobld.AddAttribute(ConnectorAttributeBuilder.Build(attrName));
                        }
                        else if (attrValue.GetType() == typeof(Object[]) || attrValue.GetType() == typeof(System.Collections.ICollection))
                        {
                            var list = new Collection <object>();
                            foreach (var val in (ICollection)attrValue)
                            {
                                list.Add(FrameworkUtil.IsSupportedAttributeType(val.GetType()) ? val : val.ToString());
                            }
                            cobld.AddAttribute(ConnectorAttributeBuilder.Build(attrName, list));
                        }
                        else
                        {
                            cobld.AddAttribute(ConnectorAttributeBuilder.Build(attrName, attrValue));
                        }
                    }
                }
                cobld.ObjectClass = _objectClass;
                syncbld.Object    = cobld.Build();
            }
            // If operation is DELETE and the ConnectorObject is null,
            // we need to set the ObjectClass at the SyncDelta level
            else if ((SyncDeltaType.DELETE == syncbld.DeltaType) && isValidKeyAndValue(result, ObjectClassKeyName))
            {
                var objclass = result[ObjectClassKeyName];
                if (objclass is ObjectClass)
                {
                    syncbld.ObjectClass = objclass as ObjectClass;
                }
                else if (objclass is String)
                {
                    syncbld.ObjectClass = new ObjectClass(objclass as String);
                }
                else
                {
                    throw new ArgumentException("Unrecognized ObjectClass in Sync result");
                }
            }
            else
            {
                throw new ArgumentException("Object is missing in Sync result");
            }

            return(_handler.Handle(syncbld.Build()));
        }
コード例 #18
0
        // creates a collection of attributes that correspond to the original ones, but resolves ADD/DELETE using existing values of psuser
        public ICollection <ConnectorAttribute> DetermineNewAttributeValues(UpdateOpContext context, ConnectorObject originalObject)
        {
            if (context.UpdateType == UpdateType.REPLACE)
            {
                // TODO check multivaluedness and updateability (as below)
                return(new List <ConnectorAttribute>(context.Attributes));
            }
            else
            {
                Boolean add;
                if (context.UpdateType == UpdateType.ADD)
                {
                    add = true;
                }
                else if (context.UpdateType == UpdateType.DELETE)
                {
                    add = false;
                }
                else
                {
                    throw new ArgumentException("Unsupported update type: " + context.UpdateType);
                }

                Schema schema = null;
                ICollection <ConnectorAttribute> rv = new List <ConnectorAttribute>(context.Attributes.Count);
                foreach (ConnectorAttribute attribute in context.Attributes)
                {
                    ConnectorAttribute originalAttribute = originalObject.GetAttributeByName(attribute.Name);
                    IList <object>     newValues         = originalAttribute != null && originalAttribute.Value != null ? new List <object>(originalAttribute.Value) : new List <object>();
                    Boolean            changed           = false;
                    if (attribute.Value != null)
                    {
                        foreach (object item in attribute.Value)
                        {
                            if (add)
                            {
                                if (newValues.Contains(item))
                                {
                                    LOG.Warn("Trying to add value from " + attribute.Name + " that is already there: " + item);
                                }
                                else
                                {
                                    newValues.Add(item);
                                    changed = true;
                                }
                            }
                            else
                            {
                                if (!newValues.Contains(item))
                                {
                                    LOG.Warn("Trying to remove value from " + attribute.Name + " that is not there: " + item);
                                }
                                else
                                {
                                    newValues.Remove(item);
                                    changed = true;
                                }
                            }
                        }
                    }
                    if (changed)
                    {
                        ConnectorAttributeBuilder b = new ConnectorAttributeBuilder();
                        b.Name = attribute.Name;
                        b.AddValue(newValues);
                        ConnectorAttribute modified = b.Build();

                        if (schema == null)
                        {
                            ExchangeConnector connector = (ExchangeConnector)context.Connector;
                            schema = connector.Schema();
                        }
                        ObjectClassInfo oci = schema.FindObjectClassInfo(context.ObjectClass.Type);
                        if (oci == null)
                        {
                            throw new InvalidOperationException("No object class info for " + context.ObjectClass.Type + " in the schema");
                        }
                        var cai = ConnectorAttributeInfoUtil.Find(attribute.Name, oci.ConnectorAttributeInfos);
                        if (cai == null)
                        {
                            throw new InvalidOperationException("No connector attribute info for " + context.ObjectClass.Type + " in the schema");
                        }

                        if (!cai.IsUpdateable)
                        {
                            throw new ConnectorSecurityException("Attempt to update a non-updateable attribute (" + attribute.Name + "): " +
                                                                 CollectionUtil.Dump(newValues));
                        }

                        if (newValues.Count > 1 && !cai.IsMultiValued)
                        {
                            throw new InvalidAttributeValueException("More than one value in a single-valued attribute (" + attribute.Name + "): " +
                                                                     CollectionUtil.Dump(newValues));
                        }
                        rv.Add(modified);
                    }
                }
                return(rv);
            }
        }
コード例 #19
0
        /// <summary>
        /// DeduplicatesEmailAddresses.
        ///  - on REPLACE (i.e. update/replace or create) the situation is easy: we just remove duplicate entries (SMTP:x & smtp:x result in SMTP:x)
        ///  - on DELETE we currently do nothing
        ///  - on ADD we have one additional rule:
        ///     "If we are adding SMTP:x, we first convert all SMTP:y in existing records to smtp:y because we see the intent of having x to be a new primary"
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <param name="attributes">these are attributes to be set (already resolved if we have update of type ADD or DELETE)</param>
        /// <returns></returns>
        private ICollection <ConnectorAttribute> DeduplicateEmailAddresses(CreateUpdateOpContext context, ICollection <ConnectorAttribute> attributes)
        {
            // trivial cases

            if (context is UpdateOpContext && ((UpdateOpContext)context).UpdateType == UpdateType.DELETE)
            {
                return(attributes);
            }

            ConnectorAttribute attribute = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, attributes);

            if (attribute == null || attribute.Value == null)
            {
                return(attributes);      // missing or empty EmailAddresses - nothing to deduplicate
            }
            ConnectorAttribute attributeDelta = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, context.Attributes);

            if (attributeDelta == null || attributeDelta.Value == null)
            {
                return(attributes);      // missing or empty changed EmailAddresses - nothing to deduplicate
            }

            // now the main part

            IList <string> valuesToDeduplicate = new List <string>();

            foreach (object o in attribute.Value)
            {
                if (o != null)
                {
                    valuesToDeduplicate.Add(o.ToString());
                }
            }
            bool changed = false;

            // special rule: if ADD with SMTP:, let us change all other "SMTP:x" to "smtp:x"
            Boolean isUpdateAdd = context is UpdateOpContext && ((UpdateOpContext)context).UpdateType == UpdateType.ADD;

            if (isUpdateAdd)
            {
                string newPrimary = null;
                foreach (object o in attributeDelta.Value)
                {
                    if (((string)o).StartsWith("SMTP:"))
                    {
                        newPrimary = (string)o;
                        break;
                    }
                }
                if (newPrimary != null)
                {
                    foreach (string address in new List <string>(valuesToDeduplicate))      // to eliminate concurrent access
                    {
                        if (address.StartsWith("SMTP:") && !address.Equals(newPrimary))
                        {
                            string replacement = "smtp:" + address.Substring(5);
                            LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Changing duplicate primary-candidate address {0} to {1}", address, replacement);
                            valuesToDeduplicate.Remove(address);
                            valuesToDeduplicate.Add(replacement);
                            changed = true;
                        }
                    }
                }
            }

            IDictionary <string, string> values = new Dictionary <string, string>();       // normalized->most-recent-original e.g. SMTP:[email protected] -> SMTP:[email protected] (if primary is present)

            foreach (object v in valuesToDeduplicate)
            {
                string address    = (string)v;
                string normalized = address.ToUpper();
                if (values.ContainsKey(normalized))
                {
                    changed = true;
                    string existing = values[normalized];
                    if (address.StartsWith("SMTP:") && existing.StartsWith("smtp:"))
                    {
                        LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Removing redundant address {0}, keeping {1}", existing, address);
                        values[normalized] = address;
                    }
                    else
                    {
                        LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Removing redundant address {0}, keeping {1}", address, existing);
                    }
                }
                else
                {
                    values.Add(normalized, address);
                }
            }
            if (changed)
            {
                ConnectorAttributeBuilder cab = new ConnectorAttributeBuilder();
                cab.Name = ExchangeConnectorAttributes.AttEmailAddresses;
                foreach (string value in values.Values)
                {
                    cab.AddValue(value);
                }
                ICollection <ConnectorAttribute> rv = new List <ConnectorAttribute>(attributes);          // the original is (sometimes) a read-only collection
                rv.Remove(attribute);
                rv.Add(cab.Build());
                return(rv);
            }
            else
            {
                return(attributes);
            }
        }
コード例 #20
0
        public void UpdateMergeTests()
        {
            ConnectorAttribute     expected, actual;
            Configuration          config  = new MockConfiguration(false);
            ConnectorFacadeFactory factory = ConnectorFacadeFactory.GetInstance();
            SafeType <Connector>   clazz   = SafeType <Connector> .Get <MockUpdateConnector>();

            // **test only**
            APIConfiguration impl = TestHelpers.CreateTestConfiguration(clazz, config);

            impl.SetTimeout(SafeType <APIOperation> .Get <GetApiOp>(), APIConstants.NO_TIMEOUT);
            impl.SetTimeout(SafeType <APIOperation> .Get <UpdateApiOp>(), APIConstants.NO_TIMEOUT);
            impl.SetTimeout(SafeType <APIOperation> .Get <SearchApiOp>(), APIConstants.NO_TIMEOUT);
            ConnectorFacade facade = factory.NewInstance(impl);
            // sniff test to make sure we can get an object..
            ConnectorObject obj = facade.GetObject(ObjectClass.ACCOUNT, NewUid(1), null);

            Assert.AreEqual(NewUid(1), obj.Uid);
            // ok lets add an attribute that doesn't exist..
            String ADDED     = "somthing to add to the object";
            String ATTR_NAME = "added";
            ICollection <ConnectorAttribute> addAttrSet;

            addAttrSet = CollectionUtil.NewSet((IEnumerable <ConnectorAttribute>)obj.GetAttributes());
            addAttrSet.Add(ConnectorAttributeBuilder.Build(ATTR_NAME, ADDED));
            Name name = obj.Name;

            addAttrSet.Remove(name);
            Uid uid = facade.AddAttributeValues(ObjectClass.ACCOUNT, obj.Uid, ConnectorAttributeUtil.FilterUid(addAttrSet), null);

            // get back the object and see if there are the same..
            addAttrSet.Add(name);
            ConnectorObject addO = new ConnectorObject(ObjectClass.ACCOUNT, addAttrSet);

            obj = facade.GetObject(ObjectClass.ACCOUNT, NewUid(1), null);
            Assert.AreEqual(addO, obj);
            // attempt to add on to an existing attribute..
            addAttrSet.Remove(name);
            uid = facade.AddAttributeValues(ObjectClass.ACCOUNT, obj.Uid, ConnectorAttributeUtil.FilterUid(addAttrSet), null);
            // get the object back out and check on it..
            obj      = facade.GetObject(ObjectClass.ACCOUNT, uid, null);
            expected = ConnectorAttributeBuilder.Build(ATTR_NAME, ADDED, ADDED);
            actual   = obj.GetAttributeByName(ATTR_NAME);
            Assert.AreEqual(expected, actual);
            // attempt to delete a value from an attribute..
            ICollection <ConnectorAttribute> deleteAttrs = CollectionUtil.NewSet((IEnumerable <ConnectorAttribute>)addO.GetAttributes());

            deleteAttrs.Remove(name);
            uid      = facade.RemoveAttributeValues(ObjectClass.ACCOUNT, addO.Uid, ConnectorAttributeUtil.FilterUid(deleteAttrs), null);
            obj      = facade.GetObject(ObjectClass.ACCOUNT, uid, null);
            expected = ConnectorAttributeBuilder.Build(ATTR_NAME, ADDED);
            actual   = obj.GetAttributeByName(ATTR_NAME);
            Assert.AreEqual(expected, actual);
            // attempt to delete an attribute that doesn't exist..
            ICollection <ConnectorAttribute> nonExist = new HashSet <ConnectorAttribute>();

            nonExist.Add(NewUid(1));
            nonExist.Add(ConnectorAttributeBuilder.Build("does not exist", "asdfe"));
            uid = facade.RemoveAttributeValues(ObjectClass.ACCOUNT, addO.Uid, ConnectorAttributeUtil.FilterUid(nonExist), null);
            obj = facade.GetObject(ObjectClass.ACCOUNT, NewUid(1), null);
            Assert.IsTrue(obj.GetAttributeByName("does not exist") == null);
        }
コード例 #21
0
 private ConnectorAttribute CreateNormalizedTestAttribute()
 {
     return(ConnectorAttributeBuilder.Build("foo", "bar"));
 }
コード例 #22
0
        /// <summary>
        /// Finds the attributes in connector object and rename it according to input array of names, but only
        /// if the atribute name is in attributes to get
        /// </summary>
        /// <param name="cobject">ConnectorObject which attributes should be replaced</param>
        /// <param name="map">Replace mapping</param>
        /// <returns>ConnectorObject with replaced attributes</returns>
        /// <exception cref="ArgumentNullException">If some of the params is null</exception>
        internal static ConnectorObject ConvertAdAttributesToExchange(ConnectorObject cobject)
        {
            Assertions.NullCheck(cobject, "cobject");

            var attributes = cobject.GetAttributes();
            var builder    = new ConnectorObjectBuilder();

            bool emailAddressPolicyEnabled = true;

            foreach (ConnectorAttribute attribute in attributes)
            {
                string newName;
                if (attribute.Is(ExchangeConnectorAttributes.AttMsExchPoliciesExcludedADName))
                {
                    if (attribute.Value != null && attribute.Value.Contains("{26491cfc-9e50-4857-861b-0cb8df22b5d7}"))
                    {
                        emailAddressPolicyEnabled = false;
                    }
                }
                else if (attribute.Is(ExchangeConnectorAttributes.AttAddressBookPolicyADName))
                {
                    var newAttribute = ExtractCommonName(attribute, ExchangeConnectorAttributes.AttAddressBookPolicy);
                    builder.AddAttribute(newAttribute);
                    builder.AddAttribute(attribute);        // keep the original one as well
                }
                else if (attribute.Is(ExchangeConnectorAttributes.AttOfflineAddressBookADName))
                {
                    var newAttribute = ExtractCommonName(attribute, ExchangeConnectorAttributes.AttOfflineAddressBook);
                    builder.AddAttribute(newAttribute);
                    builder.AddAttribute(attribute);        // keep the original one as well
                }
                else if (attribute.Is(ExchangeConnectorAttributes.AttHiddenFromAddressListsEnabledADName))
                {
                    builder.AddAttribute(attribute);        // keep the original one as well
                }
                else if (ExchangeConnectorAttributes.AttMapFromAD.TryGetValue(attribute.Name, out newName))
                {
                    var newAttribute = RenameAttribute(attribute, newName);
                    builder.AddAttribute(newAttribute);
                }
                else
                {
                    builder.AddAttribute(attribute);
                }
            }

            builder.AddAttribute(ConnectorAttributeBuilder.Build(ExchangeConnectorAttributes.AttEmailAddressPolicyEnabled, emailAddressPolicyEnabled));

            copyAttribute(builder, cobject, ExchangeConnectorAttributes.AttPrimarySmtpAddressADName, ExchangeConnectorAttributes.AttPrimarySmtpAddress);

            // derive recipient type
            string recipientType = GetRecipientType(cobject);

            if (recipientType != null)
            {
                builder.AddAttribute(ConnectorAttributeBuilder.Build(ExchangeConnectorAttributes.AttRecipientType, new string[] { recipientType }));
            }

            builder.ObjectClass = cobject.ObjectClass;
            builder.SetName(cobject.Name);
            builder.SetUid(cobject.Uid);
            return(builder.Build());
        }
コード例 #23
0
        public void Create(CreateOpContext context)
        {
            context.Attributes = DeduplicateEmailAddresses(context, context.Attributes);

            // get recipient type
            string rcptType = ExchangeUtility.GetAttValue(ExchangeConnectorAttributes.AttRecipientType, context.Attributes) as string;

            if (rcptType == null || rcptType.Equals(""))
            {
                rcptType = ExchangeConnectorAttributes.RcptTypeUser;
            }

            ExchangeConnector        exconn = (ExchangeConnector)context.Connector;
            ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector;

            PSExchangeConnector.CommandInfo cmdInfoEnable = null;
            PSExchangeConnector.CommandInfo cmdInfoSet    = null;
            switch (rcptType)
            {
            case ExchangeConnectorAttributes.RcptTypeMailBox:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailbox;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailbox;
                break;

            case ExchangeConnectorAttributes.RcptTypeMailUser:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailUser;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailUser;
                break;

            case ExchangeConnectorAttributes.RcptTypeUser:
                break;

            default:
                throw new ArgumentException(
                          context.ConnectorConfiguration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", rcptType));
            }

            // first create the object in AD
            ICollection <ConnectorAttribute> adAttributes = ExchangeUtility.FilterOut(context.Attributes,
                                                                                      PSExchangeConnector.CommandInfo.EnableMailbox,
                                                                                      PSExchangeConnector.CommandInfo.SetMailbox,
                                                                                      PSExchangeConnector.CommandInfo.EnableMailUser,
                                                                                      PSExchangeConnector.CommandInfo.SetMailUser);
            Uid uid = adconn.Create(context.ObjectClass, adAttributes, context.Options);

            if (rcptType == ExchangeConnectorAttributes.RcptTypeUser)
            {
                // AD account only, we do nothing
                context.Uid = uid;
                return;
            }

            // add a empty "EmailAddresses" attribute if needed (address policy is disabled and no addresses are provided)
            ICollection <ConnectorAttribute> enhancedAttributes;
            ConnectorAttribute policyEnabledAttribute = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddressPolicyEnabled, context.Attributes);

            if (policyEnabledAttribute != null &&
                ConnectorAttributeUtil.GetBooleanValue(policyEnabledAttribute).HasValue&&
                ConnectorAttributeUtil.GetBooleanValue(policyEnabledAttribute).Value == false &&
                ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttPrimarySmtpAddress, context.Attributes) == null &&
                ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, context.Attributes) == null)
            {
                enhancedAttributes = new HashSet <ConnectorAttribute>(context.Attributes);
                enhancedAttributes.Add(ConnectorAttributeBuilder.Build(ExchangeConnectorAttributes.AttEmailAddresses));
                LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Added empty EmailAddresses attribute because address policy use is disabled and no addresses were provided");
            }
            else
            {
                enhancedAttributes = context.Attributes;        // no change
            }

            // prepare the command
            Command cmdEnable = ExchangeUtility.GetCommand(cmdInfoEnable, enhancedAttributes, uid, (ExchangeConfiguration)context.ConnectorConfiguration);
            Command cmdSet    = ExchangeUtility.GetCommand(cmdInfoSet, enhancedAttributes, uid, (ExchangeConfiguration)context.ConnectorConfiguration);

            try {
                _helper.InvokePipeline(exconn, cmdEnable);
                _helper.InvokePipeline(exconn, cmdSet);
            }
            catch {
                LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Rolling back AD create for UID: " + uid.GetUidValue());

                // rollback AD create
                try {
                    adconn.Delete(context.ObjectClass, uid, context.Options);
                } catch {
                    LOGGER.TraceEvent(TraceEventType.Warning, CAT_DEFAULT, "Not able to rollback AD create for UID: " + uid.GetUidValue());
                    // note: this is not perfect, we hide the original exception
                    throw;
                }

                // rethrow original exception
                throw;
            }

            context.Uid = uid;
        }