1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.ldap.model.name;
21
22
23 import java.io.Externalizable;
24 import java.io.IOException;
25 import java.io.ObjectInput;
26 import java.io.ObjectOutput;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Iterator;
30 import java.util.List;
31
32 import org.apache.commons.collections.MultiMap;
33 import org.apache.commons.collections.map.MultiValueMap;
34 import org.apache.directory.api.i18n.I18n;
35 import org.apache.directory.api.ldap.model.entry.StringValue;
36 import org.apache.directory.api.ldap.model.entry.Value;
37 import org.apache.directory.api.ldap.model.exception.LdapException;
38 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
39 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
40 import org.apache.directory.api.ldap.model.schema.AttributeType;
41 import org.apache.directory.api.ldap.model.schema.SchemaManager;
42 import org.apache.directory.api.ldap.model.schema.normalizers.OidNormalizer;
43 import org.apache.directory.api.util.Chars;
44 import org.apache.directory.api.util.Hex;
45 import org.apache.directory.api.util.Serialize;
46 import org.apache.directory.api.util.StringConstants;
47 import org.apache.directory.api.util.Strings;
48 import org.apache.directory.api.util.Unicode;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public class Rdn implements Cloneable, Externalizable, Iterable<Ava>, Comparable<Rdn>
120 {
121
122 protected static final Logger LOG = LoggerFactory.getLogger( Rdn.class );
123
124
125 public static final Rdn EMPTY_RDN = new Rdn();
126
127
128
129
130
131
132
133
134 private static final long serialVersionUID = 1L;
135
136
137 private String upName = null;
138
139
140 private String normName = null;
141
142
143
144
145
146
147
148 private List<Ava> avas = null;
149
150
151
152
153
154
155
156 private MultiMap avaTypes = new MultiValueMap();
157
158
159
160
161 private String avaType = null;
162
163
164
165
166
167
168 protected Ava ava = null;
169
170
171
172
173
174 private int nbAvas = 0;
175
176
177 public static final int UNDEFINED = Integer.MAX_VALUE;
178
179
180 public static final int SUPERIOR = 1;
181
182
183 public static final int INFERIOR = -1;
184
185
186 public static final int EQUAL = 0;
187
188
189 private boolean normalized = false;
190
191
192 private SchemaManager schemaManager;
193
194
195 private volatile int h;
196
197
198
199
200
201 public Rdn()
202 {
203 this( ( SchemaManager ) null );
204 }
205
206
207
208
209
210
211
212
213 public Rdn( SchemaManager schemaManager )
214 {
215
216
217
218 this.schemaManager = schemaManager;
219 upName = "";
220 normName = "";
221 normalized = false;
222 h = 0;
223 }
224
225
226
227
228
229
230
231
232
233 public Rdn( SchemaManager schemaManager, String rdn ) throws LdapInvalidDnException
234 {
235 if ( Strings.isNotEmpty( rdn ) )
236 {
237
238 parse( rdn, this );
239
240
241
242 if ( schemaManager != null )
243 {
244 this.schemaManager = schemaManager;
245 apply( schemaManager );
246 normalized = true;
247 }
248 else
249 {
250 normalize();
251 normalized = false;
252 }
253
254 if ( upName.length() < rdn.length() )
255 {
256 throw new LdapInvalidDnException( "Invalid RDN" );
257 }
258
259 upName = rdn;
260 }
261 else
262 {
263 upName = "";
264 normName = "";
265 normalized = false;
266 }
267
268 hashCode();
269 }
270
271
272
273
274
275
276
277
278 public Rdn( String rdn ) throws LdapInvalidDnException
279 {
280 this( ( SchemaManager ) null, rdn );
281 }
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296 public Rdn( SchemaManager schemaManager, String upType, String upValue ) throws LdapInvalidDnException
297 {
298 addAVA( schemaManager, upType, upType, new StringValue( upValue ), new StringValue( upValue ) );
299
300 upName = upType + '=' + upValue;
301
302 if ( schemaManager != null )
303 {
304 this.schemaManager = schemaManager;
305 apply( schemaManager );
306 normalized = true;
307 }
308 else
309 {
310
311 normalize();
312
313
314 normalized = false;
315 }
316
317 hashCode();
318 }
319
320
321
322
323
324
325
326
327
328
329 public Rdn( String upType, String upValue ) throws LdapInvalidDnException
330 {
331 this( null, upType, upValue );
332 }
333
334
335 public Rdn( SchemaManager schemaManager, Ava... avas ) throws LdapInvalidDnException
336 {
337 StringBuilder upName = new StringBuilder();
338 for ( int i = 0; i < avas.length; i++ )
339 {
340 if ( i > 0 )
341 {
342 upName.append( '+' );
343 }
344 addAVA( schemaManager, avas[i] );
345 upName.append( avas[i].getName() );
346 }
347 setUpName( upName.toString() );
348 normalize();
349 }
350
351
352 public Rdn( Ava... avas ) throws LdapInvalidDnException
353 {
354 this( null, avas );
355 }
356
357
358
359
360
361
362
363
364 public Rdn( Rdn rdn )
365 {
366 nbAvas = rdn.size();
367 this.normName = rdn.normName;
368 this.upName = rdn.getName();
369 normalized = rdn.normalized;
370 schemaManager = rdn.schemaManager;
371
372 switch ( rdn.size() )
373 {
374 case 0:
375 hashCode();
376
377 return;
378
379 case 1:
380 this.ava = rdn.ava.clone();
381 hashCode();
382
383 return;
384
385 default:
386
387 avas = new ArrayList<Ava>();
388 avaTypes = new MultiValueMap();
389
390 for ( Ava currentAva : rdn.avas )
391 {
392 avas.add( currentAva.clone() );
393 avaTypes.put( currentAva.getNormType(), currentAva );
394 }
395
396 hashCode();
397
398 return;
399 }
400 }
401
402
403
404
405
406
407
408
409
410
411
412 void normalize()
413 {
414 switch ( nbAvas )
415 {
416 case 0:
417
418 normName = "";
419 break;
420
421 case 1:
422
423
424 if ( ava.getNormValue().isHumanReadable() )
425 {
426 normName = ava.getNormName();
427 }
428 else
429 {
430 normName = ava.getNormType() + "=#" + Strings.dumpHexPairs( ava.getNormValue().getBytes() );
431 }
432
433 break;
434
435 default:
436
437 StringBuffer sb = new StringBuffer();
438
439 boolean isFirst = true;
440
441 for ( Ava ata : avas )
442 {
443 if ( isFirst )
444 {
445 isFirst = false;
446 }
447 else
448 {
449 sb.append( '+' );
450 }
451
452 sb.append( ata.getNormName() );
453 }
454
455 normName = sb.toString();
456 break;
457 }
458
459 hashCode();
460 }
461
462
463
464
465
466
467
468
469
470
471
472 public Rdn apply( SchemaManager schemaManager ) throws LdapInvalidDnException
473 {
474 if ( normalized )
475 {
476 return this;
477 }
478
479 String savedUpName = getName();
480 Dn.rdnOidToName( this, schemaManager );
481 normalize();
482 this.upName = savedUpName;
483 normalized = true;
484 this.schemaManager = schemaManager;
485 hashCode();
486
487 return this;
488 }
489
490
491
492
493
494
495
496
497
498
499
500
501 private void addAVA( SchemaManager schemaManager, String upType, String type, Value<?> upValue,
502 Value<?> value ) throws LdapInvalidDnException
503 {
504
505 Value<?> normalizedValue = value;
506 String normalizedType = Strings.lowerCaseAscii( type );
507 this.schemaManager = schemaManager;
508
509 if ( schemaManager != null )
510 {
511 OidNormalizer oidNormalizer = schemaManager.getNormalizerMapping().get( normalizedType );
512 normalizedType = oidNormalizer.getAttributeTypeOid();
513
514 try
515 {
516 normalizedValue = oidNormalizer.getNormalizer().normalize( value );
517 }
518 catch ( LdapException e )
519 {
520 throw new LdapInvalidDnException( e.getMessage(), e );
521 }
522 }
523
524 switch ( nbAvas )
525 {
526 case 0:
527
528 ava = new Ava( schemaManager, upType, normalizedType, upValue, normalizedValue );
529 nbAvas = 1;
530 avaType = normalizedType;
531 hashCode();
532
533 return;
534
535 case 1:
536
537
538
539 avas = new ArrayList<Ava>();
540
541
542 avas.add( ava );
543 avaTypes = new MultiValueMap();
544 avaTypes.put( avaType, ava );
545
546 ava = null;
547
548
549
550
551 default:
552
553 Ava newAva = new Ava( schemaManager, upType, normalizedType, upValue, normalizedValue );
554 avas.add( newAva );
555 avaTypes.put( normalizedType, newAva );
556 nbAvas++;
557 hashCode();
558
559 return;
560
561 }
562 }
563
564
565
566
567
568
569
570
571
572
573
574
575 void replaceAva( Ava value, int pos ) throws LdapInvalidDnException
576 {
577 if ( ( pos < 0 ) || ( pos > nbAvas ) )
578 {
579 throw new LdapInvalidDnException( "Cannot set the AVA at position " + pos );
580 }
581
582 String normalizedType = value.getNormType();
583
584 switch ( nbAvas )
585 {
586 case 1:
587
588 ava = value;
589 avaType = normalizedType;
590
591 break;
592
593 default:
594 Ava oldAva = avas.get( pos );
595 avas.set( pos, value );
596 avaTypes.remove( oldAva.getType() );
597 avaTypes.put( normalizedType, value );
598
599 break;
600 }
601
602 h = 0;
603 hashCode();
604 }
605
606
607
608
609
610
611
612
613
614
615 void addAVA( SchemaManager schemaManager, Ava value ) throws LdapInvalidDnException
616 {
617 this.schemaManager = schemaManager;
618 String normalizedType = value.getNormType();
619
620 switch ( nbAvas )
621 {
622 case 0:
623
624 ava = value;
625 nbAvas = 1;
626 avaType = normalizedType;
627 hashCode();
628
629 return;
630
631 case 1:
632
633
634
635 if ( avaType.equals( normalizedType ) )
636 {
637 throw new LdapInvalidDnException( "Invalid RDN: the " + normalizedType
638 + " is already present in the RDN" );
639 }
640
641
642 avas = new ArrayList<Ava>();
643
644
645 avas.add( ava );
646 avaTypes = new MultiValueMap();
647 avaTypes.put( avaType, ava );
648
649 this.ava = null;
650
651
652
653
654 default:
655
656 if ( avaTypes.containsKey( normalizedType ) )
657 {
658 throw new LdapInvalidDnException( "Invalid RDN: the " + normalizedType
659 + " is already present in the RDN" );
660 }
661
662
663 avas.add( value );
664 avaTypes.put( normalizedType, value );
665 nbAvas++;
666 hashCode();
667
668 break;
669 }
670 }
671
672
673
674
675
676
677
678
679 void clear()
680 {
681 ava = null;
682 avas = null;
683 avaType = null;
684 avaTypes.clear();
685 nbAvas = 0;
686 normName = "";
687 upName = "";
688 normalized = false;
689 h = 0;
690 }
691
692
693
694
695
696
697
698
699
700
701 public Object getValue( String type ) throws LdapInvalidDnException
702 {
703
704 String normalizedType = Strings.lowerCaseAscii( Strings.trim( type ) );
705
706 if ( schemaManager != null )
707 {
708 AttributeType attributeType = schemaManager.getAttributeType( normalizedType );
709
710 if ( attributeType != null )
711 {
712 normalizedType = attributeType.getOid();
713 }
714 }
715
716 switch ( nbAvas )
717 {
718 case 0:
719 return "";
720
721 case 1:
722 if ( Strings.equals( ava.getNormType(), normalizedType ) )
723 {
724 return ava.getNormValue().getValue();
725 }
726
727 return "";
728
729 default:
730 if ( avaTypes.containsKey( normalizedType ) )
731 {
732 @SuppressWarnings("unchecked")
733 Collection<Ava> atavList = ( Collection<Ava> ) avaTypes.get( normalizedType );
734 StringBuffer sb = new StringBuffer();
735 boolean isFirst = true;
736
737 for ( Ava elem : atavList )
738 {
739 if ( isFirst )
740 {
741 isFirst = false;
742 }
743 else
744 {
745 sb.append( ',' );
746 }
747
748 sb.append( elem.getNormValue() );
749 }
750
751 return sb.toString();
752 }
753
754 return "";
755 }
756 }
757
758
759
760
761
762
763
764
765
766
767
768 public Ava getAva( String type )
769 {
770
771 String normalizedType = Strings.lowerCaseAscii( Strings.trim( type ) );
772
773 switch ( nbAvas )
774 {
775 case 0:
776 return null;
777
778 case 1:
779 if ( ava.getNormType().equals( normalizedType ) )
780 {
781 return ava;
782 }
783
784 return null;
785
786 default:
787 if ( avaTypes.containsKey( normalizedType ) )
788 {
789 @SuppressWarnings("unchecked")
790 Collection<Ava> atavList = ( Collection<Ava> ) avaTypes.get( normalizedType );
791 return atavList.iterator().next();
792 }
793
794 return null;
795 }
796 }
797
798
799
800
801
802
803
804
805
806 public Iterator<Ava> iterator()
807 {
808 if ( nbAvas == 1 || nbAvas == 0 )
809 {
810 return new Iterator<Ava>()
811 {
812 private boolean hasMoreElement = nbAvas == 1;
813
814
815 public boolean hasNext()
816 {
817 return hasMoreElement;
818 }
819
820
821 public Ava next()
822 {
823 Ava obj = ava;
824 hasMoreElement = false;
825 return obj;
826 }
827
828
829 public void remove()
830 {
831
832 }
833 };
834 }
835 else
836 {
837 return avas.iterator();
838 }
839 }
840
841
842
843
844
845
846
847 public Rdn clone()
848 {
849 try
850 {
851 Rdn rdn = ( Rdn ) super.clone();
852 rdn.normalized = normalized;
853
854
855
856 switch ( rdn.size() )
857 {
858 case 0:
859 break;
860
861 case 1:
862 rdn.ava = this.ava.clone();
863 rdn.avaTypes = avaTypes;
864 break;
865
866 default:
867
868 rdn.avaTypes = new MultiValueMap();
869 rdn.avas = new ArrayList<Ava>();
870
871 for ( Ava currentAva : this.avas )
872 {
873 rdn.avas.add( currentAva.clone() );
874 rdn.avaTypes.put( currentAva.getNormType(), currentAva );
875 }
876
877 break;
878 }
879
880 return rdn;
881 }
882 catch ( CloneNotSupportedException cnse )
883 {
884 throw new Error( "Assertion failure" );
885 }
886 }
887
888
889
890
891
892 public String getName()
893 {
894 return upName;
895 }
896
897
898
899
900
901 public String getNormName()
902 {
903 return normName == null ? "" : normName;
904 }
905
906
907
908
909
910
911
912
913
914 void setUpName( String upName )
915 {
916 this.upName = upName;
917 }
918
919
920
921
922
923
924
925
926 public Ava getAva()
927 {
928 switch ( nbAvas )
929 {
930 case 0:
931 return null;
932
933 case 1:
934 return ava;
935
936 default:
937 return avas.get( 0 );
938 }
939 }
940
941
942
943
944
945
946
947 public String getType()
948 {
949 switch ( nbAvas )
950 {
951 case 0:
952 return null;
953
954 case 1:
955 return ava.getType();
956
957 default:
958 return avas.get( 0 ).getType();
959 }
960 }
961
962
963
964
965
966
967
968 public String getNormType()
969 {
970 switch ( nbAvas )
971 {
972 case 0:
973 return null;
974
975 case 1:
976 return ava.getNormType();
977
978 default:
979 return avas.get( 0 ).getNormType();
980 }
981 }
982
983
984
985
986
987
988
989 public Value<?> getValue()
990 {
991 switch ( nbAvas )
992 {
993 case 0:
994 return null;
995
996 case 1:
997 return ava.getValue();
998
999 default:
1000 return avas.get( 0 ).getValue();
1001 }
1002 }
1003
1004
1005
1006
1007
1008
1009
1010 public Value<?> getNormValue()
1011 {
1012 switch ( nbAvas )
1013 {
1014 case 0:
1015 return null;
1016
1017 case 1:
1018 return ava.getNormValue();
1019
1020 default:
1021 return avas.get( 0 ).getNormValue();
1022 }
1023 }
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036 public boolean equals( Object that )
1037 {
1038 if ( this == that )
1039 {
1040 return true;
1041 }
1042
1043 if ( !( that instanceof Rdn ) )
1044 {
1045 return false;
1046 }
1047
1048 Rdn rdn = ( Rdn ) that;
1049
1050
1051 if ( normName.equals( rdn.normName ) )
1052 {
1053 return true;
1054 }
1055
1056
1057 if ( normName.equals( rdn.normName ) )
1058 {
1059 return true;
1060 }
1061
1062 if ( rdn.nbAvas != nbAvas )
1063 {
1064
1065
1066
1067 return false;
1068 }
1069
1070 switch ( nbAvas )
1071 {
1072 case 0:
1073 return true;
1074
1075 case 1:
1076 return ava.equals( rdn.ava );
1077
1078 default:
1079
1080
1081
1082
1083
1084
1085 Iterator<Ava> localIterator = avas.iterator();
1086
1087 while ( localIterator.hasNext() )
1088 {
1089 Iterator<Ava> paramIterator = rdn.avas.iterator();
1090
1091 Ava localAva = localIterator.next();
1092 boolean equals = false;
1093
1094 while ( paramIterator.hasNext() )
1095 {
1096 Ava paramAva = paramIterator.next();
1097
1098 if ( localAva.equals( paramAva ) )
1099 {
1100 equals = true;
1101 break;
1102 }
1103 }
1104
1105 if ( !equals )
1106 {
1107 return false;
1108 }
1109 }
1110
1111 return true;
1112 }
1113 }
1114
1115
1116
1117
1118
1119
1120
1121 public int size()
1122 {
1123 return nbAvas;
1124 }
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142 public static Object unescapeValue( String value ) throws IllegalArgumentException
1143 {
1144 if ( Strings.isEmpty( value ) )
1145 {
1146 return "";
1147 }
1148
1149 char[] chars = value.toCharArray();
1150
1151
1152 if ( ( chars[0] == '\"' ) && ( chars[chars.length - 1] == '\"' ) )
1153 {
1154 return value;
1155 }
1156
1157 if ( chars[0] == '#' )
1158 {
1159 if ( chars.length == 1 )
1160 {
1161
1162 return StringConstants.EMPTY_BYTES;
1163 }
1164
1165 if ( ( chars.length % 2 ) != 1 )
1166 {
1167 throw new IllegalArgumentException( I18n.err( I18n.ERR_04213 ) );
1168 }
1169
1170
1171 byte[] hexValue = new byte[( chars.length - 1 ) / 2];
1172 int pos = 0;
1173
1174 for ( int i = 1; i < chars.length; i += 2 )
1175 {
1176 if ( Chars.isHex( chars, i ) && Chars.isHex( chars, i + 1 ) )
1177 {
1178 hexValue[pos++] = Hex.getHexValue( chars[i], chars[i + 1] );
1179 }
1180 else
1181 {
1182 throw new IllegalArgumentException( I18n.err( I18n.ERR_04214 ) );
1183 }
1184 }
1185
1186 return hexValue;
1187 }
1188 else
1189 {
1190 boolean escaped = false;
1191 boolean isHex = false;
1192 byte pair = -1;
1193 int pos = 0;
1194
1195 byte[] bytes = new byte[chars.length * 6];
1196
1197 for ( int i = 0; i < chars.length; i++ )
1198 {
1199 if ( escaped )
1200 {
1201 escaped = false;
1202
1203 switch ( chars[i] )
1204 {
1205 case '\\':
1206 case '"':
1207 case '+':
1208 case ',':
1209 case ';':
1210 case '<':
1211 case '>':
1212 case '#':
1213 case '=':
1214 case ' ':
1215 bytes[pos++] = ( byte ) chars[i];
1216 break;
1217
1218 default:
1219 if ( Chars.isHex( chars, i ) )
1220 {
1221 isHex = true;
1222 pair = ( ( byte ) ( Hex.getHexValue( chars[i] ) << 4 ) );
1223 }
1224
1225 break;
1226 }
1227 }
1228 else
1229 {
1230 if ( isHex )
1231 {
1232 if ( Chars.isHex( chars, i ) )
1233 {
1234 pair += Hex.getHexValue( chars[i] );
1235 bytes[pos++] = pair;
1236 isHex = false;
1237 }
1238 }
1239 else
1240 {
1241 switch ( chars[i] )
1242 {
1243 case '\\':
1244 escaped = true;
1245 break;
1246
1247
1248
1249
1250 case '"':
1251 case '+':
1252 case ',':
1253 case ';':
1254 case '<':
1255 case '>':
1256 case '#':
1257 if ( i != 0 )
1258 {
1259
1260 bytes[pos++] = '#';
1261 break;
1262 }
1263 case '=':
1264 throw new IllegalArgumentException( I18n.err( I18n.ERR_04215 ) );
1265
1266 case ' ':
1267 if ( ( i == 0 ) || ( i == chars.length - 1 ) )
1268 {
1269 throw new IllegalArgumentException( I18n.err( I18n.ERR_04215 ) );
1270 }
1271 else
1272 {
1273 bytes[pos++] = ' ';
1274 break;
1275 }
1276
1277 default:
1278 if ( ( chars[i] >= 0 ) && ( chars[i] < 128 ) )
1279 {
1280 bytes[pos++] = ( byte ) chars[i];
1281 }
1282 else
1283 {
1284 byte[] result = Unicode.charToBytes( chars[i] );
1285 System.arraycopy( result, 0, bytes, pos, result.length );
1286 pos += result.length;
1287 }
1288
1289 break;
1290 }
1291 }
1292 }
1293 }
1294
1295 return Strings.utf8ToString( bytes, pos );
1296 }
1297 }
1298
1299
1300
1301
1302
1303
1304
1305
1306 public static String escapeValue( String value )
1307 {
1308 if ( Strings.isEmpty( value ) )
1309 {
1310 return "";
1311 }
1312
1313 char[] chars = value.toCharArray();
1314 char[] newChars = new char[chars.length * 3];
1315 int pos = 0;
1316
1317 for ( int i = 0; i < chars.length; i++ )
1318 {
1319 switch ( chars[i] )
1320 {
1321 case ' ':
1322 if ( ( i > 0 ) && ( i < chars.length - 1 ) )
1323 {
1324 newChars[pos++] = chars[i];
1325 }
1326 else
1327 {
1328 newChars[pos++] = '\\';
1329 newChars[pos++] = chars[i];
1330 }
1331
1332 break;
1333
1334 case '#':
1335 if ( i != 0 )
1336 {
1337 newChars[pos++] = chars[i];
1338 }
1339 else
1340 {
1341 newChars[pos++] = '\\';
1342 newChars[pos++] = chars[i];
1343 }
1344
1345 break;
1346
1347 case '"':
1348 case '+':
1349 case ',':
1350 case ';':
1351 case '=':
1352 case '<':
1353 case '>':
1354 case '\\':
1355 newChars[pos++] = '\\';
1356 newChars[pos++] = chars[i];
1357 break;
1358
1359 case 0x7F:
1360 newChars[pos++] = '\\';
1361 newChars[pos++] = '7';
1362 newChars[pos++] = 'F';
1363 break;
1364
1365 case 0x00:
1366 case 0x01:
1367 case 0x02:
1368 case 0x03:
1369 case 0x04:
1370 case 0x05:
1371 case 0x06:
1372 case 0x07:
1373 case 0x08:
1374 case 0x09:
1375 case 0x0A:
1376 case 0x0B:
1377 case 0x0C:
1378 case 0x0D:
1379 case 0x0E:
1380 case 0x0F:
1381 newChars[pos++] = '\\';
1382 newChars[pos++] = '0';
1383 newChars[pos++] = Strings.dumpHex( ( byte ) ( chars[i] & 0x0F ) );
1384 break;
1385
1386 case 0x10:
1387 case 0x11:
1388 case 0x12:
1389 case 0x13:
1390 case 0x14:
1391 case 0x15:
1392 case 0x16:
1393 case 0x17:
1394 case 0x18:
1395 case 0x19:
1396 case 0x1A:
1397 case 0x1B:
1398 case 0x1C:
1399 case 0x1D:
1400 case 0x1E:
1401 case 0x1F:
1402 newChars[pos++] = '\\';
1403 newChars[pos++] = '1';
1404 newChars[pos++] = Strings.dumpHex( ( byte ) ( chars[i] & 0x0F ) );
1405 break;
1406
1407 default:
1408 newChars[pos++] = chars[i];
1409 break;
1410 }
1411 }
1412
1413 return new String( newChars, 0, pos );
1414 }
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424 public static String escapeValue( byte[] attrValue )
1425 {
1426 if ( Strings.isEmpty( attrValue ) )
1427 {
1428 return "";
1429 }
1430
1431 String value = Strings.utf8ToString( attrValue );
1432
1433 return escapeValue( value );
1434 }
1435
1436
1437
1438
1439
1440
1441
1442 public boolean isSchemaAware()
1443 {
1444 return schemaManager != null;
1445 }
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458 public static boolean isValid( String dn )
1459 {
1460 Rdn rdn = new Rdn();
1461
1462 try
1463 {
1464 parse( dn, rdn );
1465
1466 return true;
1467 }
1468 catch ( LdapInvalidDnException e )
1469 {
1470 return false;
1471 }
1472 }
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487 private static void parse( String dn, Rdn rdn ) throws LdapInvalidDnException
1488 {
1489 try
1490 {
1491 FastDnParser.parseRdn( dn, rdn );
1492 }
1493 catch ( TooComplexDnException e )
1494 {
1495 rdn.clear();
1496 new ComplexDnParser().parseRdn( dn, rdn );
1497 }
1498 }
1499
1500
1501
1502
1503
1504
1505
1506
1507 public int hashCode()
1508 {
1509 if ( h == 0 )
1510 {
1511 h = 37;
1512
1513 switch ( nbAvas )
1514 {
1515 case 0:
1516
1517 break;
1518
1519 case 1:
1520
1521 h = h * 17 + ava.hashCode();
1522 break;
1523
1524 default:
1525
1526
1527 for ( Ava ata : avas )
1528 {
1529 h = h * 17 + ata.hashCode();
1530 }
1531
1532 break;
1533 }
1534 }
1535
1536 return h;
1537 }
1538
1539
1540
1541
1542
1543
1544
1545 public int serialize( byte[] buffer, int pos ) throws IOException
1546 {
1547 int length = 4 + 4;
1548
1549
1550 pos = Serialize.serialize( nbAvas, buffer, pos );
1551
1552
1553 byte[] upNameBytes = Strings.getBytesUtf8( upName );
1554 length += 4 + upNameBytes.length;
1555
1556 byte[] normNameBytes = Strings.EMPTY_BYTES;
1557 length += 4;
1558
1559 if ( !upName.equals( normName ) )
1560 {
1561 normNameBytes = Strings.getBytesUtf8( normName );
1562 length += 4 + normNameBytes.length;
1563 }
1564
1565
1566 if ( buffer.length - pos < length )
1567 {
1568 throw new ArrayIndexOutOfBoundsException();
1569 }
1570
1571
1572 pos = Serialize.serialize( upNameBytes, buffer, pos );
1573
1574
1575 pos = Serialize.serialize( normNameBytes, buffer, pos );
1576
1577
1578 switch ( nbAvas )
1579 {
1580 case 0:
1581 break;
1582
1583 case 1:
1584 pos = ava.serialize( buffer, pos );
1585
1586 break;
1587
1588 default:
1589 for ( Ava localAva : avas )
1590 {
1591 pos = localAva.serialize( buffer, pos );
1592 }
1593
1594 break;
1595 }
1596
1597
1598 pos = Serialize.serialize( h, buffer, pos );
1599
1600 return pos;
1601 }
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613 public int deserialize( byte[] buffer, int pos ) throws IOException, LdapInvalidAttributeValueException
1614 {
1615 if ( ( pos < 0 ) || ( pos >= buffer.length ) )
1616 {
1617 throw new ArrayIndexOutOfBoundsException();
1618 }
1619
1620
1621 nbAvas = Serialize.deserializeInt( buffer, pos );
1622 pos += 4;
1623
1624
1625 byte[] upNameBytes = Serialize.deserializeBytes( buffer, pos );
1626 pos += 4 + upNameBytes.length;
1627 upName = Strings.utf8ToString( upNameBytes );
1628
1629
1630 byte[] normNameBytes = Serialize.deserializeBytes( buffer, pos );
1631 pos += 4 + normNameBytes.length;
1632
1633 if ( normNameBytes.length == 0 )
1634 {
1635 normName = upName;
1636 }
1637 else
1638 {
1639 normName = Strings.utf8ToString( normNameBytes );
1640 }
1641
1642
1643 switch ( nbAvas )
1644 {
1645 case 0:
1646 break;
1647
1648 case 1:
1649 ava = new Ava( schemaManager );
1650 pos = ava.deserialize( buffer, pos );
1651 avaType = ava.getNormType();
1652
1653 break;
1654
1655 default:
1656 avas = new ArrayList<Ava>();
1657
1658 avaTypes = new MultiValueMap();
1659
1660 for ( int i = 0; i < nbAvas; i++ )
1661 {
1662 Ava ava = new Ava( schemaManager );
1663 pos = ava.deserialize( buffer, pos );
1664 avas.add( ava );
1665 avaTypes.put( ava.getNormType(), ava );
1666 }
1667
1668 ava = null;
1669 avaType = null;
1670
1671 break;
1672 }
1673
1674
1675 h = Serialize.deserializeInt( buffer, pos );
1676 pos += 4;
1677
1678 return pos;
1679 }
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722 public void writeExternal( ObjectOutput out ) throws IOException
1723 {
1724 out.writeInt( nbAvas );
1725 out.writeUTF( upName );
1726
1727 if ( upName.equals( normName ) )
1728 {
1729 out.writeUTF( "" );
1730 }
1731 else
1732 {
1733 out.writeUTF( normName );
1734 }
1735
1736 switch ( nbAvas )
1737 {
1738 case 0:
1739 break;
1740
1741 case 1:
1742 ava.writeExternal( out );
1743 break;
1744
1745 default:
1746 for ( Ava localAva : avas )
1747 {
1748 localAva.writeExternal( out );
1749 }
1750
1751 break;
1752 }
1753
1754 out.writeInt( h );
1755
1756 out.flush();
1757 }
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
1771 {
1772
1773 nbAvas = in.readInt();
1774
1775
1776 upName = in.readUTF();
1777
1778
1779 normName = in.readUTF();
1780
1781 if ( Strings.isEmpty( normName ) )
1782 {
1783 normName = upName;
1784 }
1785
1786 switch ( nbAvas )
1787 {
1788 case 0:
1789 ava = null;
1790 break;
1791
1792 case 1:
1793 ava = new Ava( schemaManager );
1794 ava.readExternal( in );
1795 avaType = ava.getNormType();
1796
1797 break;
1798
1799 default:
1800 avas = new ArrayList<Ava>();
1801
1802 avaTypes = new MultiValueMap();
1803
1804 for ( int i = 0; i < nbAvas; i++ )
1805 {
1806 Ava ava = new Ava( schemaManager );
1807 ava.readExternal( in );
1808 avas.add( ava );
1809 avaTypes.put( ava.getNormType(), ava );
1810 }
1811
1812 ava = null;
1813 avaType = null;
1814
1815 break;
1816 }
1817
1818 h = in.readInt();
1819 }
1820
1821
1822 public int compareTo( Rdn arg0 )
1823 {
1824
1825 return 0;
1826 }
1827
1828
1829
1830
1831
1832
1833 public String toString()
1834 {
1835 return upName == null ? "" : upName;
1836 }
1837 }