1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.directory.api.ldap.model.name;
22
23
24 import java.io.Externalizable;
25 import java.io.IOException;
26 import java.io.ObjectInput;
27 import java.io.ObjectOutput;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.TreeSet;
36
37 import org.apache.commons.collections.list.UnmodifiableList;
38 import org.apache.directory.api.i18n.I18n;
39 import org.apache.directory.api.ldap.model.exception.LdapException;
40 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
41 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
42 import org.apache.directory.api.ldap.model.schema.SchemaManager;
43 import org.apache.directory.api.ldap.model.schema.normalizers.OidNormalizer;
44 import org.apache.directory.api.util.Strings;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public class Dn implements Iterable<Rdn>, Externalizable
70 {
71
72 protected static final Logger LOG = LoggerFactory.getLogger( Dn.class );
73
74
75
76
77
78
79
80
81 private static final long serialVersionUID = 1L;
82
83
84 public static final int NOT_EQUAL = -1;
85
86
87 public static final int EQUAL = 0;
88
89
90
91
92
93
94
95
96
97
98
99
100
101 protected List<Rdn> rdns = new ArrayList<Rdn>( 5 );
102
103
104 private String upName;
105
106
107 private String normName;
108
109
110 private byte[] bytes;
111
112
113 public static final Dn EMPTY_DN = new Dn();
114
115
116 public static final Dn ROOT_DSE = new Dn();
117
118
119 private SchemaManager schemaManager;
120
121
122
123
124 private final class RdnIterator implements Iterator<Rdn>
125 {
126
127 int index;
128
129
130 private RdnIterator()
131 {
132 index = rdns != null ? rdns.size() - 1 : -1;
133 }
134
135
136
137
138
139 public boolean hasNext()
140 {
141 return index >= 0;
142 }
143
144
145
146
147
148 public Rdn next()
149 {
150 return index >= 0 ? rdns.get( index-- ) : null;
151 }
152
153
154
155
156
157 public void remove()
158 {
159
160 }
161 }
162
163
164
165
166
167 public Dn()
168 {
169 this( ( SchemaManager ) null );
170 }
171
172
173
174
175
176
177
178 public Dn( SchemaManager schemaManager )
179 {
180 this.schemaManager = schemaManager;
181 upName = "";
182 normName = "";
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 public Dn( String... upRdns ) throws LdapInvalidDnException
210 {
211 this( null, upRdns );
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238 public Dn( SchemaManager schemaManager, String... upRdns ) throws LdapInvalidDnException
239 {
240 StringBuilder sb = new StringBuilder();
241 boolean valueExpected = false;
242 boolean isFirst = true;
243
244 for ( String upRdn : upRdns )
245 {
246 if ( Strings.isEmpty( upRdn ) )
247 {
248 continue;
249 }
250
251 if ( isFirst )
252 {
253 isFirst = false;
254 }
255 else if ( !valueExpected )
256 {
257 sb.append( ',' );
258 }
259
260 if ( !valueExpected )
261 {
262 sb.append( upRdn );
263
264 if ( upRdn.indexOf( '=' ) == -1 )
265 {
266 valueExpected = true;
267 }
268 }
269 else
270 {
271 sb.append( "=" ).append( upRdn );
272
273 valueExpected = false;
274 }
275 }
276
277 if ( !isFirst && valueExpected )
278 {
279 throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, I18n.err( I18n.ERR_04202 ) );
280 }
281
282
283
284 upName = sb.toString();
285 parseInternal( upName, rdns );
286
287 apply( schemaManager );
288 }
289
290
291
292
293
294
295
296
297
298
299
300
301 Dn( SchemaManager schemaManager, String upName, String normName, Rdn... rdns )
302 {
303 this.schemaManager = schemaManager;
304 this.upName = upName;
305 this.normName = normName;
306 bytes = Strings.getBytesUtf8Ascii( upName );
307 this.rdns = Arrays.asList( rdns );
308 }
309
310
311
312
313
314
315
316
317 public Dn( Rdn... rdns ) throws LdapInvalidDnException
318 {
319 if ( rdns == null )
320 {
321 return;
322 }
323
324 for ( Rdn rdn : rdns )
325 {
326 this.rdns.add( rdn );
327 }
328
329 apply( null );
330 toUpName();
331 }
332
333
334
335
336
337
338
339
340
341 public Dn( Rdn rdn, Dn dn ) throws LdapInvalidDnException
342 {
343 if ( ( dn == null ) || ( rdn == null ) )
344 {
345 throw new IllegalArgumentException( "Either the dn or the rdn is null" );
346 }
347
348 for ( Rdn rdnParent : dn )
349 {
350 rdns.add( 0, rdnParent );
351 }
352
353 rdns.add( 0, rdn );
354
355 apply( dn.schemaManager );
356 toUpName();
357 }
358
359
360
361
362
363
364
365
366
367 public Dn( SchemaManager schemaManager, Rdn... rdns ) throws LdapInvalidDnException
368 {
369 if ( rdns == null )
370 {
371 return;
372 }
373
374 for ( Rdn rdn : rdns )
375 {
376 this.rdns.add( rdn );
377 }
378
379 apply( schemaManager );
380 toUpName();
381 }
382
383
384
385
386
387
388
389 public SchemaManager getSchemaManager()
390 {
391 return schemaManager;
392 }
393
394
395
396
397
398
399
400 private String toUpName()
401 {
402 if ( rdns.size() == 0 )
403 {
404 upName = "";
405 }
406 else
407 {
408 StringBuffer sb = new StringBuffer();
409 boolean isFirst = true;
410
411 for ( Rdn rdn : rdns )
412 {
413 if ( isFirst )
414 {
415 isFirst = false;
416 }
417 else
418 {
419 sb.append( ',' );
420 }
421
422 sb.append( rdn.getName() );
423 }
424
425 upName = sb.toString();
426 }
427
428 return upName;
429 }
430
431
432
433
434
435
436
437
438 @Override
439 public int hashCode()
440 {
441 int result = 37;
442
443 for ( Rdn rdn : rdns )
444 {
445 result = result * 17 + rdn.hashCode();
446 }
447
448 return result;
449 }
450
451
452
453
454
455
456
457 public String getName()
458 {
459 return ( upName == null ? "" : upName );
460 }
461
462
463
464
465
466
467
468
469
470 void setUpName( String upName )
471 {
472 this.upName = upName;
473 }
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492 public String getNormName()
493 {
494 return normName;
495 }
496
497
498
499
500
501
502 public int size()
503 {
504 return rdns.size();
505 }
506
507
508
509
510
511
512
513
514 public static int getNbBytes( Dn dn )
515 {
516 return dn.bytes == null ? 0 : dn.bytes.length;
517 }
518
519
520
521
522
523
524
525
526 public static byte[] getBytes( Dn dn )
527 {
528 return dn == null ? null : dn.bytes;
529 }
530
531
532
533
534
535
536
537
538
539
540 public boolean isAncestorOf( String dn )
541 {
542 try
543 {
544 return isAncestorOf( new Dn( dn ) );
545 }
546 catch ( LdapInvalidDnException lide )
547 {
548 return false;
549 }
550 }
551
552
553
554
555
556
557
558
559
560
561 public boolean isAncestorOf( Dn dn )
562 {
563 if ( dn == null )
564 {
565 return false;
566 }
567
568 return dn.isDescendantOf( this );
569 }
570
571
572
573
574
575
576
577
578
579
580 public boolean isDescendantOf( String dn )
581 {
582 try
583 {
584 return isDescendantOf( new Dn( schemaManager, dn ) );
585 }
586 catch ( LdapInvalidDnException lide )
587 {
588 return false;
589 }
590 }
591
592
593
594
595
596
597
598
599
600
601 public boolean isDescendantOf( Dn dn )
602 {
603 if ( ( dn == null ) || dn.isRootDse() )
604 {
605 return true;
606 }
607
608 if ( dn.size() > size() )
609 {
610
611 return false;
612 }
613
614
615
616
617 for ( int i = dn.size() - 1; i >= 0; i-- )
618 {
619 Rdn nameRdn = dn.rdns.get( dn.rdns.size() - i - 1 );
620 Rdn ldapRdn = rdns.get( rdns.size() - i - 1 );
621
622 if ( !nameRdn.equals( ldapRdn ) )
623 {
624 return false;
625 }
626 }
627
628 return true;
629 }
630
631
632
633
634
635
636
637 public boolean isEmpty()
638 {
639 return ( rdns.size() == 0 );
640 }
641
642
643
644
645
646
647
648 public boolean isRootDse()
649 {
650 return ( rdns.size() == 0 );
651 }
652
653
654
655
656
657
658
659
660
661
662
663 public Rdn getRdn( int posn )
664 {
665 if ( rdns.size() == 0 )
666 {
667 return null;
668 }
669
670 if ( ( posn < 0 ) || ( posn >= rdns.size() ) )
671 {
672 throw new IllegalArgumentException( "Invalid position : " + posn );
673 }
674
675 Rdn rdn = rdns.get( posn );
676
677 return rdn;
678 }
679
680
681
682
683
684
685
686 public Rdn getRdn()
687 {
688 if ( isNullOrEmpty( this ) )
689 {
690 return Rdn.EMPTY_RDN;
691 }
692
693 return rdns.get( 0 );
694 }
695
696
697
698
699
700
701
702 @SuppressWarnings("unchecked")
703 public List<Rdn> getRdns()
704 {
705 return UnmodifiableList.decorate( rdns );
706 }
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723 public Dn getDescendantOf( String ancestor ) throws LdapInvalidDnException
724 {
725 return getDescendantOf( new Dn( schemaManager, ancestor ) );
726 }
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743 public Dn getDescendantOf( Dn ancestor ) throws LdapInvalidDnException
744 {
745 if ( ( ancestor == null ) || ( ancestor.size() == 0 ) )
746 {
747 return this;
748 }
749
750 if ( rdns.size() == 0 )
751 {
752 return EMPTY_DN;
753 }
754
755 int length = ancestor.size();
756
757 if ( length > rdns.size() )
758 {
759 String message = I18n.err( I18n.ERR_04206, length, rdns.size() );
760 LOG.error( message );
761 throw new ArrayIndexOutOfBoundsException( message );
762 }
763
764 Dn newDn = new Dn( schemaManager );
765 List<Rdn> rdnsAncestor = ancestor.getRdns();
766
767 for ( int i = 0; i < ancestor.size(); i++ )
768 {
769 Rdn rdn = rdns.get( size() - 1 - i );
770 Rdn rdnDescendant = rdnsAncestor.get( ancestor.size() - 1 - i );
771
772 if ( !rdn.equals( rdnDescendant ) )
773 {
774 throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX );
775 }
776 }
777
778 for ( int i = 0; i < rdns.size() - length; i++ )
779 {
780 newDn.rdns.add( rdns.get( i ) );
781 }
782
783 newDn.toUpName();
784 newDn.apply( schemaManager, true );
785
786 return newDn;
787 }
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804 public Dn getAncestorOf( String descendant ) throws LdapInvalidDnException
805 {
806 return getAncestorOf( new Dn( schemaManager, descendant ) );
807 }
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824 public Dn getAncestorOf( Dn descendant ) throws LdapInvalidDnException
825 {
826 if ( ( descendant == null ) || ( descendant.size() == 0 ) )
827 {
828 return this;
829 }
830
831 if ( rdns.size() == 0 )
832 {
833 return EMPTY_DN;
834 }
835
836 int length = descendant.size();
837
838 if ( length > rdns.size() )
839 {
840 String message = I18n.err( I18n.ERR_04206, length, rdns.size() );
841 LOG.error( message );
842 throw new ArrayIndexOutOfBoundsException( message );
843 }
844
845 Dn newDn = new Dn( schemaManager );
846 List<Rdn> rdnsDescendant = descendant.getRdns();
847
848 for ( int i = 0; i < descendant.size(); i++ )
849 {
850 Rdn rdn = rdns.get( i );
851 Rdn rdnDescendant = rdnsDescendant.get( i );
852
853 if ( !rdn.equals( rdnDescendant ) )
854 {
855 throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX );
856 }
857 }
858
859 for ( int i = length; i < rdns.size(); i++ )
860 {
861 newDn.rdns.add( rdns.get( i ) );
862 }
863
864 newDn.toUpName();
865 newDn.apply( schemaManager, true );
866
867 return newDn;
868 }
869
870
871
872
873
874 public Dn add( Dn suffix ) throws LdapInvalidDnException
875 {
876 if ( ( suffix == null ) || ( suffix.size() == 0 ) )
877 {
878 return this;
879 }
880
881 Dn clonedDn = copy();
882
883
884 clonedDn.rdns.addAll( 0, suffix.rdns );
885
886
887 if ( clonedDn.isSchemaAware() && suffix.isSchemaAware() )
888 {
889 if ( clonedDn.size() != 0 )
890 {
891 clonedDn.normName = suffix.getNormName() + "," + normName;
892 clonedDn.bytes = Strings.getBytesUtf8Ascii( normName );
893 clonedDn.upName = suffix.getName() + "," + upName;
894 }
895 }
896 else
897 {
898 clonedDn.apply( schemaManager, true );
899 clonedDn.toUpName();
900 }
901
902 return clonedDn;
903 }
904
905
906
907
908
909 public Dn add( String comp ) throws LdapInvalidDnException
910 {
911 if ( comp.length() == 0 )
912 {
913 return this;
914 }
915
916 Dn clonedDn = copy();
917
918
919 Rdn newRdn = new Rdn( schemaManager, comp );
920
921 clonedDn.rdns.add( 0, newRdn );
922
923 clonedDn.apply( schemaManager, true );
924 clonedDn.toUpName();
925
926 return clonedDn;
927 }
928
929
930
931
932
933
934
935
936 public Dn add( Rdn newRdn ) throws LdapInvalidDnException
937 {
938 if ( ( newRdn == null ) || ( newRdn.size() == 0 ) )
939 {
940 return this;
941 }
942
943 Dn clonedDn = copy();
944
945 clonedDn.rdns.add( 0, newRdn );
946 clonedDn.apply( schemaManager, true );
947 clonedDn.toUpName();
948
949 return clonedDn;
950 }
951
952
953
954
955
956
957
958
959
960 public Dn getParent()
961 {
962 if ( isNullOrEmpty( this ) )
963 {
964 return this;
965 }
966
967 int posn = rdns.size() - 1;
968
969 Dn newDn = new Dn( schemaManager );
970
971 for ( int i = rdns.size() - posn; i < rdns.size(); i++ )
972 {
973 newDn.rdns.add( rdns.get( i ) );
974 }
975
976 try
977 {
978 newDn.apply( schemaManager, true );
979 }
980 catch ( LdapInvalidDnException e )
981 {
982 LOG.error( e.getMessage(), e );
983 }
984
985 newDn.toUpName();
986
987 return newDn;
988 }
989
990
991
992
993
994 private Dn copy()
995 {
996 Dn dn = new Dn( schemaManager );
997 dn.rdns = new ArrayList<Rdn>();
998
999 for ( Rdn rdn : rdns )
1000 {
1001 dn.rdns.add( rdn );
1002 }
1003
1004 return dn;
1005 }
1006
1007
1008
1009
1010
1011
1012 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS",
1013 justification = "String is a special case")
1014 @Override
1015 public boolean equals( Object obj )
1016 {
1017 if ( obj instanceof String )
1018 {
1019 return normName.equals( obj );
1020 }
1021 else if ( obj instanceof Dn )
1022 {
1023 Dn name = ( Dn ) obj;
1024
1025 if ( name.getNormName().equals( normName ) )
1026 {
1027 return true;
1028 }
1029
1030 if ( name.size() != this.size() )
1031 {
1032 return false;
1033 }
1034
1035 for ( int i = 0; i < this.size(); i++ )
1036 {
1037 if ( !name.rdns.get( i ).equals( rdns.get( i ) ) )
1038 {
1039 return false;
1040 }
1041 }
1042
1043
1044 return true;
1045 }
1046 else
1047 {
1048 return false;
1049 }
1050 }
1051
1052
1053
1054
1055
1056 private static Ava atavOidToName( Ava atav, SchemaManager schemaManager )
1057 throws LdapInvalidDnException
1058 {
1059 Map<String, OidNormalizer> oidsMap = schemaManager.getNormalizerMapping();
1060 String type = Strings.trim( atav.getNormType() );
1061
1062 if ( ( type.startsWith( "oid." ) ) || ( type.startsWith( "OID." ) ) )
1063 {
1064 type = type.substring( 4 );
1065 }
1066
1067 if ( Strings.isNotEmpty( type ) )
1068 {
1069 if ( oidsMap == null )
1070 {
1071 return atav;
1072 }
1073
1074 type = Strings.toLowerCase( type );
1075
1076
1077 if ( !oidsMap.containsKey( type ) )
1078 {
1079
1080 String msg = I18n.err( I18n.ERR_04268_OID_NOT_FOUND, atav.getType() );
1081 LOG.error( msg );
1082 throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, msg );
1083 }
1084
1085 OidNormalizer oidNormalizer = oidsMap.get( type );
1086
1087 if ( oidNormalizer != null )
1088 {
1089 try
1090 {
1091 Ava newAva = new Ava(
1092 atav.getType(),
1093 oidNormalizer.getAttributeTypeOid(),
1094 atav.getValue(),
1095 oidNormalizer.getNormalizer().normalize( atav.getNormValue() ),
1096 atav.getName() );
1097 newAva.apply( schemaManager );
1098
1099 return newAva;
1100 }
1101 catch ( LdapException le )
1102 {
1103 throw new LdapInvalidDnException( le.getMessage(), le );
1104 }
1105 }
1106 else
1107 {
1108
1109 return atav;
1110 }
1111 }
1112 else
1113 {
1114
1115 String msg = I18n.err( I18n.ERR_04209_EMPTY_TYPE_NOT_ALLOWED );
1116 LOG.error( msg );
1117 throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, msg );
1118 }
1119 }
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131 static void rdnOidToName( Rdn rdn, SchemaManager schemaManager ) throws LdapInvalidDnException
1132 {
1133
1134
1135
1136
1137
1138 if ( rdn.size() < 2 )
1139 {
1140 Ava newAtav = atavOidToName( rdn.getAva(), schemaManager );
1141 rdn.replaceAva( newAtav, 0 );
1142 }
1143 else
1144 {
1145 Set<String> sortedOids = new TreeSet<String>();
1146 Map<String, Ava> avas = new HashMap<String, Ava>();
1147
1148
1149 for ( Ava val : rdn )
1150 {
1151 Ava newAtav = atavOidToName( val, schemaManager );
1152 String oid = newAtav.getAttributeType().getOid();
1153 sortedOids.add( oid );
1154 avas.put( oid, newAtav );
1155 }
1156
1157
1158 int pos = 0;
1159
1160 for ( String oid : sortedOids )
1161 {
1162 rdn.replaceAva( avas.get( oid ), pos++ );
1163 }
1164 }
1165 }
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177 public Dn apply( SchemaManager schemaManager, boolean force ) throws LdapInvalidDnException
1178 {
1179 if ( ( this.schemaManager == null ) || force )
1180 {
1181 this.schemaManager = schemaManager;
1182
1183 if ( this.schemaManager != null )
1184 {
1185 synchronized ( this )
1186 {
1187 if ( size() == 0 )
1188 {
1189 bytes = null;
1190 normName = "";
1191
1192 return this;
1193 }
1194
1195 StringBuilder sb = new StringBuilder();
1196 boolean isFirst = true;
1197
1198 for ( Rdn rdn : rdns )
1199 {
1200 rdn.apply( schemaManager );
1201
1202 if ( isFirst )
1203 {
1204 isFirst = false;
1205 }
1206 else
1207 {
1208 sb.append( ',' );
1209 }
1210
1211 sb.append( rdn.getNormName() );
1212 }
1213
1214 String newNormName = sb.toString();
1215
1216 if ( ( normName == null ) || !normName.equals( newNormName ) )
1217 {
1218 bytes = Strings.getBytesUtf8Ascii( newNormName );
1219 normName = newNormName;
1220 }
1221 }
1222 }
1223 else
1224 {
1225 if ( rdns.size() == 0 )
1226 {
1227 bytes = null;
1228 normName = "";
1229 }
1230 else
1231 {
1232 StringBuffer sb = new StringBuffer();
1233 boolean isFirst = true;
1234
1235 for ( Rdn rdn : rdns )
1236 {
1237 if ( isFirst )
1238 {
1239 isFirst = false;
1240 }
1241 else
1242 {
1243 sb.append( ',' );
1244 }
1245
1246 sb.append( rdn.getNormName() );
1247 }
1248
1249 String newNormName = sb.toString();
1250
1251 if ( ( normName == null ) || !normName.equals( newNormName ) )
1252 {
1253 bytes = Strings.getBytesUtf8Ascii( newNormName );
1254 normName = newNormName;
1255 }
1256 }
1257 }
1258 }
1259
1260 return this;
1261 }
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271 public Dn apply( SchemaManager schemaManager ) throws LdapInvalidDnException
1272 {
1273 if ( this.schemaManager != null )
1274 {
1275 return this;
1276 }
1277 else
1278 {
1279 return apply( schemaManager, true );
1280 }
1281 }
1282
1283
1284
1285
1286
1287
1288
1289 public boolean isSchemaAware()
1290 {
1291 return schemaManager != null;
1292 }
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314 public Iterator<Rdn> iterator()
1315 {
1316 return new RdnIterator();
1317 }
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327 public static boolean isNullOrEmpty( Dn dn )
1328 {
1329 return ( dn == null ) || dn.isEmpty();
1330 }
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340 public static boolean isValid( String name )
1341 {
1342 Dn dn = new Dn();
1343
1344 try
1345 {
1346 parseInternal( name, dn.rdns );
1347 return true;
1348 }
1349 catch ( LdapInvalidDnException e )
1350 {
1351 return false;
1352 }
1353 }
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363 private static void parseInternal( String name, List<Rdn> rdns ) throws LdapInvalidDnException
1364 {
1365 try
1366 {
1367 FastDnParser.parseDn( name, rdns );
1368 }
1369 catch ( TooComplexDnException e )
1370 {
1371 rdns.clear();
1372 new ComplexDnParser().parseDn( name, rdns );
1373 }
1374 }
1375
1376
1377
1378
1379
1380 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
1381 {
1382
1383 upName = in.readUTF();
1384
1385
1386 normName = in.readUTF();
1387
1388 if ( normName.length() == 0 )
1389 {
1390
1391
1392
1393 normName = upName;
1394 }
1395
1396
1397 int nbRdns = in.readInt();
1398
1399 rdns = new ArrayList<Rdn>( nbRdns );
1400
1401 for ( int i = 0; i < nbRdns; i++ )
1402 {
1403 Rdn rdn = new Rdn( schemaManager );
1404 rdn.readExternal( in );
1405 rdns.add( rdn );
1406 }
1407 }
1408
1409
1410
1411
1412
1413 public void writeExternal( ObjectOutput out ) throws IOException
1414 {
1415 if ( upName == null )
1416 {
1417 String message = "Cannot serialize a NULL Dn";
1418 LOG.error( message );
1419 throw new IOException( message );
1420 }
1421
1422
1423 out.writeUTF( upName );
1424
1425
1426 if ( upName.equals( normName ) )
1427 {
1428 out.writeUTF( "" );
1429 }
1430 else
1431 {
1432 out.writeUTF( normName );
1433 }
1434
1435
1436
1437 out.writeInt( size() );
1438
1439
1440 for ( Rdn rdn : rdns )
1441 {
1442 rdn.writeExternal( out );
1443 }
1444
1445 out.flush();
1446 }
1447
1448
1449
1450
1451
1452
1453
1454
1455 @Override
1456 public String toString()
1457 {
1458 return getName();
1459 }
1460 }