Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.naming/share/classes/javax/naming/ldap/LdapName.java
41159 views
1
/*
2
* Copyright (c) 2003, 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.ldap;
27
28
import javax.naming.Name;
29
import javax.naming.InvalidNameException;
30
31
import java.util.Enumeration;
32
import java.util.Collection;
33
import java.util.ArrayList;
34
import java.util.List;
35
import java.util.Iterator;
36
import java.util.ListIterator;
37
import java.util.Collections;
38
39
import java.io.ObjectOutputStream;
40
import java.io.ObjectInputStream;
41
import java.io.IOException;
42
43
/**
44
* This class represents a distinguished name as specified by
45
* <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>.
46
* A distinguished name, or DN, is composed of an ordered list of
47
* components called <em>relative distinguished name</em>s, or RDNs.
48
* Details of a DN's syntax are described in RFC 2253.
49
*<p>
50
* This class resolves a few ambiguities found in RFC 2253
51
* as follows:
52
* <ul>
53
* <li> RFC 2253 leaves the term "whitespace" undefined. The
54
* ASCII space character 0x20 (" ") is used in its place.
55
* <li> Whitespace is allowed on either side of ',', ';', '=', and '+'.
56
* Such whitespace is accepted but not generated by this code,
57
* and is ignored when comparing names.
58
* <li> AttributeValue strings containing '=' or non-leading '#'
59
* characters (unescaped) are accepted.
60
* </ul>
61
*<p>
62
* String names passed to {@code LdapName} or returned by it
63
* use the full Unicode character set. They may also contain
64
* characters encoded into UTF-8 with each octet represented by a
65
* three-character substring such as "\\B4".
66
* They may not, however, contain characters encoded into UTF-8 with
67
* each octet represented by a single character in the string: the
68
* meaning would be ambiguous.
69
*<p>
70
* {@code LdapName} will properly parse all valid names, but
71
* does not attempt to detect all possible violations when parsing
72
* invalid names. It is "generous" in accepting invalid names.
73
* The "validity" of a name is determined ultimately when it
74
* is supplied to an LDAP server, which may accept or
75
* reject the name based on factors such as its schema information
76
* and interoperability considerations.
77
*<p>
78
* When names are tested for equality, attribute types, both binary
79
* and string values, are case-insensitive.
80
* String values with different but equivalent usage of quoting,
81
* escaping, or UTF8-hex-encoding are considered equal. The order of
82
* components in multi-valued RDNs (such as "ou=Sales+cn=Bob") is not
83
* significant.
84
* <p>
85
* The components of a LDAP name, that is, RDNs, are numbered. The
86
* indexes of a LDAP name with n RDNs range from 0 to n-1.
87
* This range may be written as [0,n).
88
* The right most RDN is at index 0, and the left most RDN is at
89
* index n-1. For example, the distinguished name:
90
* "CN=Steve Kille, O=Isode Limited, C=GB" is numbered in the following
91
* sequence ranging from 0 to 2: {C=GB, O=Isode Limited, CN=Steve Kille}. An
92
* empty LDAP name is represented by an empty RDN list.
93
*<p>
94
* Concurrent multithreaded read-only access of an instance of
95
* {@code LdapName} need not be synchronized.
96
*<p>
97
* Unless otherwise noted, the behavior of passing a null argument
98
* to a constructor or method in this class will cause a
99
* NullPointerException to be thrown.
100
*
101
* @author Scott Seligman
102
* @since 1.5
103
*/
104
105
public class LdapName implements Name {
106
107
private transient List<Rdn> rdns; // parsed name components
108
private transient String unparsed; // if non-null, the DN in unparsed form
109
110
@java.io.Serial
111
private static final long serialVersionUID = -1595520034788997356L;
112
113
/**
114
* Constructs an LDAP name from the given distinguished name.
115
*
116
* @param name This is a non-null distinguished name formatted
117
* according to the rules defined in
118
* <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>.
119
*
120
* @throws InvalidNameException if a syntax violation is detected.
121
* @see Rdn#escapeValue(Object value)
122
*/
123
public LdapName(String name) throws InvalidNameException {
124
unparsed = name;
125
parse();
126
}
127
128
/**
129
* Constructs an LDAP name given its parsed RDN components.
130
* <p>
131
* The indexing of RDNs in the list follows the numbering of
132
* RDNs described in the class description.
133
*
134
* @param rdns The non-null list of {@code Rdn}s forming this LDAP name.
135
*/
136
public LdapName(List<Rdn> rdns) {
137
138
// if (rdns instanceof ArrayList<Rdn>) {
139
// this.rdns = rdns.clone();
140
// } else if (rdns instanceof List<Rdn>) {
141
// this.rdns = new ArrayList<Rdn>(rdns);
142
// } else {
143
// throw IllegalArgumentException(
144
// "Invalid entries, list entries must be of type Rdn");
145
// }
146
147
this.rdns = new ArrayList<>(rdns.size());
148
for (int i = 0; i < rdns.size(); i++) {
149
Object obj = rdns.get(i);
150
if (!(obj instanceof Rdn)) {
151
throw new IllegalArgumentException("Entry:" + obj +
152
" not a valid type;list entries must be of type Rdn");
153
}
154
this.rdns.add((Rdn)obj);
155
}
156
}
157
158
/*
159
* Constructs an LDAP name given its parsed components (the elements
160
* of "rdns" in the range [beg,end)) and, optionally
161
* (if "name" is not null), the unparsed DN.
162
*
163
*/
164
private LdapName(String name, List<Rdn> rdns, int beg, int end) {
165
unparsed = name;
166
// this.rdns = rdns.subList(beg, end);
167
168
List<Rdn> sList = rdns.subList(beg, end);
169
this.rdns = new ArrayList<>(sList);
170
}
171
172
/**
173
* Retrieves the number of components in this LDAP name.
174
* @return The non-negative number of components in this LDAP name.
175
*/
176
public int size() {
177
return rdns.size();
178
}
179
180
/**
181
* Determines whether this LDAP name is empty.
182
* An empty name is one with zero components.
183
* @return true if this LDAP name is empty, false otherwise.
184
*/
185
public boolean isEmpty() {
186
return rdns.isEmpty();
187
}
188
189
/**
190
* Retrieves the components of this name as an enumeration
191
* of strings. The effect of updates to this name on this enumeration
192
* is undefined. If the name has zero components, an empty (non-null)
193
* enumeration is returned.
194
* The order of the components returned by the enumeration is same as
195
* the order in which the components are numbered as described in the
196
* class description.
197
*
198
* @return A non-null enumeration of the components of this LDAP name.
199
* Each element of the enumeration is of class String.
200
*/
201
public Enumeration<String> getAll() {
202
final Iterator<Rdn> iter = rdns.iterator();
203
204
return new Enumeration<String>() {
205
public boolean hasMoreElements() {
206
return iter.hasNext();
207
}
208
public String nextElement() {
209
return iter.next().toString();
210
}
211
};
212
}
213
214
/**
215
* Retrieves a component of this LDAP name as a string.
216
* @param posn The 0-based index of the component to retrieve.
217
* Must be in the range [0,size()).
218
* @return The non-null component at index posn.
219
* @exception IndexOutOfBoundsException if posn is outside the
220
* specified range.
221
*/
222
public String get(int posn) {
223
return rdns.get(posn).toString();
224
}
225
226
/**
227
* Retrieves an RDN of this LDAP name as an Rdn.
228
* @param posn The 0-based index of the RDN to retrieve.
229
* Must be in the range [0,size()).
230
* @return The non-null RDN at index posn.
231
* @exception IndexOutOfBoundsException if posn is outside the
232
* specified range.
233
*/
234
public Rdn getRdn(int posn) {
235
return rdns.get(posn);
236
}
237
238
/**
239
* Creates a name whose components consist of a prefix of the
240
* components of this LDAP name.
241
* Subsequent changes to this name will not affect the name
242
* that is returned and vice versa.
243
* @param posn The 0-based index of the component at which to stop.
244
* Must be in the range [0,size()].
245
* @return An instance of {@code LdapName} consisting of the
246
* components at indexes in the range [0,posn).
247
* If posn is zero, an empty LDAP name is returned.
248
* @exception IndexOutOfBoundsException
249
* If posn is outside the specified range.
250
*/
251
public Name getPrefix(int posn) {
252
try {
253
return new LdapName(null, rdns, 0, posn);
254
} catch (IllegalArgumentException e) {
255
throw new IndexOutOfBoundsException(
256
"Posn: " + posn + ", Size: "+ rdns.size());
257
}
258
}
259
260
/**
261
* Creates a name whose components consist of a suffix of the
262
* components in this LDAP name.
263
* Subsequent changes to this name do not affect the name that is
264
* returned and vice versa.
265
*
266
* @param posn The 0-based index of the component at which to start.
267
* Must be in the range [0,size()].
268
* @return An instance of {@code LdapName} consisting of the
269
* components at indexes in the range [posn,size()).
270
* If posn is equal to size(), an empty LDAP name is
271
* returned.
272
* @exception IndexOutOfBoundsException
273
* If posn is outside the specified range.
274
*/
275
public Name getSuffix(int posn) {
276
try {
277
return new LdapName(null, rdns, posn, rdns.size());
278
} catch (IllegalArgumentException e) {
279
throw new IndexOutOfBoundsException(
280
"Posn: " + posn + ", Size: "+ rdns.size());
281
}
282
}
283
284
/**
285
* Determines whether this LDAP name starts with a specified LDAP name
286
* prefix.
287
* A name {@code n} is a prefix if it is equal to
288
* {@code getPrefix(n.size())}--in other words this LDAP
289
* name starts with 'n'. If n is null or not a RFC2253 formatted name
290
* as described in the class description, false is returned.
291
*
292
* @param n The LDAP name to check.
293
* @return true if {@code n} is a prefix of this LDAP name,
294
* false otherwise.
295
* @see #getPrefix(int posn)
296
*/
297
public boolean startsWith(Name n) {
298
if (n == null) {
299
return false;
300
}
301
int len1 = rdns.size();
302
int len2 = n.size();
303
return (len1 >= len2 &&
304
matches(0, len2, n));
305
}
306
307
/**
308
* Determines whether the specified RDN sequence forms a prefix of this
309
* LDAP name. Returns true if this LdapName is at least as long as rdns,
310
* and for every position p in the range [0, rdns.size()) the component
311
* getRdn(p) matches rdns.get(p). Returns false otherwise. If rdns is
312
* null, false is returned.
313
*
314
* @param rdns The sequence of {@code Rdn}s to check.
315
* @return true if {@code rdns} form a prefix of this LDAP name,
316
* false otherwise.
317
*/
318
public boolean startsWith(List<Rdn> rdns) {
319
if (rdns == null) {
320
return false;
321
}
322
int len1 = this.rdns.size();
323
int len2 = rdns.size();
324
return (len1 >= len2 &&
325
doesListMatch(0, len2, rdns));
326
}
327
328
/**
329
* Determines whether this LDAP name ends with a specified
330
* LDAP name suffix.
331
* A name {@code n} is a suffix if it is equal to
332
* {@code getSuffix(size()-n.size())}--in other words this LDAP
333
* name ends with 'n'. If n is null or not a RFC2253 formatted name
334
* as described in the class description, false is returned.
335
*
336
* @param n The LDAP name to check.
337
* @return true if {@code n} is a suffix of this name, false otherwise.
338
* @see #getSuffix(int posn)
339
*/
340
public boolean endsWith(Name n) {
341
if (n == null) {
342
return false;
343
}
344
int len1 = rdns.size();
345
int len2 = n.size();
346
return (len1 >= len2 &&
347
matches(len1 - len2, len1, n));
348
}
349
350
/**
351
* Determines whether the specified RDN sequence forms a suffix of this
352
* LDAP name. Returns true if this LdapName is at least as long as rdns,
353
* and for every position p in the range [size() - rdns.size(), size())
354
* the component getRdn(p) matches rdns.get(p). Returns false otherwise.
355
* If rdns is null, false is returned.
356
*
357
* @param rdns The sequence of {@code Rdn}s to check.
358
* @return true if {@code rdns} form a suffix of this LDAP name,
359
* false otherwise.
360
*/
361
public boolean endsWith(List<Rdn> rdns) {
362
if (rdns == null) {
363
return false;
364
}
365
int len1 = this.rdns.size();
366
int len2 = rdns.size();
367
return (len1 >= len2 &&
368
doesListMatch(len1 - len2, len1, rdns));
369
}
370
371
private boolean doesListMatch(int beg, int end, List<Rdn> rdns) {
372
for (int i = beg; i < end; i++) {
373
if (!this.rdns.get(i).equals(rdns.get(i - beg))) {
374
return false;
375
}
376
}
377
return true;
378
}
379
380
/*
381
* Helper method for startsWith() and endsWith().
382
* Returns true if components [beg,end) match the components of "n".
383
* If "n" is not an LdapName, each of its components is parsed as
384
* the string form of an RDN.
385
* The following must hold: end - beg == n.size().
386
*/
387
private boolean matches(int beg, int end, Name n) {
388
if (n instanceof LdapName) {
389
LdapName ln = (LdapName) n;
390
return doesListMatch(beg, end, ln.rdns);
391
} else {
392
for (int i = beg; i < end; i++) {
393
Rdn rdn;
394
String rdnString = n.get(i - beg);
395
try {
396
rdn = (new Rfc2253Parser(rdnString)).parseRdn();
397
} catch (InvalidNameException e) {
398
return false;
399
}
400
if (!rdn.equals(rdns.get(i))) {
401
return false;
402
}
403
}
404
}
405
return true;
406
}
407
408
/**
409
* Adds the components of a name -- in order -- to the end of this name.
410
*
411
* @param suffix The non-null components to add.
412
* @return The updated name (not a new instance).
413
*
414
* @throws InvalidNameException if {@code suffix} is not a valid LDAP
415
* name, or if the addition of the components would violate the
416
* syntax rules of this LDAP name.
417
*/
418
public Name addAll(Name suffix) throws InvalidNameException {
419
return addAll(size(), suffix);
420
}
421
422
423
/**
424
* Adds the RDNs of a name -- in order -- to the end of this name.
425
*
426
* @param suffixRdns The non-null suffix {@code Rdn}s to add.
427
* @return The updated name (not a new instance).
428
*/
429
public Name addAll(List<Rdn> suffixRdns) {
430
return addAll(size(), suffixRdns);
431
}
432
433
/**
434
* Adds the components of a name -- in order -- at a specified position
435
* within this name. Components of this LDAP name at or after the
436
* index (if any) of the first new component are shifted up
437
* (away from index 0) to accommodate the new components.
438
*
439
* @param suffix The non-null components to add.
440
* @param posn The index at which to add the new component.
441
* Must be in the range [0,size()].
442
*
443
* @return The updated name (not a new instance).
444
*
445
* @throws InvalidNameException if {@code suffix} is not a valid LDAP
446
* name, or if the addition of the components would violate the
447
* syntax rules of this LDAP name.
448
* @throws IndexOutOfBoundsException
449
* If posn is outside the specified range.
450
*/
451
public Name addAll(int posn, Name suffix)
452
throws InvalidNameException {
453
unparsed = null; // no longer valid
454
if (suffix instanceof LdapName) {
455
LdapName s = (LdapName) suffix;
456
rdns.addAll(posn, s.rdns);
457
} else {
458
Enumeration<String> comps = suffix.getAll();
459
while (comps.hasMoreElements()) {
460
rdns.add(posn++,
461
(new Rfc2253Parser(comps.nextElement()).
462
parseRdn()));
463
}
464
}
465
return this;
466
}
467
468
/**
469
* Adds the RDNs of a name -- in order -- at a specified position
470
* within this name. RDNs of this LDAP name at or after the
471
* index (if any) of the first new RDN are shifted up (away from index 0) to
472
* accommodate the new RDNs.
473
*
474
* @param suffixRdns The non-null suffix {@code Rdn}s to add.
475
* @param posn The index at which to add the suffix RDNs.
476
* Must be in the range [0,size()].
477
*
478
* @return The updated name (not a new instance).
479
* @throws IndexOutOfBoundsException
480
* If posn is outside the specified range.
481
*/
482
public Name addAll(int posn, List<Rdn> suffixRdns) {
483
unparsed = null;
484
for (int i = 0; i < suffixRdns.size(); i++) {
485
Object obj = suffixRdns.get(i);
486
if (!(obj instanceof Rdn)) {
487
throw new IllegalArgumentException("Entry:" + obj +
488
" not a valid type;suffix list entries must be of type Rdn");
489
}
490
rdns.add(i + posn, (Rdn)obj);
491
}
492
return this;
493
}
494
495
/**
496
* Adds a single component to the end of this LDAP name.
497
*
498
* @param comp The non-null component to add.
499
* @return The updated LdapName, not a new instance.
500
* Cannot be null.
501
* @exception InvalidNameException If adding comp at end of the name
502
* would violate the name's syntax.
503
*/
504
public Name add(String comp) throws InvalidNameException {
505
return add(size(), comp);
506
}
507
508
/**
509
* Adds a single RDN to the end of this LDAP name.
510
*
511
* @param comp The non-null RDN to add.
512
*
513
* @return The updated LdapName, not a new instance.
514
* Cannot be null.
515
*/
516
public Name add(Rdn comp) {
517
return add(size(), comp);
518
}
519
520
/**
521
* Adds a single component at a specified position within this
522
* LDAP name.
523
* Components of this LDAP name at or after the index (if any) of the new
524
* component are shifted up by one (away from index 0) to accommodate
525
* the new component.
526
*
527
* @param comp The non-null component to add.
528
* @param posn The index at which to add the new component.
529
* Must be in the range [0,size()].
530
* @return The updated LdapName, not a new instance.
531
* Cannot be null.
532
* @exception IndexOutOfBoundsException
533
* If posn is outside the specified range.
534
* @exception InvalidNameException If adding comp at the
535
* specified position would violate the name's syntax.
536
*/
537
public Name add(int posn, String comp) throws InvalidNameException {
538
Rdn rdn = (new Rfc2253Parser(comp)).parseRdn();
539
rdns.add(posn, rdn);
540
unparsed = null; // no longer valid
541
return this;
542
}
543
544
/**
545
* Adds a single RDN at a specified position within this
546
* LDAP name.
547
* RDNs of this LDAP name at or after the index (if any) of the new
548
* RDN are shifted up by one (away from index 0) to accommodate
549
* the new RDN.
550
*
551
* @param comp The non-null RDN to add.
552
* @param posn The index at which to add the new RDN.
553
* Must be in the range [0,size()].
554
* @return The updated LdapName, not a new instance.
555
* Cannot be null.
556
* @exception IndexOutOfBoundsException
557
* If posn is outside the specified range.
558
*/
559
public Name add(int posn, Rdn comp) {
560
if (comp == null) {
561
throw new NullPointerException("Cannot set comp to null");
562
}
563
rdns.add(posn, comp);
564
unparsed = null; // no longer valid
565
return this;
566
}
567
568
/**
569
* Removes a component from this LDAP name.
570
* The component of this name at the specified position is removed.
571
* Components with indexes greater than this position (if any)
572
* are shifted down (toward index 0) by one.
573
*
574
* @param posn The index of the component to remove.
575
* Must be in the range [0,size()).
576
* @return The component removed (a String).
577
*
578
* @throws IndexOutOfBoundsException
579
* if posn is outside the specified range.
580
* @throws InvalidNameException if deleting the component
581
* would violate the syntax rules of the name.
582
*/
583
public Object remove(int posn) throws InvalidNameException {
584
unparsed = null; // no longer valid
585
return rdns.remove(posn).toString();
586
}
587
588
/**
589
* Retrieves the list of relative distinguished names.
590
* The contents of the list are unmodifiable.
591
* The indexing of RDNs in the returned list follows the numbering of
592
* RDNs as described in the class description.
593
* If the name has zero components, an empty list is returned.
594
*
595
* @return The name as a list of RDNs which are instances of
596
* the class {@link Rdn Rdn}.
597
*/
598
public List<Rdn> getRdns() {
599
return Collections.unmodifiableList(rdns);
600
}
601
602
/**
603
* Generates a new copy of this name.
604
* Subsequent changes to the components of this name will not
605
* affect the new copy, and vice versa.
606
*
607
* @return A copy of the this LDAP name.
608
*/
609
public Object clone() {
610
return new LdapName(unparsed, rdns, 0, rdns.size());
611
}
612
613
/**
614
* Returns a string representation of this LDAP name in a format
615
* defined by <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>
616
* and described in the class description. If the name has zero
617
* components an empty string is returned.
618
*
619
* @return The string representation of the LdapName.
620
*/
621
public String toString() {
622
if (unparsed != null) {
623
return unparsed;
624
}
625
StringBuilder builder = new StringBuilder();
626
int size = rdns.size();
627
if ((size - 1) >= 0) {
628
builder.append(rdns.get(size - 1));
629
}
630
for (int next = size - 2; next >= 0; next--) {
631
builder.append(',');
632
builder.append(rdns.get(next));
633
}
634
unparsed = builder.toString();
635
return unparsed;
636
}
637
638
/**
639
* Determines whether two LDAP names are equal.
640
* If obj is null or not an LDAP name, false is returned.
641
* <p>
642
* Two LDAP names are equal if each RDN in one is equal
643
* to the corresponding RDN in the other. This implies
644
* both have the same number of RDNs, and each RDN's
645
* equals() test against the corresponding RDN in the other
646
* name returns true. See {@link Rdn#equals(Object obj)}
647
* for a definition of RDN equality.
648
*
649
* @param obj The possibly null object to compare against.
650
* @return true if obj is equal to this LDAP name,
651
* false otherwise.
652
* @see #hashCode
653
*/
654
public boolean equals(Object obj) {
655
// check possible shortcuts
656
if (obj == this) {
657
return true;
658
}
659
if (!(obj instanceof LdapName)) {
660
return false;
661
}
662
LdapName that = (LdapName) obj;
663
if (rdns.size() != that.rdns.size()) {
664
return false;
665
}
666
if (unparsed != null && unparsed.equalsIgnoreCase(
667
that.unparsed)) {
668
return true;
669
}
670
// Compare RDNs one by one for equality
671
for (int i = 0; i < rdns.size(); i++) {
672
// Compare a single pair of RDNs.
673
Rdn rdn1 = rdns.get(i);
674
Rdn rdn2 = that.rdns.get(i);
675
if (!rdn1.equals(rdn2)) {
676
return false;
677
}
678
}
679
return true;
680
}
681
682
/**
683
* Compares this LdapName with the specified Object for order.
684
* Returns a negative integer, zero, or a positive integer as this
685
* Name is less than, equal to, or greater than the given Object.
686
* <p>
687
* If obj is null or not an instance of LdapName, ClassCastException
688
* is thrown.
689
* <p>
690
* Ordering of LDAP names follows the lexicographical rules for
691
* string comparison, with the extension that this applies to all
692
* the RDNs in the LDAP name. All the RDNs are lined up in their
693
* specified order and compared lexicographically.
694
* See {@link Rdn#compareTo(Object obj) Rdn.compareTo(Object obj)}
695
* for RDN comparison rules.
696
* <p>
697
* If this LDAP name is lexicographically lesser than obj,
698
* a negative number is returned.
699
* If this LDAP name is lexicographically greater than obj,
700
* a positive number is returned.
701
* @param obj The non-null LdapName instance to compare against.
702
*
703
* @return A negative integer, zero, or a positive integer as this Name
704
* is less than, equal to, or greater than the given obj.
705
* @exception ClassCastException if obj is null or not a LdapName.
706
*/
707
public int compareTo(Object obj) {
708
709
if (!(obj instanceof LdapName)) {
710
throw new ClassCastException("The obj is not a LdapName");
711
}
712
713
// check possible shortcuts
714
if (obj == this) {
715
return 0;
716
}
717
LdapName that = (LdapName) obj;
718
719
if (unparsed != null && unparsed.equalsIgnoreCase(
720
that.unparsed)) {
721
return 0;
722
}
723
724
// Compare RDNs one by one, lexicographically.
725
int minSize = Math.min(rdns.size(), that.rdns.size());
726
for (int i = 0; i < minSize; i++) {
727
// Compare a single pair of RDNs.
728
Rdn rdn1 = rdns.get(i);
729
Rdn rdn2 = that.rdns.get(i);
730
731
int diff = rdn1.compareTo(rdn2);
732
if (diff != 0) {
733
return diff;
734
}
735
}
736
return (rdns.size() - that.rdns.size()); // longer DN wins
737
}
738
739
/**
740
* Computes the hash code of this LDAP name.
741
* The hash code is the sum of the hash codes of individual RDNs
742
* of this name.
743
*
744
* @return An int representing the hash code of this name.
745
* @see #equals
746
*/
747
public int hashCode() {
748
// Sum up the hash codes of the components.
749
int hash = 0;
750
751
// For each RDN...
752
for (int i = 0; i < rdns.size(); i++) {
753
Rdn rdn = rdns.get(i);
754
hash += rdn.hashCode();
755
}
756
return hash;
757
}
758
759
/**
760
* The writeObject method is called to save the state of the
761
* {@code LdapName} to a stream.
762
*
763
* Serializes only the unparsed DN, for compactness and to avoid
764
* any implementation dependency.
765
*
766
* @serialData The DN {@code String} representation of this LDAP name.
767
*
768
* @param s the {@code ObjectOutputStream} to write to
769
* @throws java.io.IOException if an I/O error occurs
770
*/
771
@java.io.Serial
772
private void writeObject(ObjectOutputStream s)
773
throws java.io.IOException {
774
s.defaultWriteObject();
775
s.writeObject(toString());
776
}
777
778
/**
779
* The readObject method is called to restore the state of
780
* the {@code LdapName} from a stream.
781
*
782
* See {@code writeObject} for a description of the serial form.
783
*
784
* @param s the {@code ObjectInputStream} to read from
785
* @throws java.io.IOException if an I/O error occurs
786
* @throws ClassNotFoundException if the class of a serialized object
787
* could not be found
788
*/
789
@java.io.Serial
790
private void readObject(ObjectInputStream s)
791
throws java.io.IOException, ClassNotFoundException {
792
s.defaultReadObject();
793
unparsed = (String)s.readObject();
794
try {
795
parse();
796
} catch (InvalidNameException e) {
797
// shouldn't happen
798
throw new java.io.StreamCorruptedException(
799
"Invalid name: " + unparsed);
800
}
801
}
802
803
private void parse() throws InvalidNameException {
804
// rdns = (ArrayList<Rdn>) (new RFC2253Parser(unparsed)).getDN();
805
806
rdns = new Rfc2253Parser(unparsed).parseDn();
807
}
808
}
809
810