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.entry;
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.Arrays;
28
29 import org.apache.directory.api.i18n.I18n;
30 import org.apache.directory.api.ldap.model.exception.LdapException;
31 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
32 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
33 import org.apache.directory.api.ldap.model.schema.AttributeType;
34 import org.apache.directory.api.ldap.model.schema.LdapComparator;
35 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
36 import org.apache.directory.api.ldap.model.schema.MatchingRule;
37 import org.apache.directory.api.ldap.model.schema.Normalizer;
38 import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
39 import org.apache.directory.api.ldap.model.schema.comparators.StringComparator;
40 import org.apache.directory.api.ldap.model.schema.normalizers.NoOpNormalizer;
41 import org.apache.directory.api.util.Serialize;
42 import org.apache.directory.api.util.Strings;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 public class Value implements Cloneable, Externalizable, Comparable<Value>
74 {
75
76 private static final long serialVersionUID = 2L;
77
78
79 private static final Logger LOG = LoggerFactory.getLogger( Value.class );
80
81
82 private transient AttributeType attributeType;
83
84
85 private String upValue;
86
87
88 private String normValue;
89
90
91 private volatile int h;
92
93
94 private byte[] bytes;
95
96
97 private boolean isHR = true;
98
99
100 private static StringComparator stringComparator = new StringComparator( null );
101
102
103
104
105
106
107
108
109
110 public Value( String upValue )
111 {
112 this.upValue = upValue;
113
114
115 normValue = upValue;
116
117 if ( upValue != null )
118 {
119 bytes = Strings.getBytesUtf8( upValue );
120 }
121
122 hashCode();
123 }
124
125
126
127
128
129
130
131 public Value( byte[] value )
132 {
133 if ( value != null )
134 {
135 bytes = new byte[value.length];
136 System.arraycopy( value, 0, bytes, 0, value.length );
137 }
138 else
139 {
140 bytes = null;
141 }
142
143 isHR = false;
144
145 hashCode();
146 }
147
148
149
150
151
152
153
154
155
156
157 public Value( AttributeType attributeType, byte[] upValue ) throws LdapInvalidAttributeValueException
158 {
159 init( attributeType );
160
161 if ( upValue != null )
162 {
163 bytes = new byte[upValue.length];
164 System.arraycopy( upValue, 0, bytes, 0, upValue.length );
165
166 if ( isHR )
167 {
168 this.upValue = Strings.utf8ToString( upValue );
169 }
170 }
171 else
172 {
173 bytes = null;
174 }
175
176 if ( ( attributeType != null ) && !attributeType.isRelaxed() )
177 {
178
179 SyntaxChecker syntaxChecker = attributeType.getSyntax().getSyntaxChecker();
180
181 if ( syntaxChecker != null )
182 {
183 if ( !syntaxChecker.isValidSyntax( bytes ) )
184 {
185 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX,
186 I18n.err( I18n.ERR_13246_INVALID_VALUE_PER_SYNTAX ) );
187 }
188 }
189 else
190 {
191
192 throw new IllegalArgumentException( I18n.err( I18n.ERR_13219_NULL_SYNTAX_CHECKER, normValue ) );
193 }
194 }
195
196 hashCode();
197 }
198
199
200 private void init( AttributeType attributeType )
201 {
202 if ( attributeType != null )
203 {
204 if ( attributeType.getSyntax() == null )
205 {
206
207
208
209 if ( LOG.isTraceEnabled() )
210 {
211 LOG.trace( I18n.err( I18n.ERR_13225_NO_SYNTAX ) );
212 }
213
214 isHR = true;
215 }
216 else
217 {
218 isHR = attributeType.getSyntax().isHumanReadable();
219 }
220 }
221 else
222 {
223 if ( LOG.isWarnEnabled() )
224 {
225 LOG.warn( I18n.msg( I18n.MSG_13202_AT_IS_NULL ) );
226 }
227 }
228
229 this.attributeType = attributeType;
230 }
231
232
233
234
235
236
237
238
239 Value( AttributeType attributeType )
240 {
241 init( attributeType );
242 }
243
244
245
246
247
248
249
250
251
252
253 public Value( AttributeType attributeType, String upValue ) throws LdapInvalidAttributeValueException
254 {
255 init( attributeType );
256 this.upValue = upValue;
257
258 if ( upValue != null )
259 {
260 bytes = Strings.getBytesUtf8( upValue );
261 }
262 else
263 {
264 bytes = null;
265 }
266
267 try
268 {
269 computeNormValue();
270 }
271 catch ( LdapException le )
272 {
273 LOG.error( le.getMessage() );
274 throw new IllegalArgumentException( I18n.err( I18n.ERR_13247_INVALID_VALUE_CANT_NORMALIZE, upValue ) );
275 }
276
277 if ( !attributeType.isRelaxed() )
278 {
279
280 LdapSyntax syntax = attributeType.getSyntax();
281
282 if ( ( syntax != null ) && ( syntax.getSyntaxChecker() != null ) )
283 {
284 if ( !attributeType.getSyntax().getSyntaxChecker().isValidSyntax( upValue ) )
285 {
286 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX,
287 I18n.err( I18n.ERR_13246_INVALID_VALUE_PER_SYNTAX ) );
288 }
289 }
290 else
291 {
292
293 throw new IllegalArgumentException( I18n.err( I18n.ERR_13219_NULL_SYNTAX_CHECKER, normValue ) );
294 }
295 }
296
297 hashCode();
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311 public Value( AttributeType attributeType, String upValue, String normValue ) throws LdapInvalidAttributeValueException
312 {
313 init( attributeType );
314 this.upValue = upValue;
315
316 if ( upValue != null )
317 {
318 bytes = Strings.getBytesUtf8( upValue );
319 }
320 else
321 {
322 bytes = null;
323 }
324
325 this.normValue = normValue;
326
327 if ( !attributeType.isRelaxed() )
328 {
329
330 if ( attributeType.getSyntax().getSyntaxChecker() != null )
331 {
332 if ( !attributeType.getSyntax().getSyntaxChecker().isValidSyntax( upValue ) )
333 {
334 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX,
335 I18n.err( I18n.ERR_13246_INVALID_VALUE_PER_SYNTAX ) );
336 }
337 }
338 else
339 {
340
341 throw new IllegalArgumentException( I18n.err( I18n.ERR_13219_NULL_SYNTAX_CHECKER, normValue ) );
342 }
343 }
344
345 hashCode();
346 }
347
348
349
350
351
352
353
354
355
356 public Value( AttributeType attributeType, Value value ) throws LdapInvalidAttributeValueException
357 {
358 init( attributeType );
359
360 if ( isHR )
361 {
362 if ( value.isHR )
363 {
364 this.upValue = value.upValue;
365 }
366 else
367 {
368 this.upValue = Strings.utf8ToString( value.bytes );
369 }
370 }
371
372 try
373 {
374 computeNormValue();
375 }
376 catch ( LdapException le )
377 {
378 LOG.error( le.getMessage() );
379 throw new IllegalArgumentException( I18n.err( I18n.ERR_13247_INVALID_VALUE_CANT_NORMALIZE, upValue ) );
380 }
381
382
383 if ( !attributeType.isRelaxed() )
384 {
385
386 if ( attributeType.getSyntax().getSyntaxChecker() != null )
387 {
388 attributeType.getSyntax().getSyntaxChecker().isValidSyntax( value.normValue );
389 }
390 else
391 {
392
393 throw new IllegalArgumentException( I18n.err( I18n.ERR_13219_NULL_SYNTAX_CHECKER, normValue ) );
394 }
395 }
396
397
398 if ( value.bytes != null )
399 {
400 bytes = new byte[value.bytes.length];
401 System.arraycopy( value.bytes, 0, bytes, 0, value.bytes.length );
402 }
403
404 hashCode();
405 }
406
407
408
409
410
411
412
413
414
415 public static Value createValue( AttributeType attributeType )
416 {
417 return new Value( attributeType );
418 }
419
420
421
422
423
424
425
426 @Override
427 public Value clone()
428 {
429 try
430 {
431 Value clone = ( Value ) super.clone();
432
433 if ( isHR )
434 {
435 return clone;
436 }
437 else
438 {
439
440 if ( bytes != null )
441 {
442 clone.bytes = new byte[bytes.length];
443 System.arraycopy( bytes, 0, clone.bytes, 0, bytes.length );
444 }
445 }
446
447 return clone;
448 }
449 catch ( CloneNotSupportedException cnse )
450 {
451
452 return null;
453 }
454 }
455
456
457
458
459
460
461
462 public boolean isNull()
463 {
464 if ( isHR )
465 {
466 return upValue == null;
467 }
468 else
469 {
470 return bytes == null;
471 }
472 }
473
474
475
476
477
478
479
480 public AttributeType getAttributeType()
481 {
482 return attributeType;
483 }
484
485
486
487
488
489
490
491
492
493
494
495
496
497 public boolean isInstanceOf( AttributeType attributeType )
498 {
499 return ( attributeType != null )
500 && ( this.attributeType.equals( attributeType ) || this.attributeType.isDescendantOf( attributeType ) );
501 }
502
503
504
505
506
507
508
509 public String getEscaped()
510 {
511 if ( Strings.isEmpty( bytes ) )
512 {
513 return Strings.EMPTY_STRING;
514 }
515
516 StringBuilder sb = new StringBuilder();
517
518 boolean leadChar = true;
519
520 for ( int pos = 0; pos < bytes.length; pos++ )
521 {
522 boolean trailChar = pos == bytes.length - 1;
523 byte b = bytes[pos];
524
525 switch ( b )
526 {
527 case 0x00 :
528 sb.append( "\\00" );
529 break;
530
531 case 0x01 :
532 case 0x02 :
533 case 0x03 :
534 case 0x04 :
535 case 0x05 :
536 case 0x06 :
537 case 0x07 :
538 case 0x08 :
539 case 0x09 :
540 case 0x0A :
541 case 0x0B :
542 case 0x0C :
543 case 0x0D :
544 case 0x0E :
545 case 0x0F :
546 case 0x10 :
547 case 0x11 :
548 case 0x12 :
549 case 0x13 :
550 case 0x14 :
551 case 0x15 :
552 case 0x16 :
553 case 0x17 :
554 case 0x18 :
555 case 0x19 :
556 case 0x1A :
557 case 0x1B :
558 case 0x1C :
559 case 0x1D :
560 case 0x1E :
561 case 0x1F :
562 sb.append( ( char ) b );
563 break;
564
565 case 0x20 :
566 if ( leadChar || trailChar )
567 {
568 sb.append( "\\ " );
569 }
570 else
571 {
572 sb.append( ( char ) b );
573 }
574
575 break;
576
577 case 0x21 :
578 sb.append( ( char ) b );
579 break;
580
581
582 case 0x22 :
583 sb.append( "\\\"" );
584 break;
585
586 case 0x23 :
587 if ( leadChar )
588 {
589 sb.append( "\\#" );
590 }
591 else
592 {
593 sb.append( '#' );
594 }
595
596 break;
597
598 case 0x24 :
599 case 0x25 :
600 case 0x26 :
601 case 0x27 :
602 case 0x28 :
603 case 0x29 :
604 case 0x2A :
605 sb.append( ( char ) b );
606 break;
607
608 case 0x2B :
609 sb.append( "\\+" );
610 break;
611
612 case 0x2C :
613 sb.append( "\\," );
614 break;
615
616 case 0x2D :
617 case 0x2E :
618 case 0x2F :
619 case 0x30 :
620 case 0x31 :
621 case 0x32 :
622 case 0x33 :
623 case 0x34 :
624 case 0x35 :
625 case 0x36 :
626 case 0x37 :
627 case 0x38 :
628 case 0x39 :
629 case 0x3A :
630 sb.append( ( char ) b );
631 break;
632
633 case 0x3B :
634 sb.append( "\\;" );
635 break;
636
637 case 0x3C :
638 sb.append( "\\<" );
639 break;
640
641 case 0x3D :
642 sb.append( ( char ) b );
643 break;
644
645 case 0x3E :
646 sb.append( "\\>" );
647 break;
648
649 case 0x3F :
650 case 0x40 :
651 case 0x41 :
652 case 0x42 :
653 case 0x43 :
654 case 0x44 :
655 case 0x45 :
656 case 0x46 :
657 case 0x47 :
658 case 0x48 :
659 case 0x49 :
660 case 0x4A :
661 case 0x4B :
662 case 0x4C :
663 case 0x4D :
664 case 0x4E :
665 case 0x4F :
666 case 0x50 :
667 case 0x51 :
668 case 0x52 :
669 case 0x53 :
670 case 0x54 :
671 case 0x55 :
672 case 0x56 :
673 case 0x57 :
674 case 0x58 :
675 case 0x59 :
676 case 0x5A :
677 case 0x5B :
678 sb.append( ( char ) b );
679 break;
680
681 case 0x5C :
682 sb.append( "\\\\" );
683 break;
684
685 case 0x5D :
686 case 0x5E :
687 case 0x5F :
688 case 0x60 :
689 case 0x61 :
690 case 0x62 :
691 case 0x63 :
692 case 0x64 :
693 case 0x65 :
694 case 0x66 :
695 case 0x67 :
696 case 0x68 :
697 case 0x69 :
698 case 0x6A :
699 case 0x6B :
700 case 0x6C :
701 case 0x6D :
702 case 0x6E :
703 case 0x6F :
704 case 0x70 :
705 case 0x71 :
706 case 0x72 :
707 case 0x73 :
708 case 0x74 :
709 case 0x75 :
710 case 0x76 :
711 case 0x77 :
712 case 0x78 :
713 case 0x79 :
714 case 0x7A :
715 case 0x7B :
716 case 0x7C :
717 case 0x7D :
718 case 0x7E :
719 case 0x7F :
720 sb.append( ( char ) b );
721 break;
722
723
724 case ( byte ) 0x80 :
725 case ( byte ) 0x81 :
726 case ( byte ) 0x82 :
727 case ( byte ) 0x83 :
728 case ( byte ) 0x84 :
729 case ( byte ) 0x85 :
730 case ( byte ) 0x86 :
731 case ( byte ) 0x87 :
732 case ( byte ) 0x88 :
733 case ( byte ) 0x89 :
734 case ( byte ) 0x8A :
735 case ( byte ) 0x8B :
736 case ( byte ) 0x8C :
737 case ( byte ) 0x8D :
738 case ( byte ) 0x8E :
739 case ( byte ) 0x8F :
740 case ( byte ) 0x90 :
741 case ( byte ) 0x91 :
742 case ( byte ) 0x92 :
743 case ( byte ) 0x93 :
744 case ( byte ) 0x94 :
745 case ( byte ) 0x95 :
746 case ( byte ) 0x96 :
747 case ( byte ) 0x97 :
748 case ( byte ) 0x98 :
749 case ( byte ) 0x99 :
750 case ( byte ) 0x9A :
751 case ( byte ) 0x9B :
752 case ( byte ) 0x9C :
753 case ( byte ) 0x9D :
754 case ( byte ) 0x9E :
755 case ( byte ) 0x9F :
756 case ( byte ) 0xA0 :
757 case ( byte ) 0xA1 :
758 case ( byte ) 0xA2 :
759 case ( byte ) 0xA3 :
760 case ( byte ) 0xA4 :
761 case ( byte ) 0xA5 :
762 case ( byte ) 0xA6 :
763 case ( byte ) 0xA7 :
764 case ( byte ) 0xA8 :
765 case ( byte ) 0xA9 :
766 case ( byte ) 0xAA :
767 case ( byte ) 0xAB :
768 case ( byte ) 0xAC :
769 case ( byte ) 0xAD :
770 case ( byte ) 0xAE :
771 case ( byte ) 0xAF :
772 case ( byte ) 0xB0 :
773 case ( byte ) 0xB1 :
774 case ( byte ) 0xB2 :
775 case ( byte ) 0xB3 :
776 case ( byte ) 0xB4 :
777 case ( byte ) 0xB5 :
778 case ( byte ) 0xB6 :
779 case ( byte ) 0xB7 :
780 case ( byte ) 0xB8 :
781 case ( byte ) 0xB9 :
782 case ( byte ) 0xBA :
783 case ( byte ) 0xBB :
784 case ( byte ) 0xBC :
785 case ( byte ) 0xBD :
786 case ( byte ) 0xBE :
787 case ( byte ) 0xBF :
788 case ( byte ) 0xC0 :
789 case ( byte ) 0xC1 :
790 sb.append( '\\' ).append( Strings.byteToString( b ) );
791 break;
792
793
794 case ( byte ) 0xC2 :
795 case ( byte ) 0xC3 :
796 case ( byte ) 0xC4 :
797 case ( byte ) 0xC5 :
798 case ( byte ) 0xC6 :
799 case ( byte ) 0xC7 :
800 case ( byte ) 0xC8 :
801 case ( byte ) 0xC9 :
802 case ( byte ) 0xCA :
803 case ( byte ) 0xCB :
804 case ( byte ) 0xCC :
805 case ( byte ) 0xCD :
806 case ( byte ) 0xCE :
807 case ( byte ) 0xCF :
808 case ( byte ) 0xD0 :
809 case ( byte ) 0xD1 :
810 case ( byte ) 0xD2 :
811 case ( byte ) 0xD3 :
812 case ( byte ) 0xD4 :
813 case ( byte ) 0xD5 :
814 case ( byte ) 0xD6 :
815 case ( byte ) 0xD7 :
816 case ( byte ) 0xD8 :
817 case ( byte ) 0xD9 :
818 case ( byte ) 0xDA :
819 case ( byte ) 0xDB :
820 case ( byte ) 0xDC :
821 case ( byte ) 0xDD :
822 case ( byte ) 0xDE :
823 case ( byte ) 0xDF :
824
825 if ( trailChar )
826 {
827
828 sb.append( '\\' ).append( Strings.byteToString( b ) );
829 }
830 else
831 {
832 int b2 = bytes[pos + 1] & 0x00FF;
833
834 if ( ( b2 >= 0x0080 ) && ( b2 <= 0x00BF ) )
835 {
836
837 sb.append( Strings.utf8ToString( bytes, pos, 2 ) );
838 pos++;
839 }
840 else
841 {
842
843 sb.append( '\\' ).append( Strings.byteToString( b ) );
844 }
845 }
846
847 break;
848
849 case ( byte ) 0xE0 :
850
851 if ( trailChar )
852 {
853
854 sb.append( '\\' ).append( Strings.byteToString( b ) );
855 break;
856 }
857
858 if ( pos == bytes.length - 2 )
859 {
860
861 sb.append( '\\' ).append( Strings.byteToString( b ) );
862 }
863 else
864 {
865 int b2 = bytes[pos + 1] & 0x00FF;
866
867 if ( ( b2 >= 0x00A0 ) && ( b2 <= 0x00BF ) )
868 {
869 int b3 = bytes[pos + 2] & 0x00FF;
870
871
872 if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
873 {
874
875 sb.append( Strings.utf8ToString( bytes, pos, 3 ) );
876 pos += 2;
877 }
878 else
879 {
880
881 sb.append( '\\' ).append( Strings.byteToString( b ) );
882 }
883 }
884 else
885 {
886
887 sb.append( '\\' ).append( Strings.byteToString( b ) );
888 }
889 }
890
891 break;
892
893
894
895 case ( byte ) 0xE1 :
896 case ( byte ) 0xE2 :
897 case ( byte ) 0xE3 :
898 case ( byte ) 0xE4 :
899 case ( byte ) 0xE5 :
900 case ( byte ) 0xE6 :
901 case ( byte ) 0xE7 :
902 case ( byte ) 0xE8 :
903 case ( byte ) 0xE9 :
904 case ( byte ) 0xEA :
905 case ( byte ) 0xEB :
906 case ( byte ) 0xEC :
907 case ( byte ) 0xEE :
908 case ( byte ) 0xEF :
909 if ( trailChar )
910 {
911
912 sb.append( '\\' ).append( Strings.byteToString( b ) );
913 break;
914 }
915
916 if ( pos == bytes.length - 2 )
917 {
918
919 sb.append( '\\' ).append( Strings.byteToString( b ) );
920 }
921 else
922 {
923 int b2 = bytes[pos + 1] & 0x00FF;
924
925 if ( ( b2 >= 0x0080 ) && ( b2 <= 0x00BF ) )
926 {
927 int b3 = bytes[pos + 2] & 0x00FF;
928
929
930 if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
931 {
932
933 sb.append( Strings.utf8ToString( bytes, pos, 3 ) );
934 pos += 2;
935 }
936 else
937 {
938
939 sb.append( '\\' ).append( Strings.byteToString( b ) );
940 }
941 }
942 else
943 {
944
945 sb.append( '\\' ).append( Strings.byteToString( b ) );
946 pos++;
947 }
948 }
949
950 break;
951
952 case ( byte ) 0xED :
953
954 if ( trailChar )
955 {
956
957 sb.append( '\\' ).append( Strings.byteToString( b ) );
958 break;
959 }
960
961 if ( pos == bytes.length - 2 )
962 {
963
964 sb.append( '\\' ).append( Strings.byteToString( b ) );
965 }
966 else
967 {
968 int b2 = bytes[pos + 1] & 0x00FF;
969
970 if ( ( b2 >= 0x0080 ) && ( b2 <= 0x009F ) )
971 {
972 int b3 = bytes[pos + 2] & 0x00FF;
973
974
975 if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
976 {
977
978 sb.append( Strings.utf8ToString( bytes, pos, 3 ) );
979 pos += 2;
980 }
981 else
982 {
983
984 sb.append( '\\' ).append( Strings.byteToString( b ) );
985 }
986 }
987 else
988 {
989
990 sb.append( '\\' ).append( Strings.byteToString( b ) );
991 pos++;
992 }
993 }
994
995 break;
996
997 case ( byte ) 0xF0 :
998
999 if ( trailChar )
1000 {
1001
1002 sb.append( '\\' ).append( Strings.byteToString( b ) );
1003 break;
1004 }
1005
1006 if ( pos == bytes.length - 3 )
1007 {
1008
1009 sb.append( '\\' ).append( Strings.byteToString( b ) );
1010 }
1011 else
1012 {
1013 int b2 = bytes[pos + 1] & 0x00FF;
1014
1015 if ( ( b2 >= 0x0090 ) && ( b2 <= 0x00BF ) )
1016 {
1017 int b3 = bytes[pos + 2] & 0x00FF;
1018
1019
1020 if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
1021 {
1022 int b4 = bytes[pos + 3] & 0x00FF;
1023
1024
1025 if ( ( b4 >= 0x0080 ) && ( b4 <= 0x00BF ) )
1026 {
1027
1028 sb.append( Strings.utf8ToString( bytes, pos, 4 ) );
1029 pos += 3;
1030 }
1031 else
1032 {
1033
1034 sb.append( '\\' ).append( Strings.byteToString( b ) );
1035 }
1036 }
1037 else
1038 {
1039
1040 sb.append( '\\' ).append( Strings.byteToString( b ) );
1041 }
1042 }
1043 else
1044 {
1045
1046 sb.append( '\\' ).append( Strings.byteToString( b ) );
1047 pos++;
1048 }
1049 }
1050
1051 break;
1052
1053 case ( byte ) 0xF1 :
1054 case ( byte ) 0xF2 :
1055 case ( byte ) 0xF3 :
1056
1057
1058 if ( trailChar )
1059 {
1060
1061 sb.append( '\\' ).append( Strings.byteToString( b ) );
1062 break;
1063 }
1064
1065 if ( pos == bytes.length - 3 )
1066 {
1067
1068 sb.append( '\\' ).append( Strings.byteToString( b ) );
1069 }
1070 else
1071 {
1072 int b2 = bytes[pos + 1] & 0x00FF;
1073
1074 if ( ( b2 >= 0x0080 ) && ( b2 <= 0x00BF ) )
1075 {
1076 int b3 = bytes[pos + 2] & 0x00FF;
1077
1078
1079 if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
1080 {
1081 int b4 = bytes[pos + 3] & 0x00FF;
1082
1083
1084 if ( ( b4 >= 0x0080 ) && ( b4 <= 0x00BF ) )
1085 {
1086
1087 sb.append( Strings.utf8ToString( bytes, pos, 4 ) );
1088 pos += 3;
1089 }
1090 else
1091 {
1092
1093 sb.append( '\\' ).append( Strings.byteToString( b ) );
1094 }
1095 }
1096 else
1097 {
1098
1099 sb.append( '\\' ).append( Strings.byteToString( b ) );
1100 }
1101 }
1102 else
1103 {
1104
1105 sb.append( '\\' ).append( Strings.byteToString( b ) );
1106 pos++;
1107 }
1108 }
1109
1110 break;
1111
1112 case ( byte ) 0xF4 :
1113
1114 if ( trailChar )
1115 {
1116
1117 sb.append( '\\' ).append( Strings.byteToString( b ) );
1118 break;
1119 }
1120
1121 if ( pos == bytes.length - 3 )
1122 {
1123
1124 sb.append( '\\' ).append( Strings.byteToString( b ) );
1125 }
1126 else
1127 {
1128 int b2 = bytes[pos + 1] & 0x00FF;
1129
1130 if ( ( b2 >= 0x0080 ) && ( b2 <= 0x008F ) )
1131 {
1132 int b3 = bytes[pos + 2] & 0x00FF;
1133
1134
1135 if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
1136 {
1137 int b4 = bytes[pos + 3] & 0x00FF;
1138
1139
1140 if ( ( b4 >= 0x0080 ) && ( b4 <= 0x00BF ) )
1141 {
1142
1143 sb.append( Strings.utf8ToString( bytes, pos, 4 ) );
1144 pos += 3;
1145 }
1146 else
1147 {
1148
1149 sb.append( '\\' ).append( Strings.byteToString( b ) );
1150 }
1151 }
1152 else
1153 {
1154
1155 sb.append( '\\' ).append( Strings.byteToString( b ) );
1156 }
1157 }
1158 else
1159 {
1160
1161 sb.append( '\\' ).append( Strings.byteToString( b ) );
1162 pos++;
1163 }
1164 }
1165
1166 break;
1167
1168
1169 default :
1170
1171 sb.append( '\\' ).append( Strings.byteToString( b ) );
1172
1173 break;
1174
1175 }
1176
1177 if ( leadChar )
1178 {
1179 leadChar = false;
1180 }
1181 }
1182
1183 return sb.toString();
1184 }
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 public String getString()
1195 {
1196 if ( isHR )
1197 {
1198 return upValue;
1199 }
1200 else
1201 {
1202 return Strings.utf8ToString( bytes );
1203 }
1204 }
1205
1206
1207
1208
1209
1210
1211
1212 private void computeNormValue() throws LdapException
1213 {
1214 if ( upValue == null )
1215 {
1216 return;
1217 }
1218
1219 Normalizer normalizer;
1220
1221
1222 MatchingRule equality = attributeType.getEquality();
1223
1224 if ( equality == null )
1225 {
1226
1227 MatchingRule subString = attributeType.getSubstring();
1228
1229 if ( subString == null )
1230 {
1231
1232 MatchingRule ordering = attributeType.getOrdering();
1233
1234 if ( ordering == null )
1235 {
1236
1237 normalizer = new NoOpNormalizer();
1238 }
1239 else
1240 {
1241 normalizer = ordering.getNormalizer();
1242 }
1243 }
1244 else
1245 {
1246 normalizer = subString.getNormalizer();
1247 }
1248 }
1249 else
1250 {
1251 normalizer = equality.getNormalizer();
1252 }
1253
1254 if ( normalizer == null )
1255 {
1256 throw new IllegalArgumentException( I18n.err( I18n.ERR_13220_NO_NORMALIZER ) );
1257 }
1258
1259
1260 normValue = normalizer.normalize( upValue );
1261 }
1262
1263
1264
1265
1266
1267 public String getNormalized()
1268 {
1269 return normValue;
1270 }
1271
1272
1273
1274
1275
1276 public String getUpValue()
1277 {
1278 if ( isHR )
1279 {
1280 return upValue;
1281 }
1282 else
1283 {
1284 return getEscaped();
1285 }
1286 }
1287
1288
1289
1290
1291
1292
1293
1294
1295 public byte[] getBytes()
1296 {
1297 if ( bytes == null )
1298 {
1299 return null;
1300 }
1301
1302 if ( bytes.length == 0 )
1303 {
1304 return Strings.EMPTY_BYTES;
1305 }
1306
1307 byte[] copy = new byte[bytes.length];
1308 System.arraycopy( bytes, 0, copy, 0, bytes.length );
1309
1310 return copy;
1311 }
1312
1313
1314
1315
1316
1317
1318
1319 public boolean isSchemaAware()
1320 {
1321 return attributeType != null;
1322 }
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333 public final boolean isValid( SyntaxChecker syntaxChecker ) throws LdapInvalidAttributeValueException
1334 {
1335 if ( syntaxChecker == null )
1336 {
1337 String message = I18n.err( I18n.ERR_13219_NULL_SYNTAX_CHECKER, toString() );
1338 LOG.error( message );
1339 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message );
1340 }
1341
1342
1343 if ( isHR )
1344 {
1345
1346 return syntaxChecker.isValidSyntax( getString() );
1347 }
1348 else
1349 {
1350 return syntaxChecker.isValidSyntax( bytes );
1351 }
1352 }
1353
1354
1355
1356
1357
1358
1359
1360 public boolean isHumanReadable()
1361 {
1362 return isHR;
1363 }
1364
1365
1366
1367
1368
1369 public int length()
1370 {
1371 if ( isHR )
1372 {
1373 return upValue != null ? upValue.length() : 0;
1374 }
1375 else
1376 {
1377 return bytes != null ? bytes.length : 0;
1378 }
1379 }
1380
1381
1382
1383
1384
1385
1386
1387
1388 private LdapComparator<?> getLdapComparator()
1389 {
1390 if ( attributeType != null )
1391 {
1392 MatchingRule mr = attributeType.getEquality();
1393
1394 if ( mr != null )
1395 {
1396 return mr.getLdapComparator();
1397 }
1398 }
1399
1400 return null;
1401 }
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411 public int serialize( byte[] buffer, int pos )
1412 {
1413
1414 int length = 1;
1415 byte[] preparedBytes = null;
1416
1417 if ( isHR )
1418 {
1419 if ( upValue != null )
1420 {
1421
1422 length += 1 + 4 + bytes.length;
1423 }
1424
1425 if ( normValue != null )
1426 {
1427
1428 preparedBytes = Strings.getBytesUtf8( normValue );
1429 length += 1 + 4 + preparedBytes.length;
1430 }
1431 }
1432 else
1433 {
1434 if ( bytes != null )
1435 {
1436 length = 1 + 1 + 4 + bytes.length;
1437 }
1438 else
1439 {
1440 length = 1 + 1;
1441 }
1442 }
1443
1444
1445 if ( buffer.length - pos < length )
1446 {
1447 throw new ArrayIndexOutOfBoundsException();
1448 }
1449
1450 if ( isHR )
1451 {
1452 buffer[pos++] = Serialize.TRUE;
1453
1454
1455 if ( bytes != null )
1456 {
1457 buffer[pos++] = Serialize.TRUE;
1458 pos = Serialize.serialize( bytes, buffer, pos );
1459 }
1460 else
1461 {
1462 buffer[pos++] = Serialize.FALSE;
1463 }
1464
1465
1466 if ( normValue != null )
1467 {
1468 buffer[pos++] = Serialize.TRUE;
1469 pos = Serialize.serialize( preparedBytes, buffer, pos );
1470 }
1471 else
1472 {
1473 buffer[pos++] = Serialize.FALSE;
1474 }
1475 }
1476 else
1477 {
1478 buffer[pos++] = Serialize.FALSE;
1479
1480 if ( bytes != null )
1481 {
1482 buffer[pos++] = Serialize.TRUE;
1483 pos = Serialize.serialize( bytes, buffer, pos );
1484 }
1485 else
1486 {
1487 buffer[pos++] = Serialize.FALSE;
1488 }
1489 }
1490
1491 return pos;
1492 }
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503 public static Value deserialize( ObjectInput in ) throws IOException, ClassNotFoundException
1504 {
1505 Value value = new Value( ( AttributeType ) null );
1506 value.readExternal( in );
1507
1508 return value;
1509 }
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521 public static Value deserialize( AttributeType attributeType, ObjectInput in ) throws IOException, ClassNotFoundException
1522 {
1523 Value value = new Value( attributeType );
1524 value.readExternal( in );
1525
1526 return value;
1527 }
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539 public int deserialize( byte[] buffer, int pos ) throws IOException, LdapInvalidAttributeValueException
1540 {
1541 if ( ( pos < 0 ) || ( pos >= buffer.length ) )
1542 {
1543 throw new ArrayIndexOutOfBoundsException();
1544 }
1545
1546
1547 isHR = Serialize.deserializeBoolean( buffer, pos );
1548 pos++;
1549
1550 if ( isHR )
1551 {
1552
1553 boolean hasValue = Serialize.deserializeBoolean( buffer, pos );
1554 pos++;
1555
1556 if ( hasValue )
1557 {
1558 bytes = Serialize.deserializeBytes( buffer, pos );
1559 pos += 4 + bytes.length;
1560
1561 upValue = Strings.utf8ToString( bytes );
1562 }
1563
1564
1565 boolean hasPreparedValue = Serialize.deserializeBoolean( buffer, pos );
1566 pos++;
1567
1568 if ( hasPreparedValue )
1569 {
1570 byte[] preparedBytes = Serialize.deserializeBytes( buffer, pos );
1571 pos += 4 + preparedBytes.length;
1572 normValue = Strings.utf8ToString( preparedBytes );
1573 }
1574 }
1575 else
1576 {
1577
1578 boolean hasBytes = Serialize.deserializeBoolean( buffer, pos );
1579 pos++;
1580
1581 if ( hasBytes )
1582 {
1583 bytes = Serialize.deserializeBytes( buffer, pos );
1584 pos += 4 + bytes.length;
1585 }
1586
1587 }
1588
1589 if ( attributeType != null )
1590 {
1591 try
1592 {
1593 computeNormValue();
1594 }
1595 catch ( LdapException le )
1596 {
1597 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, le.getMessage() );
1598 }
1599 }
1600
1601 hashCode();
1602
1603 return pos;
1604 }
1605
1606
1607
1608
1609
1610 @Override
1611 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
1612 {
1613
1614 isHR = in.readBoolean();
1615
1616 if ( isHR )
1617 {
1618
1619 if ( in.readBoolean() )
1620 {
1621 int length = in.readInt();
1622 bytes = new byte[length];
1623
1624 if ( length != 0 )
1625 {
1626 in.readFully( bytes );
1627 }
1628
1629 upValue = Strings.utf8ToString( bytes );
1630 }
1631
1632
1633 if ( in.readBoolean() )
1634 {
1635 normValue = in.readUTF();
1636 }
1637 }
1638 else
1639 {
1640 if ( in.readBoolean() )
1641 {
1642 int length = in.readInt();
1643 bytes = new byte[length];
1644
1645 if ( length != 0 )
1646 {
1647 in.readFully( bytes );
1648 }
1649 }
1650 }
1651
1652 hashCode();
1653 }
1654
1655
1656
1657
1658
1659 @Override
1660 public void writeExternal( ObjectOutput out ) throws IOException
1661 {
1662
1663 out.writeBoolean( isHR );
1664
1665 if ( isHR )
1666 {
1667
1668 out.writeBoolean( upValue != null );
1669
1670 if ( upValue != null )
1671 {
1672
1673 out.writeInt( bytes.length );
1674
1675 if ( bytes.length > 0 )
1676 {
1677 out.write( bytes );
1678 }
1679 }
1680
1681
1682 out.writeBoolean( normValue != null );
1683
1684 if ( normValue != null )
1685 {
1686
1687 out.writeUTF( normValue );
1688 }
1689 }
1690 else
1691 {
1692
1693 out.writeBoolean( bytes != null );
1694
1695 if ( bytes != null )
1696 {
1697 out.writeInt( bytes.length );
1698
1699 if ( bytes.length > 0 )
1700 {
1701 out.write( bytes );
1702 }
1703 }
1704 }
1705
1706
1707 out.flush();
1708 }
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720 public int compareTo( String other )
1721 {
1722 if ( !isHR )
1723 {
1724 String msg = I18n.err( I18n.ERR_13224_FAILED_TO_COMPARE_NORM_VALUES, this, other );
1725 LOG.error( msg );
1726 throw new IllegalStateException( msg );
1727 }
1728
1729
1730 if ( bytes == null )
1731 {
1732 if ( other == null )
1733 {
1734 return 0;
1735 }
1736 else
1737 {
1738 return -1;
1739 }
1740 }
1741 else if ( other == null )
1742 {
1743 return 1;
1744 }
1745
1746
1747
1748
1749 try
1750 {
1751 if ( attributeType != null )
1752 {
1753
1754
1755 String normalizedOther = attributeType.getEquality().getNormalizer().normalize( other );
1756
1757 return normValue.compareTo( normalizedOther );
1758 }
1759 else
1760 {
1761
1762 return normValue.compareTo( other );
1763 }
1764 }
1765 catch ( LdapException le )
1766 {
1767 return -1;
1768 }
1769 }
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781 public int compareTo( byte[] other )
1782 {
1783 if ( isHR )
1784 {
1785 String msg = I18n.err( I18n.ERR_13224_FAILED_TO_COMPARE_NORM_VALUES, this, other );
1786 LOG.error( msg );
1787 throw new IllegalStateException( msg );
1788 }
1789
1790
1791 if ( bytes == null )
1792 {
1793 if ( other == null )
1794 {
1795 return 0;
1796 }
1797 else
1798 {
1799 return -1;
1800 }
1801 }
1802 else if ( other == null )
1803 {
1804 return 1;
1805 }
1806
1807
1808 return Strings.compare( bytes, other );
1809 }
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822 @Override
1823 public int compareTo( Value other )
1824 {
1825
1826 if ( isHR != other.isHR )
1827 {
1828 String msg = I18n.err( I18n.ERR_13224_FAILED_TO_COMPARE_NORM_VALUES, this, other );
1829 LOG.error( msg );
1830 throw new IllegalStateException( msg );
1831 }
1832
1833
1834 if ( bytes == null )
1835 {
1836 if ( other.bytes == null )
1837 {
1838 return 0;
1839 }
1840 else
1841 {
1842 return -1;
1843 }
1844 }
1845 else if ( other.bytes == null )
1846 {
1847 return 1;
1848 }
1849
1850
1851
1852
1853 if ( !isHR )
1854 {
1855 return Strings.compare( bytes, other.bytes );
1856 }
1857
1858
1859
1860
1861 try
1862 {
1863 if ( attributeType != null )
1864 {
1865
1866 if ( other.attributeType == null )
1867 {
1868
1869
1870 String normalizedOther = attributeType.getEquality().getNormalizer().normalize( other.upValue );
1871
1872 return normValue.compareTo( normalizedOther );
1873 }
1874 else
1875 {
1876 return normValue.compareTo( other.normValue );
1877 }
1878 }
1879 else
1880 {
1881 if ( other.attributeType != null )
1882 {
1883
1884 String normalizedThis = other.attributeType.getEquality().getNormalizer().normalize( upValue );
1885
1886 return normalizedThis.compareTo( other.normValue );
1887 }
1888 else
1889 {
1890
1891 return normValue.compareTo( other.normValue );
1892 }
1893 }
1894 }
1895 catch ( LdapException le )
1896 {
1897 return -1;
1898 }
1899 }
1900
1901
1902
1903
1904
1905
1906
1907 @Override
1908 public boolean equals( Object obj )
1909 {
1910 if ( this == obj )
1911 {
1912 return true;
1913 }
1914
1915 if ( obj instanceof String )
1916 {
1917 String other = ( String ) obj;
1918
1919 if ( !isHR )
1920 {
1921 return false;
1922 }
1923
1924 if ( attributeType == null )
1925 {
1926 if ( upValue != null )
1927 {
1928 return upValue.equals( other );
1929 }
1930 else
1931 {
1932 return obj == null;
1933 }
1934 }
1935 else
1936 {
1937
1938
1939 try
1940 {
1941 LdapComparator<String> comparator = ( LdapComparator<String> ) getLdapComparator();
1942
1943 Normalizer normalizer = null;
1944
1945 if ( attributeType.getEquality() != null )
1946 {
1947 normalizer = attributeType.getEquality().getNormalizer();
1948 }
1949
1950 if ( normalizer == null )
1951 {
1952 if ( comparator == null )
1953 {
1954 return normValue.equals( other );
1955 }
1956 else
1957 {
1958 return comparator.compare( normValue, other ) == 0;
1959 }
1960 }
1961
1962 String thisNormValue = normValue;
1963 String otherNormValue = normalizer.normalize( other );
1964
1965
1966 if ( comparator == null )
1967 {
1968 return thisNormValue.equals( otherNormValue );
1969 }
1970 else
1971 {
1972 return comparator.compare( thisNormValue, otherNormValue ) == 0;
1973 }
1974 }
1975 catch ( LdapException ne )
1976 {
1977 return false;
1978 }
1979 }
1980 }
1981
1982 if ( !( obj instanceof Value ) )
1983 {
1984 return false;
1985 }
1986
1987 Value other = ( Value ) obj;
1988
1989
1990 if ( isHR != other.isHR )
1991 {
1992
1993 return false;
1994 }
1995
1996 if ( !isHR )
1997 {
1998
1999 return Arrays.equals( bytes, other.bytes );
2000 }
2001
2002
2003 if ( bytes == null )
2004 {
2005 return other.bytes == null;
2006 }
2007
2008
2009 if ( other.bytes == null )
2010 {
2011 return false;
2012 }
2013
2014
2015 if ( bytes.length == 0 )
2016 {
2017 return other.bytes.length == 0;
2018 }
2019 else if ( other.bytes.length == 0 )
2020 {
2021 return false;
2022 }
2023
2024
2025
2026
2027 MatchingRule equalityMR;
2028
2029 if ( attributeType == null )
2030 {
2031 if ( other.attributeType != null )
2032 {
2033
2034 equalityMR = other.attributeType.getEquality();
2035
2036
2037 if ( equalityMR == null )
2038 {
2039 return Arrays.equals( bytes, other.bytes );
2040 }
2041
2042 LdapComparator<Object> ldapComparator = equalityMR.getLdapComparator();
2043
2044 if ( ldapComparator == null )
2045 {
2046
2047 LOG.error( I18n.err( I18n.ERR_13249_NO_COMPARATOR_FOR_AT, other.attributeType ) );
2048
2049 return false;
2050 }
2051
2052 return ldapComparator.compare( normValue, other.normValue ) == 0;
2053 }
2054 else
2055 {
2056
2057
2058 if ( upValue != null )
2059 {
2060 return upValue.equals( other.upValue );
2061 }
2062 else
2063 {
2064 return Arrays.equals( bytes, other.bytes );
2065 }
2066 }
2067 }
2068 else
2069 {
2070 if ( other.attributeType != null )
2071 {
2072
2073 if ( !attributeType.equals( other.attributeType ) )
2074 {
2075 return false;
2076 }
2077
2078
2079
2080 LdapComparator<String> comparator = ( LdapComparator<String> ) getLdapComparator();
2081
2082 if ( other.attributeType.getEquality() == null )
2083 {
2084
2085 return stringComparator.compare( normValue, other.normValue ) == 0;
2086 }
2087
2088
2089
2090 if ( comparator == null )
2091 {
2092 return normValue.equals( other.normValue );
2093 }
2094 else
2095 {
2096 return comparator.compare( normValue, other.normValue ) == 0;
2097 }
2098 }
2099
2100
2101 if ( normValue == null )
2102 {
2103 return other.normValue == null;
2104 }
2105 else
2106 {
2107 return normValue.equals( other.normValue );
2108 }
2109 }
2110 }
2111
2112
2113
2114
2115
2116
2117 @Override
2118 public int hashCode()
2119 {
2120 if ( h == 0 )
2121 {
2122
2123
2124 if ( isHR )
2125 {
2126 if ( normValue != null )
2127 {
2128 h = normValue.hashCode();
2129 }
2130 else
2131 {
2132 h = 0;
2133 }
2134 }
2135 else
2136 {
2137 h = Arrays.hashCode( bytes );
2138 }
2139 }
2140
2141 return h;
2142 }
2143
2144
2145
2146
2147
2148 @Override
2149 public String toString()
2150 {
2151 if ( isHR )
2152 {
2153 return upValue == null ? "null" : upValue;
2154 }
2155 else
2156 {
2157
2158 if ( bytes == null )
2159 {
2160 return "null";
2161 }
2162 else if ( bytes.length > 16 )
2163 {
2164
2165 byte[] copy = new byte[16];
2166
2167 System.arraycopy( bytes, 0, copy, 0, 16 );
2168
2169 return Strings.dumpBytes( copy ) + "...";
2170 }
2171 else
2172 {
2173 return Strings.dumpBytes( bytes );
2174 }
2175 }
2176 }
2177 }