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 *******************************************************************************/
24 // Novell.Directory.Ldap.LdapAttribute.cs
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
33 using ArrayEnumeration
= Novell
.Directory
.Ldap
.Utilclass
.ArrayEnumeration
;
34 using Base64
= Novell
.Directory
.Ldap
.Utilclass
.Base64
;
36 namespace Novell
.Directory
.Ldap
38 /// <summary> The name and values of one attribute of a directory entry.
40 /// LdapAttribute objects are used when searching for, adding,
41 /// modifying, and deleting attributes from the directory.
42 /// LdapAttributes are often used in conjunction with an
43 /// {@link LdapAttributeSet} when retrieving or adding multiple
44 /// attributes to an entry.
49 /// <seealso cref="LdapEntry">
51 /// <seealso cref="LdapAttributeSet">
53 /// <seealso cref="LdapModification">
56 public class LdapAttribute
: System
.ICloneable
, System
.IComparable
60 private void InitBlock(LdapAttribute enclosingInstance
)
62 this.enclosingInstance
= enclosingInstance
;
64 private LdapAttribute enclosingInstance
;
65 public LdapAttribute Enclosing_Instance
69 return enclosingInstance
;
75 public URLData(LdapAttribute enclosingInstance
, sbyte[] data
, int length
)
77 InitBlock(enclosingInstance
);
82 public int getLength()
86 public sbyte[] getData()
91 /// <summary> Returns an enumerator for the values of the attribute in byte format.
94 /// <returns> The values of the attribute in byte format.
95 /// Note: All string values will be UTF-8 encoded. To decode use the
96 /// String constructor. Example: new String( byteArray, "UTF-8" );
98 virtual public System
.Collections
.IEnumerator ByteValues
102 return new ArrayEnumeration(ByteValueArray
);
106 /// <summary> Returns an enumerator for the string values of an attribute.
109 /// <returns> The string values of an attribute.
111 virtual public System
.Collections
.IEnumerator StringValues
115 return new ArrayEnumeration(StringValueArray
);
119 /// <summary> Returns the values of the attribute as an array of bytes.
122 /// <returns> The values as an array of bytes or an empty array if there are
125 [CLSCompliantAttribute(false)]
126 virtual public sbyte[][] ByteValueArray
130 if (null == this.values
)
131 return new sbyte[0][];
132 int size
= this.values
.Length
;
133 sbyte[][] bva
= new sbyte[size
][];
134 // Deep copy so application cannot change values
135 for (int i
= 0, u
= size
; i
< u
; i
++)
137 bva
[i
] = new sbyte[((sbyte[]) values
[i
]).Length
];
138 Array
.Copy((System
.Array
) this.values
[i
], 0, (System
.Array
) bva
[i
], 0, bva
[i
].Length
);
144 /// <summary> Returns the values of the attribute as an array of strings.
147 /// <returns> The values as an array of strings or an empty array if there are
150 virtual public System
.String
[] StringValueArray
154 if (null == this.values
)
155 return new System
.String
[0];
156 int size
= values
.Length
;
157 System
.String
[] sva
= new System
.String
[size
];
158 for (int j
= 0; j
< size
; j
++)
162 System
.Text
.Encoding encoder
= System
.Text
.Encoding
.GetEncoding("utf-8");
163 char[] dchar
= encoder
.GetChars(SupportClass
.ToByteArray((sbyte[])values
[j
]));
164 // char[] dchar = encoder.GetChars((byte[])values[j]);
165 sva
[j
] = new String(dchar
);
166 // sva[j] = new String((sbyte[]) values[j], "UTF-8");
168 catch (System
.IO
.IOException uee
)
170 // Exception should NEVER get thrown but just in case it does ...
171 throw new System
.SystemException(uee
.ToString());
178 /// <summary> Returns the the first value of the attribute as a <code>String</code>.
181 /// <returns> The UTF-8 encoded<code>String</code> value of the attribute's
182 /// value. If the value wasn't a UTF-8 encoded <code>String</code>
183 /// to begin with the value of the returned <code>String</code> is
184 /// non deterministic.
186 /// If <code>this</code> attribute has more than one value the
187 /// first value is converted to a UTF-8 encoded <code>String</code>
188 /// and returned. It should be noted, that the directory may
189 /// return attribute values in any order, so that the first
190 /// value may vary from one call to another.
192 /// If the attribute has no values <code>null</code> is returned
194 virtual public System
.String StringValue
198 System
.String rval
= null;
199 if (this.values
!= null)
203 System
.Text
.Encoding encoder
= System
.Text
.Encoding
.GetEncoding("utf-8");
204 char[] dchar
= encoder
.GetChars(SupportClass
.ToByteArray((sbyte[])this.values
[0]));
205 // char[] dchar = encoder.GetChars((byte[]) this.values[0]);
206 rval
= new String(dchar
);
208 catch (System
.IO
.IOException use
)
210 throw new System
.SystemException(use
.ToString());
217 /// <summary> Returns the the first value of the attribute as a byte array.
220 /// <returns> The binary value of <code>this</code> attribute or
221 /// <code>null</code> if <code>this</code> attribute doesn't have a value.
223 /// If the attribute has no values <code>null</code> is returned
225 [CLSCompliantAttribute(false)]
226 virtual public sbyte[] ByteValue
231 if (this.values
!= null)
233 // Deep copy so app can't change the value
234 bva
= new sbyte[((sbyte[]) values
[0]).Length
];
235 Array
.Copy((System
.Array
) this.values
[0], 0, (System
.Array
) bva
, 0, bva
.Length
);
241 /// <summary> Returns the language subtype of the attribute, if any.
243 /// For example, if the attribute name is cn;lang-ja;phonetic,
244 /// this method returns the string, lang-ja.
247 /// <returns> The language subtype of the attribute or null if the attribute
250 virtual public System
.String LangSubtype
254 if (subTypes
!= null)
256 for (int i
= 0; i
< subTypes
.Length
; i
++)
258 if (subTypes
[i
].StartsWith("lang-"))
268 /// <summary> Returns the name of the attribute.
271 /// <returns> The name of the attribute.
273 virtual public System
.String Name
281 /// <summary> Replaces all values with the specified value. This protected method is
282 /// used by sub-classes of LdapSchemaElement because the value cannot be set
283 /// with a contructor.
285 virtual protected internal System
.String Value
292 System
.Text
.Encoding encoder
= System
.Text
.Encoding
.GetEncoding("utf-8");
293 byte[] ibytes
= encoder
.GetBytes(value);
294 sbyte[] sbytes
=SupportClass
.ToSByteArray(ibytes
);
298 catch (System
.IO
.IOException ue
)
300 throw new System
.SystemException(ue
.ToString());
306 private System
.String name
; // full attribute name
307 private System
.String baseName
; // cn of cn;lang-ja;phonetic
308 private System
.String
[] subTypes
= null; // lang-ja of cn;lang-ja
309 private System
.Object
[] values
= null; // Array of byte[] attribute values
311 /// <summary> Constructs an attribute with copies of all values of the input
315 /// <param name="attr"> An LdapAttribute to use as a template.
317 /// @throws IllegalArgumentException if attr is null
319 public LdapAttribute(LdapAttribute attr
)
323 throw new System
.ArgumentException("LdapAttribute class cannot be null");
325 // Do a deep copy of the LdapAttribute template
326 this.name
= attr
.name
;
327 this.baseName
= attr
.baseName
;
328 if (null != attr
.subTypes
)
330 this.subTypes
= new System
.String
[attr
.subTypes
.Length
];
331 Array
.Copy((System
.Array
) attr
.subTypes
, 0, (System
.Array
) this.subTypes
, 0, this.subTypes
.Length
);
333 // OK to just copy attributes, as the app only sees a deep copy of them
334 if (null != attr
.values
)
336 this.values
= new System
.Object
[attr
.values
.Length
];
337 Array
.Copy((System
.Array
) attr
.values
, 0, (System
.Array
) this.values
, 0, this.values
.Length
);
342 /// <summary> Constructs an attribute with no values.
345 /// <param name="attrName">Name of the attribute.
347 /// @throws IllegalArgumentException if attrName is null
349 public LdapAttribute(System
.String attrName
)
351 if ((System
.Object
) attrName
== null)
353 throw new System
.ArgumentException("Attribute name cannot be null");
355 this.name
= attrName
;
356 this.baseName
= LdapAttribute
.getBaseName(attrName
);
357 this.subTypes
= LdapAttribute
.getSubtypes(attrName
);
361 /// <summary> Constructs an attribute with a byte-formatted value.
364 /// <param name="attrName">Name of the attribute.
366 /// <param name="attrBytes">Value of the attribute as raw bytes.
368 /// Note: If attrBytes represents a string it should be UTF-8 encoded.
370 /// @throws IllegalArgumentException if attrName or attrBytes is null
372 [CLSCompliantAttribute(false)]
373 public LdapAttribute(System
.String attrName
, sbyte[] attrBytes
):this(attrName
)
375 if (attrBytes
== null)
377 throw new System
.ArgumentException("Attribute value cannot be null");
379 // Make our own copy of the byte array to prevent app from changing it
380 sbyte[] tmp
= new sbyte[attrBytes
.Length
];
381 Array
.Copy((System
.Array
) attrBytes
, 0, (System
.Array
)tmp
, 0, attrBytes
.Length
);
386 /// <summary> Constructs an attribute with a single string value.
389 /// <param name="attrName">Name of the attribute.
391 /// <param name="attrString">Value of the attribute as a string.
393 /// @throws IllegalArgumentException if attrName or attrString is null
395 public LdapAttribute(System
.String attrName
, System
.String attrString
):this(attrName
)
397 if ((System
.Object
) attrString
== null)
399 throw new System
.ArgumentException("Attribute value cannot be null");
403 System
.Text
.Encoding encoder
= System
.Text
.Encoding
.GetEncoding("utf-8");
404 byte[] ibytes
= encoder
.GetBytes(attrString
);
405 sbyte[] sbytes
=SupportClass
.ToSByteArray(ibytes
);
409 catch (System
.IO
.IOException e
)
411 throw new System
.SystemException(e
.ToString());
416 /// <summary> Constructs an attribute with an array of string values.
419 /// <param name="attrName">Name of the attribute.
421 /// <param name="attrStrings">Array of values as strings.
423 /// @throws IllegalArgumentException if attrName, attrStrings, or a member
424 /// of attrStrings is null
426 public LdapAttribute(System
.String attrName
, System
.String
[] attrStrings
):this(attrName
)
428 if (attrStrings
== null)
430 throw new System
.ArgumentException("Attribute values array cannot be null");
432 for (int i
= 0, u
= attrStrings
.Length
; i
< u
; i
++)
436 if ((System
.Object
) attrStrings
[i
] == null)
438 throw new System
.ArgumentException("Attribute value " + "at array index " + i
+ " cannot be null");
440 System
.Text
.Encoding encoder
= System
.Text
.Encoding
.GetEncoding("utf-8");
441 byte[] ibytes
= encoder
.GetBytes(attrStrings
[i
]);
442 sbyte[] sbytes
=SupportClass
.ToSByteArray(ibytes
);
444 // this.add(attrStrings[i].getBytes("UTF-8"));
446 catch (System
.IO
.IOException e
)
448 throw new System
.SystemException(e
.ToString());
454 /// <summary> Returns a clone of this LdapAttribute.
457 /// <returns> clone of this LdapAttribute.
459 public System
.Object
Clone()
463 System
.Object newObj
= base.MemberwiseClone();
466 Array
.Copy((System
.Array
) this.values
, 0, (System
.Array
) ((LdapAttribute
) newObj
).values
, 0, this.values
.Length
);
470 catch (System
.Exception ce
)
472 throw new System
.SystemException("Internal error, cannot create clone");
476 /// <summary> Adds a string value to the attribute.
479 /// <param name="attrString">Value of the attribute as a String.
481 /// @throws IllegalArgumentException if attrString is null
483 public virtual void addValue(System
.String attrString
)
485 if ((System
.Object
) attrString
== null)
487 throw new System
.ArgumentException("Attribute value cannot be null");
491 System
.Text
.Encoding encoder
= System
.Text
.Encoding
.GetEncoding("utf-8");
492 byte[] ibytes
= encoder
.GetBytes(attrString
);
493 sbyte[] sbytes
=SupportClass
.ToSByteArray(ibytes
);
495 // this.add(attrString.getBytes("UTF-8"));
497 catch (System
.IO
.IOException ue
)
499 throw new System
.SystemException(ue
.ToString());
504 /// <summary> Adds a byte-formatted value to the attribute.
507 /// <param name="attrBytes">Value of the attribute as raw bytes.
509 /// Note: If attrBytes represents a string it should be UTF-8 encoded.
511 /// @throws IllegalArgumentException if attrBytes is null
513 [CLSCompliantAttribute(false)]
514 public virtual void addValue(sbyte[] attrBytes
)
516 if (attrBytes
== null)
518 throw new System
.ArgumentException("Attribute value cannot be null");
524 /// <summary> Adds a base64 encoded value to the attribute.
525 /// The value will be decoded and stored as bytes. String
526 /// data encoded as a base64 value must be UTF-8 characters.
529 /// <param name="attrString">The base64 value of the attribute as a String.
531 /// @throws IllegalArgumentException if attrString is null
533 public virtual void addBase64Value(System
.String attrString
)
535 if ((System
.Object
) attrString
== null)
537 throw new System
.ArgumentException("Attribute value cannot be null");
540 this.add(Base64
.decode(attrString
));
544 /// <summary> Adds a base64 encoded value to the attribute.
545 /// The value will be decoded and stored as bytes. Character
546 /// data encoded as a base64 value must be UTF-8 characters.
549 /// <param name="attrString">The base64 value of the attribute as a StringBuffer.
551 /// <param name="start"> The start index of base64 encoded part, inclusive.
553 /// <param name="end"> The end index of base encoded part, exclusive.
555 /// @throws IllegalArgumentException if attrString is null
557 public virtual void addBase64Value(System
.Text
.StringBuilder attrString
, int start
, int end
)
559 if (attrString
== null)
561 throw new System
.ArgumentException("Attribute value cannot be null");
564 this.add(Base64
.decode(attrString
, start
, end
));
569 /// <summary> Adds a base64 encoded value to the attribute.
570 /// The value will be decoded and stored as bytes. Character
571 /// data encoded as a base64 value must be UTF-8 characters.
574 /// <param name="attrChars">The base64 value of the attribute as an array of
577 /// @throws IllegalArgumentException if attrString is null
579 public virtual void addBase64Value(char[] attrChars
)
581 if (attrChars
== null)
583 throw new System
.ArgumentException("Attribute value cannot be null");
586 this.add(Base64
.decode(attrChars
));
590 /// <summary> Adds a URL, indicating a file or other resource that contains
591 /// the value of the attribute.
594 /// <param name="url">String value of a URL pointing to the resource containing
595 /// the value of the attribute.
597 /// @throws IllegalArgumentException if url is null
599 public virtual void addURLValue(System
.String url
)
601 if ((System
.Object
) url
== null)
603 throw new System
.ArgumentException("Attribute URL cannot be null");
605 addURLValue(new System
.Uri(url
));
609 /// <summary> Adds a URL, indicating a file or other resource that contains
610 /// the value of the attribute.
613 /// <param name="url">A URL class pointing to the resource containing the value
614 /// of the attribute.
616 /// @throws IllegalArgumentException if url is null
618 public virtual void addURLValue(System
.Uri url
)
620 // Class to encapsulate the data bytes and the length
623 throw new System
.ArgumentException("Attribute URL cannot be null");
627 // Get InputStream from the URL
628 System
.IO
.Stream in_Renamed
= System
.Net
.WebRequest
.Create(url
).GetResponse().GetResponseStream();
629 // Read the bytes into buffers and store the them in an arraylist
630 System
.Collections
.ArrayList bufs
= new System
.Collections
.ArrayList();
631 sbyte[] buf
= new sbyte[4096];
632 int len
, totalLength
= 0;
633 while ((len
= SupportClass
.ReadInput(in_Renamed
, ref buf
, 0, 4096)) != - 1)
635 bufs
.Add(new URLData(this, buf
, len
));
636 buf
= new sbyte[4096];
640 * Now that the length is known, allocate an array to hold all
641 * the bytes of data and copy the data to that array, store
642 * it in this LdapAttribute
644 sbyte[] data
= new sbyte[totalLength
];
646 for (int i
= 0; i
< bufs
.Count
; i
++)
648 URLData b
= (URLData
) bufs
[i
];
650 Array
.Copy((System
.Array
) b
.getData(), 0, (System
.Array
) data
, offset
, len
);
655 catch (System
.IO
.IOException ue
)
657 throw new System
.SystemException(ue
.ToString());
662 /// <summary> Returns the base name of the attribute.
664 /// For example, if the attribute name is cn;lang-ja;phonetic,
665 /// this method returns cn.
668 /// <returns> The base name of the attribute.
670 public virtual System
.String
getBaseName()
675 /// <summary> Returns the base name of the specified attribute name.
677 /// For example, if the attribute name is cn;lang-ja;phonetic,
678 /// this method returns cn.
681 /// <param name="attrName">Name of the attribute from which to extract the
685 /// <returns> The base name of the attribute.
687 /// @throws IllegalArgumentException if attrName is null
689 public static System
.String
getBaseName(System
.String attrName
)
691 if ((System
.Object
) attrName
== null)
693 throw new System
.ArgumentException("Attribute name cannot be null");
695 int idx
= attrName
.IndexOf((System
.Char
) ';');
700 return attrName
.Substring(0, (idx
) - (0));
703 /// <summary> Extracts the subtypes from the attribute name.
705 /// For example, if the attribute name is cn;lang-ja;phonetic,
706 /// this method returns an array containing lang-ja and phonetic.
709 /// <returns> An array subtypes or null if the attribute has none.
711 public virtual System
.String
[] getSubtypes()
716 /// <summary> Extracts the subtypes from the specified attribute name.
718 /// For example, if the attribute name is cn;lang-ja;phonetic,
719 /// this method returns an array containing lang-ja and phonetic.
722 /// <param name="attrName"> Name of the attribute from which to extract
726 /// <returns> An array subtypes or null if the attribute has none.
728 /// @throws IllegalArgumentException if attrName is null
730 public static System
.String
[] getSubtypes(System
.String attrName
)
732 if ((System
.Object
) attrName
== null)
734 throw new System
.ArgumentException("Attribute name cannot be null");
736 SupportClass
.Tokenizer st
= new SupportClass
.Tokenizer(attrName
, ";");
737 System
.String
[] subTypes
= null;
741 st
.NextToken(); // skip over basename
742 subTypes
= new System
.String
[cnt
- 1];
744 while (st
.HasMoreTokens())
746 subTypes
[i
++] = st
.NextToken();
752 /// <summary> Reports if the attribute name contains the specified subtype.
754 /// For example, if you check for the subtype lang-en and the
755 /// attribute name is cn;lang-en, this method returns true.
758 /// <param name="subtype"> The single subtype to check for.
761 /// <returns> True, if the attribute has the specified subtype;
762 /// false, if it doesn't.
764 /// @throws IllegalArgumentException if subtype is null
766 public virtual bool hasSubtype(System
.String subtype
)
768 if ((System
.Object
) subtype
== null)
770 throw new System
.ArgumentException("subtype cannot be null");
772 if (null != this.subTypes
)
774 for (int i
= 0; i
< subTypes
.Length
; i
++)
776 if (subTypes
[i
].ToUpper().Equals(subtype
.ToUpper()))
783 /// <summary> Reports if the attribute name contains all the specified subtypes.
785 /// For example, if you check for the subtypes lang-en and phonetic
786 /// and if the attribute name is cn;lang-en;phonetic, this method
787 /// returns true. If the attribute name is cn;phonetic or cn;lang-en,
788 /// this method returns false.
791 /// <param name="subtypes"> An array of subtypes to check for.
794 /// <returns> True, if the attribute has all the specified subtypes;
795 /// false, if it doesn't have all the subtypes.
797 /// @throws IllegalArgumentException if subtypes is null or if array member
800 public virtual bool hasSubtypes(System
.String
[] subtypes
)
802 if (subtypes
== null)
804 throw new System
.ArgumentException("subtypes cannot be null");
806 for (int i
= 0; i
< subtypes
.Length
; i
++)
808 for (int j
= 0; j
< subTypes
.Length
; j
++)
810 if ((System
.Object
) subTypes
[j
] == null)
812 throw new System
.ArgumentException("subtype " + "at array index " + i
+ " cannot be null");
814 if (subTypes
[j
].ToUpper().Equals(subtypes
[i
].ToUpper()))
825 /// <summary> Removes a string value from the attribute.
828 /// <param name="attrString"> Value of the attribute as a string.
830 /// Note: Removing a value which is not present in the attribute has
833 /// @throws IllegalArgumentException if attrString is null
835 public virtual void removeValue(System
.String attrString
)
837 if (null == (System
.Object
) attrString
)
839 throw new System
.ArgumentException("Attribute value cannot be null");
843 System
.Text
.Encoding encoder
= System
.Text
.Encoding
.GetEncoding("utf-8");
844 byte[] ibytes
= encoder
.GetBytes(attrString
);
845 sbyte[] sbytes
=SupportClass
.ToSByteArray(ibytes
);
846 this.removeValue(sbytes
);
847 // this.removeValue(attrString.getBytes("UTF-8"));
849 catch (System
.IO
.IOException uee
)
851 // This should NEVER happen but just in case ...
852 throw new System
.SystemException(uee
.ToString());
857 /// <summary> Removes a byte-formatted value from the attribute.
860 /// <param name="attrBytes"> Value of the attribute as raw bytes.
861 /// Note: If attrBytes represents a string it should be UTF-8 encoded.
862 /// Example: <code>String.getBytes("UTF-8");</code>
864 /// Note: Removing a value which is not present in the attribute has
867 /// @throws IllegalArgumentException if attrBytes is null
869 [CLSCompliantAttribute(false)]
870 public virtual void removeValue(sbyte[] attrBytes
)
872 if (null == attrBytes
)
874 throw new System
.ArgumentException("Attribute value cannot be null");
876 for (int i
= 0; i
< this.values
.Length
; i
++)
878 if (equals(attrBytes
, (sbyte[]) this.values
[i
]))
880 if (0 == i
&& 1 == this.values
.Length
)
882 // Optimize if first element of a single valued attr
886 if (this.values
.Length
== 1)
892 int moved
= this.values
.Length
- i
- 1;
893 System
.Object
[] tmp
= new System
.Object
[this.values
.Length
- 1];
896 Array
.Copy((System
.Array
) values
, 0, (System
.Array
) tmp
, 0, i
);
900 Array
.Copy((System
.Array
) values
, i
+ 1, (System
.Array
) tmp
, i
, moved
);
911 /// <summary> Returns the number of values in the attribute.
914 /// <returns> The number of values in the attribute.
916 public virtual int size()
918 return null == this.values
?0:this.values
.Length
;
921 /// <summary> Compares this object with the specified object for order.
923 /// Ordering is determined by comparing attribute names (see
924 /// {@link #getName() }) using the method compareTo() of the String class.
928 /// <param name="attribute"> The LdapAttribute to be compared to this object.
931 /// <returns> Returns a negative integer, zero, or a positive
932 /// integer as this object is less than, equal to, or greater than the
933 /// specified object.
935 public virtual int CompareTo(System
.Object attribute
)
938 return name
.CompareTo(((LdapAttribute
) attribute
).name
);
941 /// <summary> Adds an object to <code>this</code> object's list of attribute values
944 /// <param name="bytes"> Ultimately all of this attribute's values are treated
945 /// as binary data so we simplify the process by requiring
946 /// that all data added to our list is in binary form.
948 /// Note: If attrBytes represents a string it should be UTF-8 encoded.
950 private void add(sbyte[] bytes
)
952 if (null == this.values
)
954 this.values
= new System
.Object
[]{bytes}
;
958 // Duplicate attribute values not allowed
959 for (int i
= 0; i
< this.values
.Length
; i
++)
961 if (equals(bytes
, (sbyte[]) this.values
[i
]))
963 return ; // Duplicate, don't add
966 System
.Object
[] tmp
= new System
.Object
[this.values
.Length
+ 1];
967 Array
.Copy((System
.Array
) this.values
, 0, (System
.Array
) tmp
, 0, this.values
.Length
);
968 tmp
[this.values
.Length
] = bytes
;
975 /// <summary> Returns true if the two specified arrays of bytes are equal to each
976 /// another. Matches the logic of Arrays.equals which is not available
980 /// <param name="e1">the first array to be tested
982 /// <param name="e2">the second array to be tested
984 /// <returns> true if the two arrays are equal
986 private bool equals(sbyte[] e1
, sbyte[] e2
)
988 // If same object, they compare true
992 // If either but not both are null, they compare false
993 if (e1
== null || e2
== null)
996 // If arrays have different length, they compare false
997 int length
= e1
.Length
;
998 if (e2
.Length
!= length
)
1001 // If any of the bytes are different, they compare false
1002 for (int i
= 0; i
< length
; i
++)
1011 /// <summary> Returns a string representation of this LdapAttribute
1014 /// <returns> a string representation of this LdapAttribute
1016 public override System
.String
ToString()
1018 System
.Text
.StringBuilder result
= new System
.Text
.StringBuilder("LdapAttribute: ");
1021 result
.Append("{type='" + name
+ "'");
1024 result
.Append(", ");
1025 if (values
.Length
== 1)
1027 result
.Append("value='");
1031 result
.Append("values='");
1033 for (int i
= 0; i
< values
.Length
; i
++)
1037 result
.Append("','");
1039 if (((sbyte[]) values
[i
]).Length
== 0)
1043 System
.Text
.Encoding encoder
= System
.Text
.Encoding
.GetEncoding("utf-8");
1044 // char[] dchar = encoder.GetChars((byte[]) values[i]);
1045 char[] dchar
= encoder
.GetChars(SupportClass
.ToByteArray((sbyte[])values
[i
]));
1046 System
.String sval
= new String(dchar
);
1048 // System.String sval = new String((sbyte[]) values[i], "UTF-8");
1049 if (sval
.Length
== 0)
1051 // didn't decode well, must be binary
1052 result
.Append("<binary value, length:" + sval
.Length
);
1055 result
.Append(sval
);
1061 catch (System
.Exception e
)
1063 throw new System
.SystemException(e
.ToString());
1065 return result
.ToString();