Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/naming/ldap/LdapName.java
38918 views
1
/*
2
* Copyright (c) 2003, 2013, 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</code> 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</code> 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
* <tt>LdapName</tt> 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
private static final long serialVersionUID = -1595520034788997356L;
110
111
/**
112
* Constructs an LDAP name from the given distinguished name.
113
*
114
* @param name This is a non-null distinguished name formatted
115
* according to the rules defined in
116
* <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>.
117
*
118
* @throws InvalidNameException if a syntax violation is detected.
119
* @see Rdn#escapeValue(Object value)
120
*/
121
public LdapName(String name) throws InvalidNameException {
122
unparsed = name;
123
parse();
124
}
125
126
/**
127
* Constructs an LDAP name given its parsed RDN components.
128
* <p>
129
* The indexing of RDNs in the list follows the numbering of
130
* RDNs described in the class description.
131
*
132
* @param rdns The non-null list of <tt>Rdn</tt>s forming this LDAP name.
133
*/
134
public LdapName(List<Rdn> rdns) {
135
136
// if (rdns instanceof ArrayList<Rdn>) {
137
// this.rdns = rdns.clone();
138
// } else if (rdns instanceof List<Rdn>) {
139
// this.rdns = new ArrayList<Rdn>(rdns);
140
// } else {
141
// throw IllegalArgumentException(
142
// "Invalid entries, list entries must be of type Rdn");
143
// }
144
145
this.rdns = new ArrayList<>(rdns.size());
146
for (int i = 0; i < rdns.size(); i++) {
147
Object obj = rdns.get(i);
148
if (!(obj instanceof Rdn)) {
149
throw new IllegalArgumentException("Entry:" + obj +
150
" not a valid type;list entries must be of type Rdn");
151
}
152
this.rdns.add((Rdn)obj);
153
}
154
}
155
156
/*
157
* Constructs an LDAP name given its parsed components (the elements
158
* of "rdns" in the range [beg,end)) and, optionally
159
* (if "name" is not null), the unparsed DN.
160
*
161
*/
162
private LdapName(String name, List<Rdn> rdns, int beg, int end) {
163
unparsed = name;
164
// this.rdns = rdns.subList(beg, end);
165
166
List<Rdn> sList = rdns.subList(beg, end);
167
this.rdns = new ArrayList<>(sList);
168
}
169
170
/**
171
* Retrieves the number of components in this LDAP name.
172
* @return The non-negative number of components in this LDAP name.
173
*/
174
public int size() {
175
return rdns.size();
176
}
177
178
/**
179
* Determines whether this LDAP name is empty.
180
* An empty name is one with zero components.
181
* @return true if this LDAP name is empty, false otherwise.
182
*/
183
public boolean isEmpty() {
184
return rdns.isEmpty();
185
}
186
187
/**
188
* Retrieves the components of this name as an enumeration
189
* of strings. The effect of updates to this name on this enumeration
190
* is undefined. If the name has zero components, an empty (non-null)
191
* enumeration is returned.
192
* The order of the components returned by the enumeration is same as
193
* the order in which the components are numbered as described in the
194
* class description.
195
*
196
* @return A non-null enumeration of the components of this LDAP name.
197
* Each element of the enumeration is of class String.
198
*/
199
public Enumeration<String> getAll() {
200
final Iterator<Rdn> iter = rdns.iterator();
201
202
return new Enumeration<String>() {
203
public boolean hasMoreElements() {
204
return iter.hasNext();
205
}
206
public String nextElement() {
207
return iter.next().toString();
208
}
209
};
210
}
211
212
/**
213
* Retrieves a component of this LDAP name as a string.
214
* @param posn The 0-based index of the component to retrieve.
215
* Must be in the range [0,size()).
216
* @return The non-null component at index posn.
217
* @exception IndexOutOfBoundsException if posn is outside the
218
* specified range.
219
*/
220
public String get(int posn) {
221
return rdns.get(posn).toString();
222
}
223
224
/**
225
* Retrieves an RDN of this LDAP name as an Rdn.
226
* @param posn The 0-based index of the RDN to retrieve.
227
* Must be in the range [0,size()).
228
* @return The non-null RDN at index posn.
229
* @exception IndexOutOfBoundsException if posn is outside the
230
* specified range.
231
*/
232
public Rdn getRdn(int posn) {
233
return rdns.get(posn);
234
}
235
236
/**
237
* Creates a name whose components consist of a prefix of the
238
* components of this LDAP name.
239
* Subsequent changes to this name will not affect the name
240
* that is returned and vice versa.
241
* @param posn The 0-based index of the component at which to stop.
242
* Must be in the range [0,size()].
243
* @return An instance of <tt>LdapName</tt> consisting of the
244
* components at indexes in the range [0,posn).
245
* If posn is zero, an empty LDAP name is returned.
246
* @exception IndexOutOfBoundsException
247
* If posn is outside the specified range.
248
*/
249
public Name getPrefix(int posn) {
250
try {
251
return new LdapName(null, rdns, 0, posn);
252
} catch (IllegalArgumentException e) {
253
throw new IndexOutOfBoundsException(
254
"Posn: " + posn + ", Size: "+ rdns.size());
255
}
256
}
257
258
/**
259
* Creates a name whose components consist of a suffix of the
260
* components in this LDAP name.
261
* Subsequent changes to this name do not affect the name that is
262
* returned and vice versa.
263
*
264
* @param posn The 0-based index of the component at which to start.
265
* Must be in the range [0,size()].
266
* @return An instance of <tt>LdapName</tt> consisting of the
267
* components at indexes in the range [posn,size()).
268
* If posn is equal to size(), an empty LDAP name is
269
* returned.
270
* @exception IndexOutOfBoundsException
271
* If posn is outside the specified range.
272
*/
273
public Name getSuffix(int posn) {
274
try {
275
return new LdapName(null, rdns, posn, rdns.size());
276
} catch (IllegalArgumentException e) {
277
throw new IndexOutOfBoundsException(
278
"Posn: " + posn + ", Size: "+ rdns.size());
279
}
280
}
281
282
/**
283
* Determines whether this LDAP name starts with a specified LDAP name
284
* prefix.
285
* A name <tt>n</tt> is a prefix if it is equal to
286
* <tt>getPrefix(n.size())</tt>--in other words this LDAP
287
* name starts with 'n'. If n is null or not a RFC2253 formatted name
288
* as described in the class description, false is returned.
289
*
290
* @param n The LDAP name to check.
291
* @return true if <tt>n</tt> is a prefix of this LDAP name,
292
* false otherwise.
293
* @see #getPrefix(int posn)
294
*/
295
public boolean startsWith(Name n) {
296
if (n == null) {
297
return false;
298
}
299
int len1 = rdns.size();
300
int len2 = n.size();
301
return (len1 >= len2 &&
302
matches(0, len2, n));
303
}
304
305
/**
306
* Determines whether the specified RDN sequence forms a prefix of this
307
* LDAP name. Returns true if this LdapName is at least as long as rdns,
308
* and for every position p in the range [0, rdns.size()) the component
309
* getRdn(p) matches rdns.get(p). Returns false otherwise. If rdns is
310
* null, false is returned.
311
*
312
* @param rdns The sequence of <tt>Rdn</tt>s to check.
313
* @return true if <tt>rdns</tt> form a prefix of this LDAP name,
314
* false otherwise.
315
*/
316
public boolean startsWith(List<Rdn> rdns) {
317
if (rdns == null) {
318
return false;
319
}
320
int len1 = this.rdns.size();
321
int len2 = rdns.size();
322
return (len1 >= len2 &&
323
doesListMatch(0, len2, rdns));
324
}
325
326
/**
327
* Determines whether this LDAP name ends with a specified
328
* LDAP name suffix.
329
* A name <tt>n</tt> is a suffix if it is equal to
330
* <tt>getSuffix(size()-n.size())</tt>--in other words this LDAP
331
* name ends with 'n'. If n is null or not a RFC2253 formatted name
332
* as described in the class description, false is returned.
333
*
334
* @param n The LDAP name to check.
335
* @return true if <tt>n</tt> is a suffix of this name, false otherwise.
336
* @see #getSuffix(int posn)
337
*/
338
public boolean endsWith(Name n) {
339
if (n == null) {
340
return false;
341
}
342
int len1 = rdns.size();
343
int len2 = n.size();
344
return (len1 >= len2 &&
345
matches(len1 - len2, len1, n));
346
}
347
348
/**
349
* Determines whether the specified RDN sequence forms a suffix of this
350
* LDAP name. Returns true if this LdapName is at least as long as rdns,
351
* and for every position p in the range [size() - rdns.size(), size())
352
* the component getRdn(p) matches rdns.get(p). Returns false otherwise.
353
* If rdns is null, false is returned.
354
*
355
* @param rdns The sequence of <tt>Rdn</tt>s to check.
356
* @return true if <tt>rdns</tt> form a suffix of this LDAP name,
357
* false otherwise.
358
*/
359
public boolean endsWith(List<Rdn> rdns) {
360
if (rdns == null) {
361
return false;
362
}
363
int len1 = this.rdns.size();
364
int len2 = rdns.size();
365
return (len1 >= len2 &&
366
doesListMatch(len1 - len2, len1, rdns));
367
}
368
369
private boolean doesListMatch(int beg, int end, List<Rdn> rdns) {
370
for (int i = beg; i < end; i++) {
371
if (!this.rdns.get(i).equals(rdns.get(i - beg))) {
372
return false;
373
}
374
}
375
return true;
376
}
377
378
/*
379
* Helper method for startsWith() and endsWith().
380
* Returns true if components [beg,end) match the components of "n".
381
* If "n" is not an LdapName, each of its components is parsed as
382
* the string form of an RDN.
383
* The following must hold: end - beg == n.size().
384
*/
385
private boolean matches(int beg, int end, Name n) {
386
if (n instanceof LdapName) {
387
LdapName ln = (LdapName) n;
388
return doesListMatch(beg, end, ln.rdns);
389
} else {
390
for (int i = beg; i < end; i++) {
391
Rdn rdn;
392
String rdnString = n.get(i - beg);
393
try {
394
rdn = (new Rfc2253Parser(rdnString)).parseRdn();
395
} catch (InvalidNameException e) {
396
return false;
397
}
398
if (!rdn.equals(rdns.get(i))) {
399
return false;
400
}
401
}
402
}
403
return true;
404
}
405
406
/**
407
* Adds the components of a name -- in order -- to the end of this name.
408
*
409
* @param suffix The non-null components to add.
410
* @return The updated name (not a new instance).
411
*
412
* @throws InvalidNameException if <tt>suffix</tt> is not a valid LDAP
413
* name, or if the addition of the components would violate the
414
* syntax rules of this LDAP name.
415
*/
416
public Name addAll(Name suffix) throws InvalidNameException {
417
return addAll(size(), suffix);
418
}
419
420
421
/**
422
* Adds the RDNs of a name -- in order -- to the end of this name.
423
*
424
* @param suffixRdns The non-null suffix <tt>Rdn</tt>s to add.
425
* @return The updated name (not a new instance).
426
*/
427
public Name addAll(List<Rdn> suffixRdns) {
428
return addAll(size(), suffixRdns);
429
}
430
431
/**
432
* Adds the components of a name -- in order -- at a specified position
433
* within this name. Components of this LDAP name at or after the
434
* index (if any) of the first new component are shifted up
435
* (away from index 0) to accommodate the new components.
436
*
437
* @param suffix The non-null components to add.
438
* @param posn The index at which to add the new component.
439
* Must be in the range [0,size()].
440
*
441
* @return The updated name (not a new instance).
442
*
443
* @throws InvalidNameException if <tt>suffix</tt> is not a valid LDAP
444
* name, or if the addition of the components would violate the
445
* syntax rules of this LDAP name.
446
* @throws IndexOutOfBoundsException
447
* If posn is outside the specified range.
448
*/
449
public Name addAll(int posn, Name suffix)
450
throws InvalidNameException {
451
unparsed = null; // no longer valid
452
if (suffix instanceof LdapName) {
453
LdapName s = (LdapName) suffix;
454
rdns.addAll(posn, s.rdns);
455
} else {
456
Enumeration<String> comps = suffix.getAll();
457
while (comps.hasMoreElements()) {
458
rdns.add(posn++,
459
(new Rfc2253Parser(comps.nextElement()).
460
parseRdn()));
461
}
462
}
463
return this;
464
}
465
466
/**
467
* Adds the RDNs of a name -- in order -- at a specified position
468
* within this name. RDNs of this LDAP name at or after the
469
* index (if any) of the first new RDN are shifted up (away from index 0) to
470
* accommodate the new RDNs.
471
*
472
* @param suffixRdns The non-null suffix <tt>Rdn</tt>s to add.
473
* @param posn The index at which to add the suffix RDNs.
474
* Must be in the range [0,size()].
475
*
476
* @return The updated name (not a new instance).
477
* @throws IndexOutOfBoundsException
478
* If posn is outside the specified range.
479
*/
480
public Name addAll(int posn, List<Rdn> suffixRdns) {
481
unparsed = null;
482
for (int i = 0; i < suffixRdns.size(); i++) {
483
Object obj = suffixRdns.get(i);
484
if (!(obj instanceof Rdn)) {
485
throw new IllegalArgumentException("Entry:" + obj +
486
" not a valid type;suffix list entries must be of type Rdn");
487
}
488
rdns.add(i + posn, (Rdn)obj);
489
}
490
return this;
491
}
492
493
/**
494
* Adds a single component to the end of this LDAP name.
495
*
496
* @param comp The non-null component to add.
497
* @return The updated LdapName, not a new instance.
498
* Cannot be null.
499
* @exception InvalidNameException If adding comp at end of the name
500
* would violate the name's syntax.
501
*/
502
public Name add(String comp) throws InvalidNameException {
503
return add(size(), comp);
504
}
505
506
/**
507
* Adds a single RDN to the end of this LDAP name.
508
*
509
* @param comp The non-null RDN to add.
510
*
511
* @return The updated LdapName, not a new instance.
512
* Cannot be null.
513
*/
514
public Name add(Rdn comp) {
515
return add(size(), comp);
516
}
517
518
/**
519
* Adds a single component at a specified position within this
520
* LDAP name.
521
* Components of this LDAP name at or after the index (if any) of the new
522
* component are shifted up by one (away from index 0) to accommodate
523
* the new component.
524
*
525
* @param comp The non-null component to add.
526
* @param posn The index at which to add the new component.
527
* Must be in the range [0,size()].
528
* @return The updated LdapName, not a new instance.
529
* Cannot be null.
530
* @exception IndexOutOfBoundsException
531
* If posn is outside the specified range.
532
* @exception InvalidNameException If adding comp at the
533
* specified position would violate the name's syntax.
534
*/
535
public Name add(int posn, String comp) throws InvalidNameException {
536
Rdn rdn = (new Rfc2253Parser(comp)).parseRdn();
537
rdns.add(posn, rdn);
538
unparsed = null; // no longer valid
539
return this;
540
}
541
542
/**
543
* Adds a single RDN at a specified position within this
544
* LDAP name.
545
* RDNs of this LDAP name at or after the index (if any) of the new
546
* RDN are shifted up by one (away from index 0) to accommodate
547
* the new RDN.
548
*
549
* @param comp The non-null RDN to add.
550
* @param posn The index at which to add the new RDN.
551
* Must be in the range [0,size()].
552
* @return The updated LdapName, not a new instance.
553
* Cannot be null.
554
* @exception IndexOutOfBoundsException
555
* If posn is outside the specified range.
556
*/
557
public Name add(int posn, Rdn comp) {
558
if (comp == null) {
559
throw new NullPointerException("Cannot set comp to null");
560
}
561
rdns.add(posn, comp);
562
unparsed = null; // no longer valid
563
return this;
564
}
565
566
/**
567
* Removes a component from this LDAP name.
568
* The component of this name at the specified position is removed.
569
* Components with indexes greater than this position (if any)
570
* are shifted down (toward index 0) by one.
571
*
572
* @param posn The index of the component to remove.
573
* Must be in the range [0,size()).
574
* @return The component removed (a String).
575
*
576
* @throws IndexOutOfBoundsException
577
* if posn is outside the specified range.
578
* @throws InvalidNameException if deleting the component
579
* would violate the syntax rules of the name.
580
*/
581
public Object remove(int posn) throws InvalidNameException {
582
unparsed = null; // no longer valid
583
return rdns.remove(posn).toString();
584
}
585
586
/**
587
* Retrieves the list of relative distinguished names.
588
* The contents of the list are unmodifiable.
589
* The indexing of RDNs in the returned list follows the numbering of
590
* RDNs as described in the class description.
591
* If the name has zero components, an empty list is returned.
592
*
593
* @return The name as a list of RDNs which are instances of
594
* the class {@link Rdn Rdn}.
595
*/
596
public List<Rdn> getRdns() {
597
return Collections.unmodifiableList(rdns);
598
}
599
600
/**
601
* Generates a new copy of this name.
602
* Subsequent changes to the components of this name will not
603
* affect the new copy, and vice versa.
604
*
605
* @return A copy of the this LDAP name.
606
*/
607
public Object clone() {
608
return new LdapName(unparsed, rdns, 0, rdns.size());
609
}
610
611
/**
612
* Returns a string representation of this LDAP name in a format
613
* defined by <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>
614
* and described in the class description. If the name has zero
615
* components an empty string is returned.
616
*
617
* @return The string representation of the LdapName.
618
*/
619
public String toString() {
620
if (unparsed != null) {
621
return unparsed;
622
}
623
StringBuilder builder = new StringBuilder();
624
int size = rdns.size();
625
if ((size - 1) >= 0) {
626
builder.append(rdns.get(size - 1));
627
}
628
for (int next = size - 2; next >= 0; next--) {
629
builder.append(',');
630
builder.append(rdns.get(next));
631
}
632
unparsed = builder.toString();
633
return unparsed;
634
}
635
636
/**
637
* Determines whether two LDAP names are equal.
638
* If obj is null or not an LDAP name, false is returned.
639
* <p>
640
* Two LDAP names are equal if each RDN in one is equal
641
* to the corresponding RDN in the other. This implies
642
* both have the same number of RDNs, and each RDN's
643
* equals() test against the corresponding RDN in the other
644
* name returns true. See {@link Rdn#equals(Object obj)}
645
* for a definition of RDN equality.
646
*
647
* @param obj The possibly null object to compare against.
648
* @return true if obj is equal to this LDAP name,
649
* false otherwise.
650
* @see #hashCode
651
*/
652
public boolean equals(Object obj) {
653
// check possible shortcuts
654
if (obj == this) {
655
return true;
656
}
657
if (!(obj instanceof LdapName)) {
658
return false;
659
}
660
LdapName that = (LdapName) obj;
661
if (rdns.size() != that.rdns.size()) {
662
return false;
663
}
664
if (unparsed != null && unparsed.equalsIgnoreCase(
665
that.unparsed)) {
666
return true;
667
}
668
// Compare RDNs one by one for equality
669
for (int i = 0; i < rdns.size(); i++) {
670
// Compare a single pair of RDNs.
671
Rdn rdn1 = rdns.get(i);
672
Rdn rdn2 = that.rdns.get(i);
673
if (!rdn1.equals(rdn2)) {
674
return false;
675
}
676
}
677
return true;
678
}
679
680
/**
681
* Compares this LdapName with the specified Object for order.
682
* Returns a negative integer, zero, or a positive integer as this
683
* Name is less than, equal to, or greater than the given Object.
684
* <p>
685
* If obj is null or not an instance of LdapName, ClassCastException
686
* is thrown.
687
* <p>
688
* Ordering of LDAP names follows the lexicographical rules for
689
* string comparison, with the extension that this applies to all
690
* the RDNs in the LDAP name. All the RDNs are lined up in their
691
* specified order and compared lexicographically.
692
* See {@link Rdn#compareTo(Object obj) Rdn.compareTo(Object obj)}
693
* for RDN comparison rules.
694
* <p>
695
* If this LDAP name is lexicographically lesser than obj,
696
* a negative number is returned.
697
* If this LDAP name is lexicographically greater than obj,
698
* a positive number is returned.
699
* @param obj The non-null LdapName instance to compare against.
700
*
701
* @return A negative integer, zero, or a positive integer as this Name
702
* is less than, equal to, or greater than the given obj.
703
* @exception ClassCastException if obj is null or not a LdapName.
704
*/
705
public int compareTo(Object obj) {
706
707
if (!(obj instanceof LdapName)) {
708
throw new ClassCastException("The obj is not a LdapName");
709
}
710
711
// check possible shortcuts
712
if (obj == this) {
713
return 0;
714
}
715
LdapName that = (LdapName) obj;
716
717
if (unparsed != null && unparsed.equalsIgnoreCase(
718
that.unparsed)) {
719
return 0;
720
}
721
722
// Compare RDNs one by one, lexicographically.
723
int minSize = Math.min(rdns.size(), that.rdns.size());
724
for (int i = 0; i < minSize; i++) {
725
// Compare a single pair of RDNs.
726
Rdn rdn1 = rdns.get(i);
727
Rdn rdn2 = that.rdns.get(i);
728
729
int diff = rdn1.compareTo(rdn2);
730
if (diff != 0) {
731
return diff;
732
}
733
}
734
return (rdns.size() - that.rdns.size()); // longer DN wins
735
}
736
737
/**
738
* Computes the hash code of this LDAP name.
739
* The hash code is the sum of the hash codes of individual RDNs
740
* of this name.
741
*
742
* @return An int representing the hash code of this name.
743
* @see #equals
744
*/
745
public int hashCode() {
746
// Sum up the hash codes of the components.
747
int hash = 0;
748
749
// For each RDN...
750
for (int i = 0; i < rdns.size(); i++) {
751
Rdn rdn = rdns.get(i);
752
hash += rdn.hashCode();
753
}
754
return hash;
755
}
756
757
/**
758
* Serializes only the unparsed DN, for compactness and to avoid
759
* any implementation dependency.
760
*
761
* @serialData The DN string
762
*/
763
private void writeObject(ObjectOutputStream s)
764
throws java.io.IOException {
765
s.defaultWriteObject();
766
s.writeObject(toString());
767
}
768
769
private void readObject(ObjectInputStream s)
770
throws java.io.IOException, ClassNotFoundException {
771
s.defaultReadObject();
772
unparsed = (String)s.readObject();
773
try {
774
parse();
775
} catch (InvalidNameException e) {
776
// shouldn't happen
777
throw new java.io.StreamCorruptedException(
778
"Invalid name: " + unparsed);
779
}
780
}
781
782
private void parse() throws InvalidNameException {
783
// rdns = (ArrayList<Rdn>) (new RFC2253Parser(unparsed)).getDN();
784
785
rdns = new Rfc2253Parser(unparsed).parseDn();
786
}
787
}
788
789