/// <summary> /// /// </summary> /// <param name="dnTag"></param> /// <returns></returns> /// <exception cref="DirectoryObjectNotFoundException"></exception> public DistinguishedName Resolve(int dnTag) { if (dnTag < ADConstants.RootDNTag) { throw new ArgumentOutOfRangeException("dnTag"); } if (dnTag == ADConstants.RootDNTag) { // TODO: or null? return(new DistinguishedName()); } // TODO: Move to constructor? var dntColId = schema.FindColumnId(CommonDirectoryAttributes.DNTag); var pdntColId = schema.FindColumnId(CommonDirectoryAttributes.ParentDNTag); var rdnColId = schema.FindColumnId(CommonDirectoryAttributes.RDN); var rdnTypeColId = schema.FindColumnId(CommonDirectoryAttributes.RDNType); DistinguishedName dn = new DistinguishedName(); cursor.CurrentIndex = schema.FindIndexName(CommonDirectoryAttributes.DNTag); int currentDNTag = dnTag; do { bool found = cursor.GotoKey(Key.Compose(currentDNTag)); if (!found) { throw new DirectoryObjectNotFoundException(dnTag); } string name = cursor.RetrieveColumnAsString(rdnColId); int rdnType = cursor.RetrieveColumnAsInt(rdnTypeColId).Value; string rdnAtt = schema.FindAttribute(rdnType).Name.ToUpper(); dn.AddParent(rdnAtt, name); currentDNTag = cursor.RetrieveColumnAsDNTag(pdntColId).Value; } while (currentDNTag != ADConstants.RootDNTag); // TODO: Parent DN Caching return(dn); }
/// <summary> /// Recursively resolves a DN Tag to a full distinguished name. /// </summary> /// <param name="dnTag">Distinguished name tag</param> /// <returns>Resolved DN</returns> /// <exception cref="DirectoryObjectNotFoundException" /> public DistinguishedName Resolve(int dnTag) { // Check the DN cache first DistinguishedName dnFromCache = this.TryResolveFromCache(dnTag); if (dnFromCache != null) { // We just return the DN from cache. return(dnFromCache); } if (dnTag < ADConstants.RootDNTag) { // Minimum DN Tag is 2. throw new ArgumentOutOfRangeException("dnTag"); } // Cache column IDs var dntColId = schema.FindColumnId(CommonDirectoryAttributes.DNTag); var pdntColId = schema.FindColumnId(CommonDirectoryAttributes.ParentDNTag); var rdnColId = schema.FindColumnId(CommonDirectoryAttributes.RDN); var rdnTypeColId = schema.FindColumnId(CommonDirectoryAttributes.RDNType); // Set index to the Distinguished Name Tag (~primary key) cursor.CurrentIndex = schema.FindIndexName(CommonDirectoryAttributes.DNTag); // We will build the DN from leaf to root DistinguishedName result = new DistinguishedName(); int currentDNTag = dnTag; while (currentDNTag != ADConstants.RootDNTag) { // Move cursor to the current object bool found = cursor.GotoKey(Key.Compose(currentDNTag)); if (!found) { throw new DirectoryObjectNotFoundException(dnTag); } // Retrieve the current object's RDN, e.g. CN=Administrator string name = cursor.RetrieveColumnAsString(rdnColId); int rdnType = cursor.RetrieveColumnAsInt(rdnTypeColId).Value; string rdnAtt = schema.FindAttribute(rdnType).Name.ToUpper(); var currentRDN = new DistinguishedNameComponent(rdnAtt, name); // Concat the current RDN with the child RDN in result result.AddParent(currentRDN); // Identify the current object's parent int parentDNTag = cursor.RetrieveColumnAsDNTag(pdntColId).Value; // Check the DN cache DistinguishedName parentDN = this.TryResolveFromCache(parentDNTag); if (parentDN != null) { // We have found the parent object in DN cache. result.AddParent(parentDN); // Add the current object to cache if the parent is DC or root. bool shoulCache = parentDN.Components.Count == 0 || String.Equals(parentDN.Components[0].Name, CommonDirectoryAttributes.DomainComponent, StringComparison.OrdinalIgnoreCase); if (shoulCache) { var currentDN = new DistinguishedName(currentRDN); currentDN.AddParent(parentDN); this.dnCache.Add(currentDNTag, currentDN); } // We can stop the recursion as we have resolved the entire DN using cache. break; } // Move upwards to the object's parent as we have not found it in the DN cache. currentDNTag = parentDNTag; } return(result); }