1 /******************************************************************************
3 * Copyright (c) 2003 Novell Inc., www.novell.com
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 *******************************************************************************/
25 // System.DirectoryServices.DirectoryEntry.cs
28 // Sunil Kumar (sunilk@novell.com)
29 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
30 // Boris Kirzner (borisk@mainsoft.com)
35 using System.ComponentModel;
36 using Novell.Directory.Ldap;
37 using Novell.Directory.Ldap.Utilclass;
38 using System.Globalization;
39 using System.DirectoryServices.Design;
40 using System.Collections.Specialized;
41 using System.Configuration;
43 namespace System.DirectoryServices
47 ///Encapsulates a node or object in the Ldap Directory hierarchy.
49 [TypeConverter (typeof (DirectoryEntryConverter))]
50 public class DirectoryEntry : Component
52 private static readonly string DEFAULT_LDAP_HOST = "System.DirectoryServices.DefaultLdapHost";
53 private static readonly string DEFAULT_LDAP_PORT = "System.DirectoryServices.DefaultLdapPort";
55 private LdapConnection _conn = null;
56 private AuthenticationTypes _AuthenticationType=AuthenticationTypes.None;
57 private DirectoryEntries _Children;
58 private string _Fdn = null;
59 private string _Path="";
60 private string _Name=null;
61 private DirectoryEntry _Parent=null;
62 private string _Username;
63 private string _Password;
64 //private string _Nativeguid;
65 private PropertyCollection _Properties = null;
66 private string _SchemaClassName=null;
67 private bool _Nflag = false;
68 private bool _usePropertyCache=true;
69 private bool _inPropertiesLoading;
72 /// Returns entry's Fully distinguished name.
78 LdapUrl lUrl = new LdapUrl (ADsPath);
79 string fDn=lUrl.getDN();
90 /// Returns the connection object used to communicate with
93 internal LdapConnection conn
107 /// Flag to check whether the entry is to be cerated or it already
120 /// <summary> Initializes the Connection and other properties.
123 private void InitBlock()
126 _conn= new LdapConnection ();
127 LdapUrl lUrl = new LdapUrl (ADsPath);
128 _conn.Connect(lUrl.Host,lUrl.Port);
129 _conn.Bind(Username,Password, (Novell.Directory.Ldap.AuthenticationTypes)AuthenticationType);
131 catch(LdapException ex) {
140 /// Initializes the Entry specific properties e.g entry DN etc.
144 LdapUrl lUrl = new LdapUrl (ADsPath);
145 string dn = lUrl.getDN();
147 if (String.Compare (dn,"rootDSE",true) == 0)
148 InitToRootDse (lUrl.Host,lUrl.Port);
150 DN userDn = new DN (dn);
151 String[] lRdn = userDn.explodeDN(false);
152 _Name = (string)lRdn[0];
153 _Parent = new DirectoryEntry(conn);
154 _Parent.Path = GetLdapUrlString (lUrl.Host,lUrl.Port,userDn.Parent.ToString ());
158 _Name=lUrl.Host+":"+lUrl.Port;
159 _Parent = new DirectoryEntry(conn);
160 _Parent.Path = "Ldap:";
165 /// Initializes a new instance of the DirectoryEntry class
167 public DirectoryEntry()
172 /// Initializes a new instance of the DirectoryEntry class that binds
173 /// to the specified native Active Directory object.
175 /// <param name="adsObject"> native active directory object</param>
176 public DirectoryEntry(object adsObject)
178 throw new NotImplementedException();
182 /// Initializes a new instance of the DirectoryEntry class that binds
183 /// this instance to the node in Ldap Directory located at the
186 /// <param name="path"> Path of the entry i.e Ldap URL specifying
187 /// entry path</param>
188 public DirectoryEntry(string path)
194 /// Initializes a new instance of the DirectoryEntry class. The Path,
195 /// Username, and Password properties are set to the specified values.
197 /// <param name="path">Path of the entry i.e Ldap URL specifying
198 /// entry path</param>
199 /// <param name="username">user name to use when authenticating the client
201 /// <param name="password">password to use when authenticating the client
203 public DirectoryEntry(string path,string username,string password)
211 /// Initializes a new instance of the DirectoryEntry class. The Path,
212 /// Username, and Password properties are set to the specified values.
214 /// <param name="path">Path of the entry i.e Ldap URL specifying
215 /// entry path</param>
216 /// <param name="username">user name to use when authenticating the client
218 /// <param name="password">password to use when authenticating the client
220 /// <param name="authenticationType"> type of authentication to use</param>
221 public DirectoryEntry(
225 AuthenticationTypes authenticationType)
230 _AuthenticationType=authenticationType;
234 /// Creates the entry object
236 /// <param name="lconn">Connection object used to communicate with
237 /// Ldap server</param>
238 internal DirectoryEntry(LdapConnection lconn)
244 /// Returns Type of authentication to use while Binding to Ldap server
246 [DSDescription ("Type of authentication to use while Binding to Ldap server")]
247 [DefaultValue (AuthenticationTypes.None)]
248 public AuthenticationTypes AuthenticationType
252 return _AuthenticationType;
256 _AuthenticationType = value;
261 /// Gets a DirectoryEntries containing the child entries of this node
262 /// in the Ldap Directory hierarchy.
264 /// <value>A DirectoryEntries containing the child entries of this node
265 /// in the Ldap Directory hierarchy.</value>
267 /// The child entries are only the immediate children of this node.
268 /// Use this property to find, retrieve, or create a directory entry
269 /// in the hierarchy. This property is a collection that, along with
270 /// usual iteration capabilities, provides an Add method through which
271 /// you add a node to the collection directly below the parent node
272 /// that you are currently bound to. When adding a node to the
273 /// collection, you must specify a name for the new node and the name of
274 /// a schema template that you want to associate with the node. For
275 /// example, you might want to use a schema titled "Computer" to add
276 /// new computers to the hierarchy.
278 [DSDescription ("Child entries of this node")]
279 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
281 public DirectoryEntries Children
285 _Children = new DirectoryEntries(ADsPath, conn);
291 /// Gets the globally unique identifier (GUID) of the DirectoryEntry
293 /// <value>The globally unique identifier of the DirectoryEntry.</value>
295 /// Not implemented yet.
297 [DSDescription ("A globally unique identifier for this DirectoryEntry")]
298 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
305 throw new NotImplementedException();
311 /// Gets the name of the object as named with the underlying directory
314 /// <value>The name of the object as named with the underlying directory
316 /// <remarks>This name, along with SchemaClassName, distinguishes this
317 /// entry from its siblings and must be unique amongst its siblings
318 /// in each instance of DirectoryEntry.</remarks>
319 [DSDescription ("The name of the object as named with the underlying directory")]
320 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
326 if(CheckEntry(conn,ADsPath))
329 throw new SystemException("There is no such object on the server");
336 /// Gets this entry's parent in the Ldap Directory hierarchy.
338 /// <value>This entry's parent in the Active Directory hierarc</value>
339 [DSDescription ("This entry's parent in the Ldap Directory hierarchy.")]
340 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
342 public DirectoryEntry Parent
346 if(CheckEntry(conn,ADsPath))
349 throw new SystemException("There is no such object on the server");
356 /// Gets the globally unique identifier of the DirectoryEntry, as
357 /// returned from the provider
360 /// The globally unique identifier of the DirectoryEntry, as returned
361 /// from the provider.
364 /// Not implemented yet.
366 [DSDescription ("The globally unique identifier of the DirectoryEntry, as returned from the provider")]
367 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
370 public string NativeGuid
373 throw new NotImplementedException();
378 /// Gets the native Active Directory Service Interfaces (ADSI) object.
381 /// Not implemented yet
382 [DSDescription ("The native Active Directory Service Interfaces (ADSI) object.")]
383 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
385 public object NativeObject
389 throw new NotImplementedException();
394 /// Determines if a cache should be used.
396 [DSDescription ("Determines if a cache should be used.")]
397 [DefaultValue (true)]
398 public bool UsePropertyCache
402 return _usePropertyCache;
406 _usePropertyCache = value;
411 /// Gets or sets the password to use when authenticating the client.
414 /// The password to use when authenticating the client.
417 /// You can set the Username and password in order to specify alternate
418 /// credentials with which to access the information in Ldap Directory.
419 /// Any other DirectoryEntry objects retrieved from this instance (for
420 /// example, through Children) are automatically created with the same
421 /// alternate credentials.
423 [DSDescription ("The password to use when authenticating the client.")]
424 [DefaultValue (null)]
426 public string Password
438 /// Gets or sets the user name to use when authenticating the client.
441 /// The user name to use when authenticating the client.
444 /// You can set the user name and Password in order to specify alternate
445 /// credentials with which to access the information in Ldap Directory.
446 /// Any other DirectoryEntry objects retrieved from this instance (for
447 /// example, through Children) are automatically created with the same
450 [DSDescription ("The user name to use when authenticating the client.")]
451 [DefaultValue (null)]
453 [TypeConverter ("System.Diagnostics.Design.StringValueConverter, " + Consts.AssemblySystem_Design)]
454 public string Username
466 /// Gets or sets the path for this DirectoryEntry.
469 /// The path of this DirectoryEntry. The default is an empty string ("").
472 /// The Path property uniquely identifies this entry in a networked
473 /// environment. This entry can always be retrieved using this Path.
475 /// Setting the Path retrieves a new entry from the directory store; it
476 /// does not change the path of the currently bound entry.
478 /// The classes associated with the DirectoryEntry component can be used
479 /// with any of the Directory service providers. Some of the current
480 /// providers are Internet Information Services (IIS), Lightweight Directory
481 /// Access Protocol (Ldap), Novell NetWare Directory Service (NDS), and WinNT.
483 /// Currently we Support only Ldap provider.
484 /// e.g Ldap://[hostname]:[port number]/[ObjectFDN]
486 [DSDescription ("The path for this DirectoryEntry.")]
488 [RecommendedAsConfigurable (true)]
489 [TypeConverter ("System.Diagnostics.Design.StringValueConverter, " + Consts.AssemblySystem_Design)]
497 _Path = String.Empty;
503 internal string ADsPath
506 if (Path == null || Path == String.Empty) {
507 DirectoryEntry rootDse = new DirectoryEntry ();
508 rootDse.InitToRootDse (null,-1);
509 string namingContext = (string) rootDse.Properties ["defaultNamingContext"].Value;
510 if ( namingContext == null )
511 namingContext = (string) rootDse.Properties ["namingContexts"].Value;
513 LdapUrl actualUrl= new LdapUrl (DefaultHost,DefaultPort,namingContext);
514 return actualUrl.ToString ();
521 /// Gets a PropertyCollection of properties set on this object.
524 /// A PropertyCollection of properties set on this object.
526 [DSDescription ("Properties set on this object.")]
527 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
529 public PropertyCollection Properties
532 return GetProperties (true);
537 /// Gets the name of the schema used for this DirectoryEntry
540 /// The name of the schema used for this DirectoryEntry.
542 [DSDescription ("The name of the schema used for this DirectoryEntry.")]
543 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
545 public string SchemaClassName
548 if(_SchemaClassName==null) {
549 _SchemaClassName = FindAttrValue("structuralObjectClass");
551 return _SchemaClassName;
556 /// Gets the current schema directory entry.
559 /// Not implemented yet
560 [DSDescription ("The current schema directory entry.")]
561 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
563 public DirectoryEntry SchemaEntry
567 throw new NotImplementedException();
571 private string DefaultHost
574 string defaultHost = (string) AppDomain.CurrentDomain.GetData (DEFAULT_LDAP_HOST);
576 if (defaultHost == null) {
577 NameValueCollection config = (NameValueCollection) ConfigurationSettings.GetConfig ("System.DirectoryServices/Settings");
579 defaultHost = config ["servername"];
581 if (defaultHost == null)
582 defaultHost = "localhost";
584 AppDomain.CurrentDomain.SetData (DEFAULT_LDAP_HOST,defaultHost);
590 private int DefaultPort
593 string defaultPortStr = (string) AppDomain.CurrentDomain.GetData (DEFAULT_LDAP_PORT);
595 if (defaultPortStr == null) {
596 NameValueCollection config = (NameValueCollection) ConfigurationSettings.GetConfig ("System.DirectoryServices/Settings");
598 defaultPortStr = config ["port"];
600 if (defaultPortStr == null)
601 defaultPortStr = "389";
603 AppDomain.CurrentDomain.SetData (DEFAULT_LDAP_PORT,defaultPortStr);
605 return Int32.Parse (defaultPortStr);
609 private void InitToRootDse(string host,int port)
616 LdapUrl rootPath = new LdapUrl (host,port,String.Empty);
617 string [] attrs = new string [] {"+","*"};
618 DirectoryEntry rootEntry = new DirectoryEntry (rootPath.ToString (),this.Username,this.Password,this.AuthenticationType);
619 DirectorySearcher searcher = new DirectorySearcher (rootEntry,null,attrs,SearchScope.Base);
621 SearchResult result = searcher.FindOne ();
622 // copy properties from search result
623 PropertyCollection pcoll = new PropertyCollection ();
624 foreach (string propertyName in result.Properties.PropertyNames) {
625 System.Collections.IEnumerator enumerator = result.Properties [propertyName].GetEnumerator ();
626 if (enumerator != null)
627 while (enumerator.MoveNext ())
628 if (String.Compare (propertyName,"ADsPath",true) != 0)
629 pcoll [propertyName].Add (enumerator.Current);
631 this.SetProperties (pcoll);
632 this._Name = "rootDSE";
635 private void SetProperties(PropertyCollection pcoll)
641 /// Returns entry properties.
643 /// <param name="forceLoad">Specifies whenever to force the properties load from the server if local property cache is empty.</param>
644 /// <returns></returns>
645 private PropertyCollection GetProperties(bool forceLoad)
647 if (_Properties == null) {
648 // load properties into a different collection
649 // to preserve original collection state if exception occurs
650 PropertyCollection properties = new PropertyCollection (this);
651 if (forceLoad && !Nflag)
652 LoadProperties (properties,null);
654 _Properties = properties ;
660 /// Loads the values of the specified properties into the property cache.
662 /// <param name="propertyNames">An array of the specified properties.</param>
663 private void LoadProperties(PropertyCollection properties,string[] propertyNames)
665 _inPropertiesLoading = true;
667 LdapSearchResults lsc=conn.Search (Fdn,LdapConnection.SCOPE_BASE,"objectClass=*",propertyNames,false);
668 if (lsc.hasMore ()) {
669 LdapEntry nextEntry = lsc.next ();
670 string [] lowcasePropertyNames = null;
672 if (propertyNames != null) {
673 length = propertyNames.Length;
674 lowcasePropertyNames = new string [length];
675 for(int i=0; i < length; i++)
676 lowcasePropertyNames [i] = propertyNames [i].ToLower ();
678 foreach (LdapAttribute attribute in nextEntry.getAttributeSet ()) {
679 string attributeName = attribute.Name;
680 if ((propertyNames == null) || (Array.IndexOf (lowcasePropertyNames,attributeName.ToLower ()) != -1)) {
681 properties [attributeName].Value = null;
682 properties [attributeName].AddRange (attribute.StringValueArray);
683 properties [attributeName].Mbit=false;
689 _inPropertiesLoading = false;
694 /// Searches an entry in the Ldap directory and returns the attribute value
696 /// <param name="attrName">attribute whose value is required</param>
697 /// <returns> value of the attribute stored in Ldap directory</returns>
698 private string FindAttrValue(string attrName)
701 string[] attrs={attrName};
703 LdapSearchResults lsc=conn.Search( Fdn,
704 LdapConnection.SCOPE_BASE,
708 while(lsc.hasMore()) {
709 LdapEntry nextEntry = null;
711 nextEntry = lsc.next();
713 catch(LdapException e) {
714 // Exception is thrown, go for next entry
717 LdapAttribute attribute = nextEntry.getAttribute(attrName);
718 aValue = attribute.StringValue;
725 /// Modifies an entry in the Ldap directory with the input LdapModification
728 /// <param name="mods">Array consisting of the entry attribute name and the
729 /// attribute values to be modified.</param>
730 private void ModEntry(LdapModification[] mods)
734 conn.Modify(Fdn,mods);
736 catch(LdapException le) {
742 /// Checks whether the entry exists in the Ldap directory or not
744 /// <param name="lconn">
745 /// Connection used to communicate with directory
747 /// <param name="epath">
748 /// path of the entry
751 /// true of the entry exists in the Ldap directory
752 /// false if entry doesn't exists
754 private static bool CheckEntry(LdapConnection lconn, string epath)
756 LdapUrl lUrl=new LdapUrl(epath);
757 string eDn=lUrl.getDN();
762 // rootDSE is a "virtual" entry that always exists
763 else if (String.Compare (eDn,"rootDSE",true) == 0)
766 string[] attrs={"objectClass"};
769 LdapSearchResults lsc=lconn.Search( eDn,
770 LdapConnection.SCOPE_BASE,
776 LdapEntry nextEntry = null;
779 nextEntry = lsc.next();
781 catch(LdapException e)
783 // Exception is thrown, go for next entry
790 catch(LdapException le)
792 if(le.ResultCode == LdapException.NO_SUCH_OBJECT)
809 /// Closes the DirectoryEntry and releases any system resources associated
810 /// with this component.
813 /// Following a call to Close, any operations on the DirectoryEntry might
814 /// raise exceptions.
818 if (_conn != null && _conn.Connected) {
824 /// Creates a copy of this entry as a child of the specified parent.
826 /// <param name="newParent">The parent DirectoryEntry. </param>
827 /// <returns>A copy of this entry as a child of the specified parent.
829 public DirectoryEntry CopyTo(DirectoryEntry newParent)
831 throw new NotImplementedException();
835 /// Deletes this entry and its entire subtree from the Active Directory
839 /// CAUTION The entry and its entire subtree are deleted from the
840 /// Ldap Directory hierarchy.
842 public void DeleteTree()
844 System.Collections.IEnumerator ienum = Children.GetEnumerator();
845 while(ienum.MoveNext())
847 DirectoryEntry de=(DirectoryEntry)ienum.Current;
854 /// Searches the directory store at the specified path to see whether
857 /// <param name="path">
858 /// The path at which to search the directory store.
861 /// true if an entry exists in the directory store at the specified
862 /// path; otherwise, false.
864 public static bool Exists(string path)
866 LdapConnection aconn=new LdapConnection();
867 LdapUrl lurl=new LdapUrl(path);
868 aconn.Connect(lurl.Host,lurl.Port);
870 if(CheckEntry(aconn,path))
877 /// Moves this entry to the specified parent.
879 /// <param name="pentry">
880 /// The parent to which you want to move this entry
882 public void MoveTo(DirectoryEntry newParent)
884 string oldParentFdn = Parent.Fdn;
885 conn.Rename(Fdn, Name, newParent.Fdn, true);
886 // TBD : threat multiple name instance in path
887 Path = Path.Replace(oldParentFdn,newParent.Fdn);
892 /// Moves this entry to the specified parent and changes its name to
893 /// the value of the newName parameter.
895 /// <param name="newParent"> The parent to which you want to move
898 /// <param name="newName">
899 /// The new name of this entry.
901 public void MoveTo( DirectoryEntry newParent,
904 string oldParentFdn = Parent.Fdn;
905 conn.Rename(Fdn, newName, newParent.Fdn, true);
906 // TBD : threat multiple name instance in path
907 Path = Path.Replace(oldParentFdn,newParent.Fdn).Replace(Name,newName);
912 /// Changes the name of this entry.
914 /// <param name="newName">
915 /// The new name of the entry.
918 /// Note This will also affect the path used to refer to this entry.
920 public void Rename( string newName )
922 string oldName = Name;
923 conn.Rename( Fdn, newName, true);
924 // TBD : threat multiple name instance in path
925 Path = Path.Replace(oldName,newName);
930 /// Calls a method on the native Active Directory.
932 /// <param name="methodName">The name of the method to invoke.
934 /// <param name="args">
935 /// An array of type Object that contains the arguments of the method
938 /// <returns>The return value of the invoked method</returns>
942 public object Invoke(string methodName,
943 params object[] args)
945 throw new NotImplementedException();
949 /// Creates a copy of this entry, as a child of the specified parent, with
950 /// the specified new name.
952 /// <param name="newParent">The parent DirectoryEntry. </param>
953 /// <param name="newName"> The name of the copy of this entry.
955 /// <returns>A renamed copy of this entry as a child of the specified parent.
957 public DirectoryEntry CopyTo( DirectoryEntry newParent,
960 throw new NotImplementedException();
964 /// Saves any changes to the entry in the Ldap Directory store.
967 /// By default, changes to properties are done locally to a cache, and
968 /// property values to be read are cached after the first read. For more
969 /// information, see UsePropertyCache.
970 /// Changes made to the cache include changes to the properties as well as
971 /// calls to Add (if this is the newly created entry).
973 public void CommitChanges()
981 private void CommitEntry()
983 PropertyCollection properties = GetProperties(false);
986 System.Collections.ArrayList modList = new System.Collections.ArrayList();
987 foreach (string attribute in properties.PropertyNames)
989 LdapAttribute attr=null;
990 if (properties [attribute].Mbit)
992 if (properties [attribute].Count == 1)
994 string val = (string) properties [attribute].Value;
995 attr = new LdapAttribute( attribute , val);
999 object[] vals =(object []) properties [attribute].Value;
1000 string[] aStrVals = new string [properties [attribute].Count];
1001 Array.Copy (vals,0,aStrVals,0,properties [attribute].Count);
1002 attr = new LdapAttribute( attribute , aStrVals);
1004 modList.Add( new LdapModification(LdapModification.REPLACE, attr));
1005 properties [attribute].Mbit=false;
1008 if (modList.Count > 0) {
1009 LdapModification[] mods = new LdapModification[modList.Count];
1010 Type mtype=Type.GetType("System.DirectoryServices.LdapModification");
1011 mods = (LdapModification[])modList.ToArray(typeof(LdapModification));
1017 LdapAttributeSet attributeSet = new LdapAttributeSet();
1018 foreach (string attribute in properties.PropertyNames)
1020 if (properties [attribute].Count == 1)
1022 string val = (string) properties [attribute].Value;
1023 attributeSet.Add(new LdapAttribute(attribute, val));
1027 object[] vals = (object []) properties [attribute].Value;
1028 string[] aStrVals = new string [properties [attribute].Count];
1029 Array.Copy (vals,0,aStrVals,0,properties [attribute].Count);
1030 attributeSet.Add( new LdapAttribute( attribute , aStrVals));
1033 LdapEntry newEntry = new LdapEntry( Fdn, attributeSet );
1034 conn.Add( newEntry );
1039 internal void CommitDeferred()
1041 if (!_inPropertiesLoading && !UsePropertyCache && !Nflag)
1053 _SchemaClassName = null;
1058 /// Loads the values of the specified properties into the property cache.
1060 public void RefreshCache ()
1062 // note that GetProperties must be called with false, elswere infinite loop will be caused
1063 PropertyCollection properties = new PropertyCollection ();
1064 LoadProperties(properties, null);
1065 SetProperties (properties);
1069 /// Loads the values of the specified properties into the property cache.
1071 /// <param name="propertyNames">An array of the specified properties. </param>
1072 public void RefreshCache (string[] propertyNames)
1074 // note that GetProperties must be called with false, elswere infinite loop will be caused
1075 LoadProperties(GetProperties(false),propertyNames);
1078 protected override void Dispose (bool disposing)
1083 base.Dispose (disposing);
1086 internal static string GetLdapUrlString(string host, int port, string dn)
1089 if (port == LdapConnection.DEFAULT_PORT)
1090 lUrl = new LdapUrl (host,0,dn);
1092 lUrl = new LdapUrl (host,port,dn);
1093 return lUrl.ToString();