Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.naming/share/classes/javax/naming/directory/BasicAttribute.java
41159 views
1
/*
2
* Copyright (c) 1999, 2020, 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 {@code Attribute} interface.
39
*<p>
40
* This implementation does not support the schema methods
41
* {@code getAttributeDefinition()} and {@code getAttributeSyntaxDefinition()}.
42
* They simply throw {@code OperationNotSupportedException}.
43
* Subclasses of {@code BasicAttribute} should override these methods if they
44
* support them.
45
*<p>
46
* The {@code BasicAttribute} class by default uses {@code Object.equals()} 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 {@code Object.equals()}.
50
* Subclasses of {@code BasicAttribute} 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 {@code BasicAttribute} class by default returns the values passed to its
54
* constructor and/or manipulated using the add/remove methods.
55
* Subclasses of {@code BasicAttribute} can override {@code get()} and {@code getAll()}
56
* to get the values dynamically from the directory (or implement
57
* the {@code Attribute} interface directly instead of subclassing {@code BasicAttribute}).
58
*<p>
59
* Note that updates to {@code BasicAttribute} (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 {@code DirContext} interface.
63
*<p>
64
* A {@code BasicAttribute} instance is not synchronized against concurrent
65
* multithreaded access. Multiple threads trying to access and modify a
66
* {@code BasicAttribute} 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
@SuppressWarnings("unchecked")
95
public Object clone() {
96
BasicAttribute attr;
97
try {
98
attr = (BasicAttribute)super.clone();
99
} catch (CloneNotSupportedException e) {
100
attr = new BasicAttribute(attrID, ordered);
101
}
102
attr.values = (Vector<Object>)values.clone();
103
return attr;
104
}
105
106
/**
107
* Determines whether obj is equal to this attribute.
108
* Two attributes are equal if their attribute-ids, syntaxes
109
* and values are equal.
110
* If the attribute values are unordered, the order that the values were added
111
* are irrelevant. If the attribute values are ordered, then the
112
* order the values must match.
113
* If obj is null or not an Attribute, false is returned.
114
*<p>
115
* By default {@code Object.equals()} is used when comparing the attribute
116
* id and its values except when a value is an array. For an array,
117
* each element of the array is checked using {@code Object.equals()}.
118
* A subclass may override this to make
119
* use of schema syntax information and matching rules,
120
* which define what it means for two attributes to be equal.
121
* How and whether a subclass makes
122
* use of the schema information is determined by the subclass.
123
* If a subclass overrides {@code equals()}, it should also override
124
* {@code hashCode()}
125
* such that two attributes that are equal have the same hash code.
126
*
127
* @param obj The possibly null object to check.
128
* @return true if obj is equal to this attribute; false otherwise.
129
* @see #hashCode
130
* @see #contains
131
*/
132
public boolean equals(Object obj) {
133
if ((obj != null) && (obj instanceof Attribute)) {
134
Attribute target = (Attribute)obj;
135
136
// Check order first
137
if (isOrdered() != target.isOrdered()) {
138
return false;
139
}
140
int len;
141
if (attrID.equals(target.getID()) &&
142
(len=size()) == target.size()) {
143
try {
144
if (isOrdered()) {
145
// Go through both list of values
146
for (int i = 0; i < len; i++) {
147
if (!valueEquals(get(i), target.get(i))) {
148
return false;
149
}
150
}
151
} else {
152
// order is not relevant; check for existence
153
Enumeration<?> theirs = target.getAll();
154
while (theirs.hasMoreElements()) {
155
if (find(theirs.nextElement()) < 0)
156
return false;
157
}
158
}
159
} catch (NamingException e) {
160
return false;
161
}
162
return true;
163
}
164
}
165
return false;
166
}
167
168
/**
169
* Calculates the hash code of this attribute.
170
*<p>
171
* The hash code is computed by adding the hash code of
172
* the attribute's id and that of all of its values except for
173
* values that are arrays.
174
* For an array, the hash code of each element of the array is summed.
175
* If a subclass overrides {@code hashCode()}, it should override
176
* {@code equals()}
177
* as well so that two attributes that are equal have the same hash code.
178
*
179
* @return an int representing the hash code of this attribute.
180
* @see #equals
181
*/
182
public int hashCode() {
183
int hash = attrID.hashCode();
184
int num = values.size();
185
Object val;
186
for (int i = 0; i < num; i ++) {
187
val = values.elementAt(i);
188
if (val != null) {
189
if (val.getClass().isArray()) {
190
Object it;
191
int len = Array.getLength(val);
192
for (int j = 0 ; j < len ; j++) {
193
it = Array.get(val, j);
194
if (it != null) {
195
hash += it.hashCode();
196
}
197
}
198
} else {
199
hash += val.hashCode();
200
}
201
}
202
}
203
return hash;
204
}
205
206
/**
207
* Generates the string representation of this attribute.
208
* The string consists of the attribute's id and its values.
209
* This string is meant for debugging and not meant to be
210
* interpreted programmatically.
211
* @return The non-null string representation of this attribute.
212
*/
213
public String toString() {
214
StringBuilder answer = new StringBuilder(attrID + ": ");
215
if (values.size() == 0) {
216
answer.append("No values");
217
} else {
218
boolean start = true;
219
for (Enumeration<Object> e = values.elements(); e.hasMoreElements(); ) {
220
if (!start)
221
answer.append(", ");
222
answer.append(e.nextElement());
223
start = false;
224
}
225
}
226
return answer.toString();
227
}
228
229
/**
230
* Constructs a new instance of an unordered attribute with no value.
231
*
232
* @param id The attribute's id. It cannot be null.
233
*/
234
public BasicAttribute(String id) {
235
this(id, false);
236
}
237
238
/**
239
* Constructs a new instance of an unordered attribute with a single value.
240
*
241
* @param id The attribute's id. It cannot be null.
242
* @param value The attribute's value. If null, a null
243
* value is added to the attribute.
244
*/
245
public BasicAttribute(String id, Object value) {
246
this(id, value, false);
247
}
248
249
/**
250
* Constructs a new instance of a possibly ordered attribute with no value.
251
*
252
* @param id The attribute's id. It cannot be null.
253
* @param ordered true means the attribute's values will be ordered;
254
* false otherwise.
255
*/
256
public BasicAttribute(String id, boolean ordered) {
257
attrID = id;
258
values = new Vector<>();
259
this.ordered = ordered;
260
}
261
262
/**
263
* Constructs a new instance of a possibly ordered attribute with a
264
* single value.
265
*
266
* @param id The attribute's id. It cannot be null.
267
* @param value The attribute's value. If null, a null
268
* value is added to the attribute.
269
* @param ordered true means the attribute's values will be ordered;
270
* false otherwise.
271
*/
272
public BasicAttribute(String id, Object value, boolean ordered) {
273
this(id, ordered);
274
values.addElement(value);
275
}
276
277
/**
278
* Retrieves an enumeration of this attribute's values.
279
*<p>
280
* By default, the values returned are those passed to the
281
* constructor and/or manipulated using the add/replace/remove methods.
282
* A subclass may override this to retrieve the values dynamically
283
* from the directory.
284
*/
285
public NamingEnumeration<?> getAll() throws NamingException {
286
return new ValuesEnumImpl();
287
}
288
289
/**
290
* Retrieves one of this attribute's values.
291
*<p>
292
* By default, the value returned is one of those passed to the
293
* constructor and/or manipulated using the add/replace/remove methods.
294
* A subclass may override this to retrieve the value dynamically
295
* from the directory.
296
*/
297
public Object get() throws NamingException {
298
if (values.size() == 0) {
299
throw new
300
NoSuchElementException("Attribute " + getID() + " has no value");
301
} else {
302
return values.elementAt(0);
303
}
304
}
305
306
public int size() {
307
return values.size();
308
}
309
310
public String getID() {
311
return attrID;
312
}
313
314
/**
315
* Determines whether a value is in this attribute.
316
*<p>
317
* By default,
318
* {@code Object.equals()} is used when comparing {@code attrVal}
319
* with this attribute's values except when {@code attrVal} is an array.
320
* For an array, each element of the array is checked using
321
* {@code Object.equals()}.
322
* A subclass may use schema information to determine equality.
323
*/
324
public boolean contains(Object attrVal) {
325
return (find(attrVal) >= 0);
326
}
327
328
// For finding first element that has a null in JDK1.1 Vector.
329
// In the Java 2 platform, can just replace this with Vector.indexOf(target);
330
private int find(Object target) {
331
Class<?> cl;
332
if (target == null) {
333
int ct = values.size();
334
for (int i = 0 ; i < ct ; i++) {
335
if (values.elementAt(i) == null)
336
return i;
337
}
338
} else if ((cl=target.getClass()).isArray()) {
339
int ct = values.size();
340
Object it;
341
for (int i = 0 ; i < ct ; i++) {
342
it = values.elementAt(i);
343
if (it != null && cl == it.getClass()
344
&& arrayEquals(target, it))
345
return i;
346
}
347
} else {
348
return values.indexOf(target, 0);
349
}
350
return -1; // not found
351
}
352
353
/**
354
* Determines whether two attribute values are equal.
355
* Use arrayEquals for arrays and {@code Object.equals()} otherwise.
356
*/
357
private static boolean valueEquals(Object obj1, Object obj2) {
358
if (obj1 == obj2) {
359
return true; // object references are equal
360
}
361
if (obj1 == null) {
362
return false; // obj2 was not false
363
}
364
if (obj1.getClass().isArray() &&
365
obj2.getClass().isArray()) {
366
return arrayEquals(obj1, obj2);
367
}
368
return (obj1.equals(obj2));
369
}
370
371
/**
372
* Determines whether two arrays are equal by comparing each of their
373
* elements using {@code Object.equals()}.
374
*/
375
private static boolean arrayEquals(Object a1, Object a2) {
376
int len;
377
if ((len = Array.getLength(a1)) != Array.getLength(a2))
378
return false;
379
380
for (int j = 0; j < len; j++) {
381
Object i1 = Array.get(a1, j);
382
Object i2 = Array.get(a2, j);
383
if (i1 == null || i2 == null) {
384
if (i1 != i2)
385
return false;
386
} else if (!i1.equals(i2)) {
387
return false;
388
}
389
}
390
return true;
391
}
392
393
/**
394
* Adds a new value to this attribute.
395
*<p>
396
* By default, {@code Object.equals()} is used when comparing {@code attrVal}
397
* with this attribute's values except when {@code attrVal} is an array.
398
* For an array, each element of the array is checked using
399
* {@code Object.equals()}.
400
* A subclass may use schema information to determine equality.
401
*/
402
public boolean add(Object attrVal) {
403
if (isOrdered() || (find(attrVal) < 0)) {
404
values.addElement(attrVal);
405
return true;
406
} else {
407
return false;
408
}
409
}
410
411
/**
412
* Removes a specified value from this attribute.
413
*<p>
414
* By default, {@code Object.equals()} is used when comparing {@code attrVal}
415
* with this attribute's values except when {@code attrVal} is an array.
416
* For an array, each element of the array is checked using
417
* {@code Object.equals()}.
418
* A subclass may use schema information to determine equality.
419
*/
420
public boolean remove(Object attrval) {
421
// For the Java 2 platform, can just use "return removeElement(attrval);"
422
// Need to do the following to handle null case
423
424
int i = find(attrval);
425
if (i >= 0) {
426
values.removeElementAt(i);
427
return true;
428
}
429
return false;
430
}
431
432
public void clear() {
433
values.setSize(0);
434
}
435
436
// ---- ordering methods
437
438
public boolean isOrdered() {
439
return ordered;
440
}
441
442
public Object get(int ix) throws NamingException {
443
return values.elementAt(ix);
444
}
445
446
public Object remove(int ix) {
447
Object answer = values.elementAt(ix);
448
values.removeElementAt(ix);
449
return answer;
450
}
451
452
public void add(int ix, Object attrVal) {
453
if (!isOrdered() && contains(attrVal)) {
454
throw new IllegalStateException(
455
"Cannot add duplicate to unordered attribute");
456
}
457
values.insertElementAt(attrVal, ix);
458
}
459
460
public Object set(int ix, Object attrVal) {
461
if (!isOrdered() && contains(attrVal)) {
462
throw new IllegalStateException(
463
"Cannot add duplicate to unordered attribute");
464
}
465
466
Object answer = values.elementAt(ix);
467
values.setElementAt(attrVal, ix);
468
return answer;
469
}
470
471
// ----------------- Schema methods
472
473
/**
474
* Retrieves the syntax definition associated with this attribute.
475
*<p>
476
* This method by default throws OperationNotSupportedException. A subclass
477
* should override this method if it supports schema.
478
*/
479
public DirContext getAttributeSyntaxDefinition() throws NamingException {
480
throw new OperationNotSupportedException("attribute syntax");
481
}
482
483
/**
484
* Retrieves this attribute's schema definition.
485
*<p>
486
* This method by default throws OperationNotSupportedException. A subclass
487
* should override this method if it supports schema.
488
*/
489
public DirContext getAttributeDefinition() throws NamingException {
490
throw new OperationNotSupportedException("attribute definition");
491
}
492
493
494
// ---- serialization methods
495
496
/**
497
* The writeObject method is called to save the state of the
498
* {@code BasicAttribute} to a stream.
499
*
500
* @serialData Default field (the attribute ID - a {@code String}),
501
* followed by the number of values (an {@code int}), and the
502
* individual values.
503
*
504
* @param s the {@code ObjectOutputStream} to write to
505
* @throws java.io.IOException if an I/O error occurs
506
*/
507
@java.io.Serial
508
private void writeObject(java.io.ObjectOutputStream s)
509
throws java.io.IOException {
510
// Overridden to avoid exposing implementation details
511
s.defaultWriteObject(); // write out the attrID
512
s.writeInt(values.size());
513
for (int i = 0; i < values.size(); i++) {
514
s.writeObject(values.elementAt(i));
515
}
516
}
517
518
/**
519
* The readObject method is called to restore the state of
520
* the {@code BasicAttribute} from a stream.
521
*
522
* See {@code writeObject} for a description of the serial form.
523
*
524
* @param s the {@code ObjectInputStream} to read from
525
* @throws java.io.IOException if an I/O error occurs
526
* @throws ClassNotFoundException if the class of a serialized object
527
* could not be found
528
*/
529
@java.io.Serial
530
private void readObject(java.io.ObjectInputStream s)
531
throws java.io.IOException, ClassNotFoundException {
532
// Overridden to avoid exposing implementation details.
533
s.defaultReadObject(); // read in the attrID
534
int n = s.readInt(); // number of values
535
values = new Vector<>(Math.min(1024, n));
536
while (--n >= 0) {
537
values.addElement(s.readObject());
538
}
539
}
540
541
542
class ValuesEnumImpl implements NamingEnumeration<Object> {
543
Enumeration<Object> list;
544
545
ValuesEnumImpl() {
546
list = values.elements();
547
}
548
549
public boolean hasMoreElements() {
550
return list.hasMoreElements();
551
}
552
553
public Object nextElement() {
554
return(list.nextElement());
555
}
556
557
public Object next() throws NamingException {
558
return list.nextElement();
559
}
560
561
public boolean hasMore() throws NamingException {
562
return list.hasMoreElements();
563
}
564
565
public void close() throws NamingException {
566
list = null;
567
}
568
}
569
570
/**
571
* Use serialVersionUID from JNDI 1.1.1 for interoperability.
572
*/
573
@java.io.Serial
574
private static final long serialVersionUID = 6743528196119291326L;
575
}
576
577