History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/naming/directory/BasicAttribute.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/naming/directory/BasicAttribute.java+556−0
@@ -0,0 +1,556 @@
1+/*
2+ * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package javax.naming.directory;
27+
28+import java.util.Vector;
29+import java.util.Enumeration;
30+import java.util.NoSuchElementException;
31+import java.lang.reflect.Array;
32+
33+import javax.naming.NamingException;
34+import javax.naming.NamingEnumeration;
35+import javax.naming.OperationNotSupportedException;
36+
37+/**
38+ * This class provides a basic implementation of the <tt>Attribute</tt> interface.
39+ *<p>
40+ * This implementation does not support the schema methods
41+ * <tt>getAttributeDefinition()</tt> and <tt>getAttributeSyntaxDefinition()</tt>.
42+ * They simply throw <tt>OperationNotSupportedException</tt>.
43+ * Subclasses of <tt>BasicAttribute</tt> should override these methods if they
44+ * support them.
45+ *<p>
46+ * The <tt>BasicAttribute</tt> class by default uses <tt>Object.equals()</tt> to
47+ * determine equality of attribute values when testing for equality or
48+ * when searching for values, <em>except</em> when the value is an array.
49+ * For an array, each element of the array is checked using <tt>Object.equals()</tt>.
50+ * Subclasses of <tt>BasicAttribute</tt> can make use of schema information
51+ * when doing similar equality checks by overriding methods
52+ * in which such use of schema is meaningful.
53+ * Similarly, the <tt>BasicAttribute</tt> class by default returns the values passed to its
54+ * constructor and/or manipulated using the add/remove methods.
55+ * Subclasses of <tt>BasicAttribute</tt> can override <tt>get()</tt> and <tt>getAll()</tt>
56+ * to get the values dynamically from the directory (or implement
57+ * the <tt>Attribute</tt> interface directly instead of subclassing <tt>BasicAttribute</tt>).
58+ *<p>
59+ * Note that updates to <tt>BasicAttribute</tt> (such as adding or removing a value)
60+ * does not affect the corresponding representation of the attribute
61+ * in the directory. Updates to the directory can only be effected
62+ * using operations in the <tt>DirContext</tt> interface.
63+ *<p>
64+ * A <tt>BasicAttribute</tt> instance is not synchronized against concurrent
65+ * multithreaded access. Multiple threads trying to access and modify a
66+ * <tt>BasicAttribute</tt> should lock the object.
67+ *
68+ * @author Rosanna Lee
69+ * @author Scott Seligman
70+ * @since 1.3
71+ */
72+public class BasicAttribute implements Attribute {
73+ /**
74+ * Holds the attribute's id. It is initialized by the public constructor and
75+ * cannot be null unless methods in BasicAttribute that use attrID
76+ * have been overridden.
77+ * @serial
78+ */
79+ protected String attrID;
80+
81+ /**
82+ * Holds the attribute's values. Initialized by public constructors.
83+ * Cannot be null unless methods in BasicAttribute that use
84+ * values have been overridden.
85+ */
86+ protected transient Vector<Object> values;
87+
88+ /**
89+ * A flag for recording whether this attribute's values are ordered.
90+ * @serial
91+ */
92+ protected boolean ordered = false;
93+
94+ public Object clone() {
95+ BasicAttribute attr;
96+ try {
97+ attr = (BasicAttribute)super.clone();
98+ } catch (CloneNotSupportedException e) {
99+ attr = new BasicAttribute(attrID, ordered);
100+ }
101+ attr.values = (Vector)values.clone();
102+ return attr;
103+ }
104+
105+ /**
106+ * Determines whether obj is equal to this attribute.
107+ * Two attributes are equal if their attribute-ids, syntaxes
108+ * and values are equal.
109+ * If the attribute values are unordered, the order that the values were added
110+ * are irrelevant. If the attribute values are ordered, then the
111+ * order the values must match.
112+ * If obj is null or not an Attribute, false is returned.
113+ *<p>
114+ * By default <tt>Object.equals()</tt> is used when comparing the attribute
115+ * id and its values except when a value is an array. For an array,
116+ * each element of the array is checked using <tt>Object.equals()</tt>.
117+ * A subclass may override this to make
118+ * use of schema syntax information and matching rules,
119+ * which define what it means for two attributes to be equal.
120+ * How and whether a subclass makes
121+ * use of the schema information is determined by the subclass.
122+ * If a subclass overrides <tt>equals()</tt>, it should also override
123+ * <tt>hashCode()</tt>
124+ * such that two attributes that are equal have the same hash code.
125+ *
126+ * @param obj The possibly null object to check.
127+ * @return true if obj is equal to this attribute; false otherwise.
128+ * @see #hashCode
129+ * @see #contains
130+ */
131+ public boolean equals(Object obj) {
132+ if ((obj != null) && (obj instanceof Attribute)) {
133+ Attribute target = (Attribute)obj;
134+
135+ // Check order first
136+ if (isOrdered() != target.isOrdered()) {
137+ return false;
138+ }
139+ int len;
140+ if (attrID.equals(target.getID()) &&
141+ (len=size()) == target.size()) {
142+ try {
143+ if (isOrdered()) {
144+ // Go through both list of values
145+ for (int i = 0; i < len; i++) {
146+ if (!valueEquals(get(i), target.get(i))) {
147+ return false;
148+ }
149+ }
150+ } else {
151+ // order is not relevant; check for existence
152+ Enumeration theirs = target.getAll();
153+ while (theirs.hasMoreElements()) {
154+ if (find(theirs.nextElement()) < 0)
155+ return false;
156+ }
157+ }
158+ } catch (NamingException e) {
159+ return false;
160+ }
161+ return true;
162+ }
163+ }
164+ return false;
165+ }
166+
167+ /**
168+ * Calculates the hash code of this attribute.
169+ *<p>
170+ * The hash code is computed by adding the hash code of
171+ * the attribute's id and that of all of its values except for
172+ * values that are arrays.
173+ * For an array, the hash code of each element of the array is summed.
174+ * If a subclass overrides <tt>hashCode()</tt>, it should override
175+ * <tt>equals()</tt>
176+ * as well so that two attributes that are equal have the same hash code.
177+ *
178+ * @return an int representing the hash code of this attribute.
179+ * @see #equals
180+ */
181+ public int hashCode() {
182+ int hash = attrID.hashCode();
183+ int num = values.size();
184+ Object val;
185+ for (int i = 0; i < num; i ++) {
186+ val = values.elementAt(i);
187+ if (val != null) {
188+ if (val.getClass().isArray()) {
189+ Object it;
190+ int len = Array.getLength(val);
191+ for (int j = 0 ; j < len ; j++) {
192+ it = Array.get(val, j);
193+ if (it != null) {
194+ hash += it.hashCode();
195+ }
196+ }
197+ } else {
198+ hash += val.hashCode();
199+ }
200+ }
201+ }
202+ return hash;
203+ }
204+
205+ /**
206+ * Generates the string representation of this attribute.
207+ * The string consists of the attribute's id and its values.
208+ * This string is meant for debugging and not meant to be
209+ * interpreted programmatically.
210+ * @return The non-null string representation of this attribute.
211+ */
212+ public String toString() {
213+ StringBuffer answer = new StringBuffer(attrID + ": ");
214+ if (values.size() == 0) {
215+ answer.append("No values");
216+ } else {
217+ boolean start = true;
218+ for (Enumeration e = values.elements(); e.hasMoreElements(); ) {
219+ if (!start)
220+ answer.append(", ");
221+ answer.append(e.nextElement());
222+ start = false;
223+ }
224+ }
225+ return answer.toString();
226+ }
227+
228+ /**
229+ * Constructs a new instance of an unordered attribute with no value.
230+ *
231+ * @param id The attribute's id. It cannot be null.
232+ */
233+ public BasicAttribute(String id) {
234+ this(id, false);
235+ }
236+
237+ /**
238+ * Constructs a new instance of an unordered attribute with a single value.
239+ *
240+ * @param id The attribute's id. It cannot be null.
241+ * @param value The attribute's value. If null, a null
242+ * value is added to the attribute.
243+ */
244+ public BasicAttribute(String id, Object value) {
245+ this(id, value, false);
246+ }
247+
248+ /**
249+ * Constructs a new instance of a possibly ordered attribute with no value.
250+ *
251+ * @param id The attribute's id. It cannot be null.
252+ * @param ordered true means the attribute's values will be ordered;
253+ * false otherwise.
254+ */
255+ public BasicAttribute(String id, boolean ordered) {
256+ attrID = id;
257+ values = new Vector();
258+ this.ordered = ordered;
259+ }
260+
261+ /**
262+ * Constructs a new instance of a possibly ordered attribute with a
263+ * single value.
264+ *
265+ * @param id The attribute's id. It cannot be null.
266+ * @param value The attribute's value. If null, a null
267+ * value is added to the attribute.
268+ * @param ordered true means the attribute's values will be ordered;
269+ * false otherwise.
270+ */
271+ public BasicAttribute(String id, Object value, boolean ordered) {
272+ this(id, ordered);
273+ values.addElement(value);
274+ }
275+
276+ /**
277+ * Retrieves an enumeration of this attribute's values.
278+ *<p>
279+ * By default, the values returned are those passed to the
280+ * constructor and/or manipulated using the add/replace/remove methods.
281+ * A subclass may override this to retrieve the values dynamically
282+ * from the directory.
283+ */
284+ public NamingEnumeration<?> getAll() throws NamingException {
285+ return new ValuesEnumImpl();
286+ }
287+
288+ /**
289+ * Retrieves one of this attribute's values.
290+ *<p>
291+ * By default, the value returned is one of those passed to the
292+ * constructor and/or manipulated using the add/replace/remove methods.
293+ * A subclass may override this to retrieve the value dynamically
294+ * from the directory.
295+ */
296+ public Object get() throws NamingException {
297+ if (values.size() == 0) {
298+ throw new
299+ NoSuchElementException("Attribute " + getID() + " has no value");
300+ } else {
301+ return values.elementAt(0);
302+ }
303+ }
304+
305+ public int size() {
306+ return values.size();
307+ }
308+
309+ public String getID() {
310+ return attrID;
311+ }
312+
313+ /**
314+ * Determines whether a value is in this attribute.
315+ *<p>
316+ * By default,
317+ * <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>
318+ * with this attribute's values except when <tt>attrVal</tt> is an array.
319+ * For an array, each element of the array is checked using
320+ * <tt>Object.equals()</tt>.
321+ * A subclass may use schema information to determine equality.
322+ */
323+ public boolean contains(Object attrVal) {
324+ return (find(attrVal) >= 0);
325+ }
326+
327+ // For finding first element that has a null in JDK1.1 Vector.
328+ // In the Java 2 platform, can just replace this with Vector.indexOf(target);
329+ private int find(Object target) {
330+ Class cl;
331+ if (target == null) {
332+ int ct = values.size();
333+ for (int i = 0 ; i < ct ; i++) {
334+ if (values.elementAt(i) == null)
335+ return i;
336+ }
337+ } else if ((cl=target.getClass()).isArray()) {
338+ int ct = values.size();
339+ Object it;
340+ for (int i = 0 ; i < ct ; i++) {
341+ it = values.elementAt(i);
342+ if (it != null && cl == it.getClass()
343+ && arrayEquals(target, it))
344+ return i;
345+ }
346+ } else {
347+ return values.indexOf(target, 0);
348+ }
349+ return -1; // not found
350+ }
351+
352+ /**
353+ * Determines whether two attribute values are equal.
354+ * Use arrayEquals for arrays and <tt>Object.equals()</tt> otherwise.
355+ */
356+ private static boolean valueEquals(Object obj1, Object obj2) {
357+ if (obj1 == obj2) {
358+ return true; // object references are equal
359+ }
360+ if (obj1 == null) {
361+ return false; // obj2 was not false
362+ }
363+ if (obj1.getClass().isArray() &&
364+ obj2.getClass().isArray()) {
365+ return arrayEquals(obj1, obj2);
366+ }
367+ return (obj1.equals(obj2));
368+ }
369+
370+ /**
371+ * Determines whether two arrays are equal by comparing each of their
372+ * elements using <tt>Object.equals()</tt>.
373+ */
374+ private static boolean arrayEquals(Object a1, Object a2) {
375+ int len;
376+ if ((len = Array.getLength(a1)) != Array.getLength(a2))
377+ return false;
378+
379+ for (int j = 0; j < len; j++) {
380+ Object i1 = Array.get(a1, j);
381+ Object i2 = Array.get(a2, j);
382+ if (i1 == null || i2 == null) {
383+ if (i1 != i2)
384+ return false;
385+ } else if (!i1.equals(i2)) {
386+ return false;
387+ }
388+ }
389+ return true;
390+ }
391+
392+ /**
393+ * Adds a new value to this attribute.
394+ *<p>
395+ * By default, <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>
396+ * with this attribute's values except when <tt>attrVal</tt> is an array.
397+ * For an array, each element of the array is checked using
398+ * <tt>Object.equals()</tt>.
399+ * A subclass may use schema information to determine equality.
400+ */
401+ public boolean add(Object attrVal) {
402+ if (isOrdered() || (find(attrVal) < 0)) {
403+ values.addElement(attrVal);
404+ return true;
405+ } else {
406+ return false;
407+ }
408+ }
409+
410+ /**
411+ * Removes a specified value from this attribute.
412+ *<p>
413+ * By default, <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>
414+ * with this attribute's values except when <tt>attrVal</tt> is an array.
415+ * For an array, each element of the array is checked using
416+ * <tt>Object.equals()</tt>.
417+ * A subclass may use schema information to determine equality.
418+ */
419+ public boolean remove(Object attrval) {
420+ // For the Java 2 platform, can just use "return removeElement(attrval);"
421+ // Need to do the following to handle null case
422+
423+ int i = find(attrval);
424+ if (i >= 0) {
425+ values.removeElementAt(i);
426+ return true;
427+ }
428+ return false;
429+ }
430+
431+ public void clear() {
432+ values.setSize(0);
433+ }
434+
435+// ---- ordering methods
436+
437+ public boolean isOrdered() {
438+ return ordered;
439+ }
440+
441+ public Object get(int ix) throws NamingException {
442+ return values.elementAt(ix);
443+ }
444+
445+ public Object remove(int ix) {
446+ Object answer = values.elementAt(ix);
447+ values.removeElementAt(ix);
448+ return answer;
449+ }
450+
451+ public void add(int ix, Object attrVal) {
452+ if (!isOrdered() && contains(attrVal)) {
453+ throw new IllegalStateException(
454+ "Cannot add duplicate to unordered attribute");
455+ }
456+ values.insertElementAt(attrVal, ix);
457+ }
458+
459+ public Object set(int ix, Object attrVal) {
460+ if (!isOrdered() && contains(attrVal)) {
461+ throw new IllegalStateException(
462+ "Cannot add duplicate to unordered attribute");
463+ }
464+
465+ Object answer = values.elementAt(ix);
466+ values.setElementAt(attrVal, ix);
467+ return answer;
468+ }
469+
470+// ----------------- Schema methods
471+
472+ /**
473+ * Retrieves the syntax definition associated with this attribute.
474+ *<p>
475+ * This method by default throws OperationNotSupportedException. A subclass
476+ * should override this method if it supports schema.
477+ */
478+ public DirContext getAttributeSyntaxDefinition() throws NamingException {
479+ throw new OperationNotSupportedException("attribute syntax");
480+ }
481+
482+ /**
483+ * Retrieves this attribute's schema definition.
484+ *<p>
485+ * This method by default throws OperationNotSupportedException. A subclass
486+ * should override this method if it supports schema.
487+ */
488+ public DirContext getAttributeDefinition() throws NamingException {
489+ throw new OperationNotSupportedException("attribute definition");
490+ }
491+
492+
493+// ---- serialization methods
494+
495+ /**
496+ * Overridden to avoid exposing implementation details
497+ * @serialData Default field (the attribute ID -- a String),
498+ * followed by the number of values (an int), and the
499+ * individual values.
500+ */
501+ private void writeObject(java.io.ObjectOutputStream s)
502+ throws java.io.IOException {
503+ s.defaultWriteObject(); // write out the attrID
504+ s.writeInt(values.size());
505+ for (int i = 0; i < values.size(); i++) {
506+ s.writeObject(values.elementAt(i));
507+ }
508+ }
509+
510+ /**
511+ * Overridden to avoid exposing implementation details.
512+ */
513+ private void readObject(java.io.ObjectInputStream s)
514+ throws java.io.IOException, ClassNotFoundException {
515+ s.defaultReadObject(); // read in the attrID
516+ int n = s.readInt(); // number of values
517+ values = new Vector(n);
518+ while (--n >= 0) {
519+ values.addElement(s.readObject());
520+ }
521+ }
522+
523+
524+ class ValuesEnumImpl implements NamingEnumeration<Object> {
525+ Enumeration list;
526+
527+ ValuesEnumImpl() {
528+ list = values.elements();
529+ }
530+
531+ public boolean hasMoreElements() {
532+ return list.hasMoreElements();
533+ }
534+
535+ public Object nextElement() {
536+ return(list.nextElement());
537+ }
538+
539+ public Object next() throws NamingException {
540+ return list.nextElement();
541+ }
542+
543+ public boolean hasMore() throws NamingException {
544+ return list.hasMoreElements();
545+ }
546+
547+ public void close() throws NamingException {
548+ list = null;
549+ }
550+ }
551+
552+ /**
553+ * Use serialVersionUID from JNDI 1.1.1 for interoperability.
554+ */
555+ private static final long serialVersionUID = 6743528196119291326L;
556+}