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.schema.parsers;
21
22
23 import java.io.BufferedReader;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.Reader;
29 import java.io.StringReader;
30 import java.nio.charset.Charset;
31 import java.nio.file.Files;
32 import java.nio.file.Paths;
33 import java.text.ParseException;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38
39 import org.apache.directory.api.asn1.util.Oid;
40 import org.apache.directory.api.i18n.I18n;
41 import org.apache.directory.api.ldap.model.exception.LdapSchemaException;
42 import org.apache.directory.api.ldap.model.schema.AttributeType;
43 import org.apache.directory.api.ldap.model.schema.DitContentRule;
44 import org.apache.directory.api.ldap.model.schema.DitStructureRule;
45 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
46 import org.apache.directory.api.ldap.model.schema.MatchingRule;
47 import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
48 import org.apache.directory.api.ldap.model.schema.ObjectClass;
49 import org.apache.directory.api.ldap.model.schema.NameForm;
50 import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum;
51 import org.apache.directory.api.ldap.model.schema.SchemaObject;
52 import org.apache.directory.api.ldap.model.schema.UsageEnum;
53 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.OpenLdapObjectIdentifierMacro;
54 import org.apache.directory.api.util.Strings;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58
59
60
61
62
63 public class OpenLdapSchemaParser
64 {
65
66 protected static final Logger LOG = LoggerFactory.getLogger( OpenLdapSchemaParser.class );
67
68
69 private boolean isQuirksModeEnabled = false;
70
71
72 protected int lineNumber;
73
74
75 private List<Object> schemaDescriptions = new ArrayList<>();
76
77
78 private List<AttributeType> attributeTypes;
79
80
81 private List<ObjectClass> objectClasses;
82
83
84 private Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros = new HashMap<>();
85
86
87 private static final String APPLIES_STR = "APPLIES";
88 private static final String ABSTRACT_STR = "ABSTRACT";
89 private static final String AUX_STR = "AUX";
90 private static final String AUXILIARY_STR = "AUXILIARY";
91 private static final String BYTECODE_STR = "BYTECODE";
92 private static final String COLLECTIVE_STR = "COLLECTIVE";
93 private static final String DESC_STR = "DESC";
94 private static final String EQUALITY_STR = "EQUALITY";
95 private static final String FORM_STR = "FORM";
96 private static final String FQCN_STR = "FQCN";
97 private static final String MAY_STR = "MAY";
98 private static final String MUST_STR = "MUST";
99 private static final String NAME_STR = "NAME";
100 private static final String NO_USER_MODIFICATION_STR = "NO-USER-MODIFICATION";
101 private static final String NOT_STR = "NOT";
102 private static final String OBSOLETE_STR = "OBSOLETE";
103 private static final String OC_STR = "OC";
104 private static final String ORDERING_STR = "ORDERING";
105 private static final String SINGLE_VALUE_STR = "SINGLE-VALUE";
106 private static final String STRUCTURAL_STR = "STRUCTURAL";
107 private static final String SUBSTR_STR = "SUBSTR";
108 private static final String SUP_STR = "SUP";
109 private static final String SYNTAX_STR = "SYNTAX";
110 private static final String USAGE_STR = "USAGE";
111 private static final String EXTENSION_PREFIX = "X-";
112
113
114 private static final String DIRECTORY_OPERATION_STR = "directoryOperation";
115 private static final String DISTRIBUTED_OPERATION_STR = "distributedOperation";
116 private static final String DSA_OPERATION_STR = "dSAOperation";
117 private static final String USER_APPLICATIONS_STR = "userApplications";
118
119
120 private static final char COLON = ':';
121 private static final char DOLLAR = '$';
122 private static final char DOT = '.';
123 private static final char EQUAL = '=';
124 private static final char ESCAPE = '\\';
125 private static final char HYPHEN = '-';
126 private static final char LBRACE = '{';
127 private static final char LPAREN = '(';
128 private static final char PLUS = '+';
129 private static final char RBRACE = '}';
130 private static final char RPAREN = ')';
131 private static final char SEMI_COLON = ';';
132 private static final char SHARP = '#';
133 private static final char SLASH = '/';
134 private static final char SQUOTE = '\'';
135 private static final char UNDERSCORE = '_';
136 private static final char DQUOTE = '"';
137
138
139
140 private boolean isResolveObjectIdentifierMacros;
141
142 private static final boolean UN_QUOTED = false;
143
144
145 private static final boolean STRICT = false;
146 private static final boolean RELAXED = true;
147
148 private class PosSchema
149 {
150
151 int lineNumber;
152
153
154 int start;
155
156
157 String line;
158
159
160
161
162 @Override
163 public String toString()
164 {
165 if ( line == null )
166 {
167 return "null";
168 }
169 else if ( line.length() < start )
170 {
171 return "EOL";
172 }
173 else
174 {
175 return line.substring( start );
176 }
177 }
178 }
179
180
181 private interface SchemaObjectElements
182 {
183 int getValue();
184 }
185
186
187
188
189
190 private enum AttributeTypeElements implements SchemaObjectElements
191 {
192 NAME(1),
193 DESC(2),
194 OBSOLETE(4),
195 SUP(8),
196 EQUALITY(16),
197 ORDERING(32),
198 SUBSTR(64),
199 SYNTAX(128),
200 SINGLE_VALUE(256),
201 COLLECTIVE(512),
202 NO_USER_MODIFICATION(1024),
203 USAGE(2048);
204
205 private int value;
206
207 AttributeTypeElements( int value )
208 {
209 this.value = value;
210 }
211
212
213 public int getValue()
214 {
215 return value;
216 }
217 }
218
219
220
221
222
223 private enum DitContentRuleElements implements SchemaObjectElements
224 {
225 NAME(1),
226 DESC(2),
227 OBSOLETE(4),
228 AUX(8),
229 MUST(16),
230 MAY(32),
231 NOT(64);
232
233 private int value;
234
235 DitContentRuleElements( int value )
236 {
237 this.value = value;
238 }
239
240
241 public int getValue()
242 {
243 return value;
244 }
245 }
246
247
248
249
250
251 private enum DitStructureRuleElements implements SchemaObjectElements
252 {
253 NAME(1),
254 DESC(2),
255 OBSOLETE(4),
256 FORM(8),
257 SUP(16);
258
259 private int value;
260
261 DitStructureRuleElements( int value )
262 {
263 this.value = value;
264 }
265
266
267 public int getValue()
268 {
269 return value;
270 }
271 }
272
273
274
275
276
277 private enum LdapComparatorElements implements SchemaObjectElements
278 {
279 DESC(1),
280 FQCN(2),
281 BYTECODE(4);
282
283 private int value;
284
285 LdapComparatorElements( int value )
286 {
287 this.value = value;
288 }
289
290
291 public int getValue()
292 {
293 return value;
294 }
295 }
296
297
298
299
300
301 private enum LdapSyntaxElements implements SchemaObjectElements
302 {
303 DESC(1);
304
305 private int value;
306
307 LdapSyntaxElements( int value )
308 {
309 this.value = value;
310 }
311
312
313 public int getValue()
314 {
315 return value;
316 }
317 }
318
319
320
321
322
323 private enum MatchingRuleElements implements SchemaObjectElements
324 {
325 NAME(1),
326 DESC(2),
327 OBSOLETE(4),
328 SYNTAX(8);
329
330 private int value;
331
332 MatchingRuleElements( int value )
333 {
334 this.value = value;
335 }
336
337
338 public int getValue()
339 {
340 return value;
341 }
342 }
343
344
345
346
347
348 private enum MatchingRuleUseElements implements SchemaObjectElements
349 {
350 NAME(1),
351 DESC(2),
352 OBSOLETE(4),
353 APPLIES(8);
354
355 private int value;
356
357 MatchingRuleUseElements( int value )
358 {
359 this.value = value;
360 }
361
362
363 public int getValue()
364 {
365 return value;
366 }
367 }
368
369
370
371
372
373 private enum NameFormElements implements SchemaObjectElements
374 {
375 NAME(1),
376 DESC(2),
377 OBSOLETE(4),
378 OC(8),
379 MUST(16),
380 MAY(32);
381
382 private int value;
383
384 NameFormElements( int value )
385 {
386 this.value = value;
387 }
388
389
390 public int getValue()
391 {
392 return value;
393 }
394 }
395
396
397
398
399
400 private enum NormalizerElements implements SchemaObjectElements
401 {
402 DESC(1),
403 FQCN(2),
404 BYTECODE(4);
405
406 private int value;
407
408 NormalizerElements( int value )
409 {
410 this.value = value;
411 }
412
413
414 public int getValue()
415 {
416 return value;
417 }
418 }
419
420
421
422
423
424 private enum ObjectClassElements implements SchemaObjectElements
425 {
426 NAME(1),
427 DESC(2),
428 OBSOLETE(4),
429 SUP(8),
430 MUST(16),
431 MAY(32),
432 ABSTRACT(64),
433 STRUCTURAL(64),
434 AUXILIARY(64);
435
436 private int value;
437
438 ObjectClassElements( int value )
439 {
440 this.value = value;
441 }
442
443
444 public int getValue()
445 {
446 return value;
447 }
448 }
449
450
451
452
453
454 private enum SyntaxCheckerElements implements SchemaObjectElements
455 {
456 DESC(1),
457 FQCN(2),
458 BYTECODE(4);
459
460 private int value;
461
462 SyntaxCheckerElements( int value )
463 {
464 this.value = value;
465 }
466
467
468 public int getValue()
469 {
470 return value;
471 }
472 }
473
474
475
476
477
478 public OpenLdapSchemaParser()
479 {
480 isResolveObjectIdentifierMacros = true;
481 isQuirksModeEnabled = false;
482 }
483
484
485
486
487
488 public void clear()
489 {
490 if ( attributeTypes != null )
491 {
492 attributeTypes.clear();
493 }
494
495 if ( objectClasses != null )
496 {
497 objectClasses.clear();
498 }
499
500 if ( schemaDescriptions != null )
501 {
502 schemaDescriptions.clear();
503 }
504
505 if ( objectIdentifierMacros != null )
506 {
507 objectIdentifierMacros.clear();
508 }
509 }
510
511
512
513
514
515
516
517 public List<AttributeType> getAttributeTypes()
518 {
519 return attributeTypes;
520 }
521
522
523
524
525
526
527
528 public List<ObjectClass> getObjectClasses()
529 {
530 return objectClasses;
531 }
532
533
534
535
536
537
538
539 public Map<String, OpenLdapObjectIdentifierMacro> getObjectIdentifierMacros()
540 {
541 return objectIdentifierMacros;
542 }
543
544
545
546
547
548
549
550
551 private void afterParse() throws ParseException
552 {
553 objectClasses = new ArrayList<>();
554 attributeTypes = new ArrayList<>();
555
556
557 for ( Object obj : schemaDescriptions )
558 {
559 if ( obj instanceof OpenLdapObjectIdentifierMacro )
560 {
561 OpenLdapObjectIdentifierMacro oid = ( OpenLdapObjectIdentifierMacro ) obj;
562 objectIdentifierMacros.put( oid.getName(), oid );
563 }
564 else if ( obj instanceof AttributeType )
565 {
566 AttributeType attributeType = ( AttributeType ) obj;
567
568 attributeTypes.add( attributeType );
569 }
570 else if ( obj instanceof ObjectClass )
571 {
572 ObjectClass objectClass = ( ObjectClass ) obj;
573
574 objectClasses.add( objectClass );
575 }
576 }
577
578 if ( isResolveObjectIdentifierMacros() )
579 {
580
581 for ( OpenLdapObjectIdentifierMacro oid : objectIdentifierMacros.values() )
582 {
583 resolveObjectIdentifierMacro( oid );
584 }
585
586
587 for ( ObjectClass objectClass : objectClasses )
588 {
589 objectClass.setOid( getResolveOid( objectClass.getOid() ) );
590 }
591
592
593 for ( AttributeType attributeType : attributeTypes )
594 {
595 attributeType.setOid( getResolveOid( attributeType.getOid() ) );
596 attributeType.setSyntaxOid( getResolveOid( attributeType.getSyntaxOid() ) );
597 }
598
599 }
600 }
601
602
603
604
605
606
607
608
609 private String getResolveOid( String oid )
610 {
611 if ( oid != null && oid.indexOf( COLON ) != -1 )
612 {
613
614 String[] nameAndSuffix = oid.split( ":" );
615
616 if ( objectIdentifierMacros.containsKey( nameAndSuffix[0] ) )
617 {
618 OpenLdapObjectIdentifierMacro macro = objectIdentifierMacros.get( nameAndSuffix[0] );
619
620 return macro.getResolvedOid() + "." + nameAndSuffix[1];
621 }
622 }
623
624 return oid;
625 }
626
627
628
629
630
631
632
633
634 private void resolveObjectIdentifierMacro( OpenLdapObjectIdentifierMacro macro ) throws ParseException
635 {
636 String rawOidOrNameSuffix = macro.getRawOidOrNameSuffix();
637
638 if ( !macro.isResolved() )
639 {
640 if ( rawOidOrNameSuffix.indexOf( COLON ) != -1 )
641 {
642
643 String[] nameAndSuffix = rawOidOrNameSuffix.split( ":" );
644
645 if ( objectIdentifierMacros.containsKey( nameAndSuffix[0] ) )
646 {
647 OpenLdapObjectIdentifierMacro parentMacro = objectIdentifierMacros.get( nameAndSuffix[0] );
648 resolveObjectIdentifierMacro( parentMacro );
649 macro.setResolvedOid( parentMacro.getResolvedOid() + "." + nameAndSuffix[1] );
650 }
651 else
652 {
653 throw new ParseException( I18n.err( I18n.ERR_13726_NO_OBJECT_IDENTIFIER_MACRO, nameAndSuffix[0] ), 0 );
654 }
655 }
656 else
657 {
658
659 if ( objectIdentifierMacros.containsKey( rawOidOrNameSuffix ) )
660 {
661 OpenLdapObjectIdentifierMacro parentMacro = objectIdentifierMacros.get( rawOidOrNameSuffix );
662 resolveObjectIdentifierMacro( parentMacro );
663 macro.setResolvedOid( parentMacro.getResolvedOid() );
664 }
665 else
666 {
667 macro.setResolvedOid( rawOidOrNameSuffix );
668 }
669 }
670 }
671 }
672
673
674
675
676
677
678
679
680
681 public SchemaObject parse( String schemaObject ) throws ParseException
682 {
683 if ( ( schemaObject == null ) || Strings.isEmpty( schemaObject.trim() ) )
684 {
685 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
686 }
687
688 try ( Reader reader = new BufferedReader( new StringReader( schemaObject ) ) )
689 {
690 parse( reader );
691 afterParse();
692 }
693 catch ( IOException | LdapSchemaException e )
694 {
695 throw new ParseException( e.getMessage(), 0 );
696 }
697
698 if ( !schemaDescriptions.isEmpty() )
699 {
700 for ( Object obj : schemaDescriptions )
701 {
702 if ( obj instanceof SchemaObject )
703 {
704 return ( SchemaObject ) obj;
705 }
706 }
707 }
708
709 return null;
710 }
711
712
713
714
715
716
717
718
719
720
721 public void parse( InputStream schemaIn ) throws ParseException, LdapSchemaException, IOException
722 {
723 try ( InputStreamReader in = new InputStreamReader( schemaIn, Charset.defaultCharset() ) )
724 {
725 try ( Reader reader = new BufferedReader( in ) )
726 {
727 parse( reader );
728 afterParse();
729 }
730 }
731 }
732
733
734
735
736
737
738
739
740
741
742 private static void skipWhites( Reader reader, PosSchema pos, boolean mandatory ) throws IOException, LdapSchemaException
743 {
744 boolean hasSpace = false;
745
746 while ( true )
747 {
748 if ( isEmpty( pos ) )
749 {
750 getLine( reader, pos );
751
752 if ( pos.line == null )
753 {
754 return;
755 }
756
757 hasSpace = true;
758 continue;
759 }
760
761 if ( pos.line == null )
762 {
763 throw new LdapSchemaException( I18n.err( I18n.ERR_13782_END_OF_FILE, pos.lineNumber, pos.start ) );
764 }
765
766 while ( Character.isWhitespace( pos.line.charAt( pos.start ) ) )
767 {
768 hasSpace = true;
769 pos.start++;
770
771 if ( isEmpty( pos ) )
772 {
773 getLine( reader, pos );
774
775 if ( pos.line == null )
776 {
777 return;
778 }
779 }
780 }
781
782 if ( pos.line.charAt( pos.start ) == SHARP )
783 {
784 getLine( reader, pos );
785
786 if ( pos.line == null )
787 {
788 return;
789 }
790
791 hasSpace = true;
792 }
793 else
794 {
795 if ( mandatory && !hasSpace )
796 {
797 throw new LdapSchemaException( I18n.err( I18n.ERR_13783_SPACE_EXPECTED, pos.lineNumber, pos.start ) );
798 }
799 else
800 {
801 return;
802 }
803 }
804 }
805 }
806
807
808
809
810
811
812 private static boolean isComment( PosSchema pos )
813 {
814 if ( isEmpty( pos ) )
815 {
816 return true;
817 }
818
819 return pos.line.charAt( pos.start ) == SHARP;
820 }
821
822
823
824
825
826
827 private static boolean isEmpty( PosSchema pos )
828 {
829 return ( pos.line == null ) || ( pos.start >= pos.line.length() );
830 }
831
832
833
834
835
836
837
838 private static boolean startsWith( PosSchema pos, String text )
839 {
840 if ( ( pos.line == null ) || ( pos.line.length() - pos.start < text.length() ) )
841 {
842 return false;
843 }
844
845 return text.equalsIgnoreCase( pos.line.substring( pos.start, pos.start + text.length() ) );
846 }
847
848
849
850
851
852
853
854
855
856
857
858
859 private static boolean startsWith( Reader reader, PosSchema pos, char c ) throws IOException, LdapSchemaException
860 {
861 return startsWith( reader, pos, c, UN_QUOTED );
862 }
863
864
865
866
867
868
869
870
871
872
873
874
875
876 private static boolean startsWith( Reader reader, PosSchema pos, char c, boolean quoted ) throws IOException, LdapSchemaException
877 {
878 if ( ( pos.line == null ) || ( pos.line.length() - pos.start < 1 ) )
879 {
880 return false;
881 }
882
883 if ( quoted )
884 {
885
886 return pos.line.charAt( pos.start ) == c;
887 }
888
889 while ( isEmpty( pos ) || ( isComment( pos ) ) )
890 {
891 getLine( reader, pos );
892
893 if ( pos.line == null )
894 {
895 return false;
896 }
897
898 skipWhites( reader, pos, false );
899
900 if ( isComment( pos ) )
901 {
902 continue;
903 }
904 }
905
906 return pos.line.charAt( pos.start ) == c;
907 }
908
909
910
911
912
913
914
915 private static boolean startsWith( PosSchema pos, char c )
916 {
917 if ( ( pos.line == null ) || ( pos.line.length() - pos.start < 1 ) )
918 {
919 return false;
920 }
921
922 return pos.line.charAt( pos.start ) == c;
923 }
924
925
926
927
928
929
930 private static boolean isAlpha( PosSchema pos )
931 {
932 return Character.isAlphabetic( pos.line.charAt( pos.start ) );
933 }
934
935
936
937
938
939
940 private static boolean isDigit( PosSchema pos )
941 {
942 return Character.isDigit( pos.line.charAt( pos.start ) );
943 }
944
945
946
947
948
949
950
951
952 private static void getLine( Reader reader, PosSchema pos ) throws IOException
953 {
954 pos.line = ( ( BufferedReader ) reader ).readLine();
955 pos.start = 0;
956
957 if ( pos.line != null )
958 {
959 pos.lineNumber++;
960 }
961 }
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977 private static String getNumericOid( PosSchema pos ) throws LdapSchemaException
978 {
979 int start = pos.start;
980 boolean isDot = false;
981 boolean isFirstZero = false;
982 boolean isFirstDigit = true;
983
984 while ( !isEmpty( pos ) )
985 {
986 char c = pos.line.charAt( pos.start );
987
988 if ( Character.isDigit( c ) )
989 {
990 if ( isFirstZero )
991 {
992 throw new LdapSchemaException( I18n.err( I18n.ERR_13784_BAD_OID_TWO_ZEROES, pos.lineNumber, pos.start ) );
993 }
994
995 if ( ( pos.line.charAt( pos.start ) == '0' ) && isFirstDigit )
996 {
997 isFirstZero = true;
998 }
999
1000 isDot = false;
1001 pos.start++;
1002 isFirstDigit = false;
1003 }
1004 else if ( c == DOT )
1005 {
1006 if ( isDot )
1007 {
1008
1009 throw new LdapSchemaException( I18n.err( I18n.ERR_13785_BAD_OID_CONSECUTIVE_DOTS, pos.lineNumber, pos.start ) );
1010 }
1011
1012 isFirstZero = false;
1013 isFirstDigit = true;
1014 pos.start++;
1015 isDot = true;
1016 }
1017 else
1018 {
1019 break;
1020 }
1021 }
1022
1023 if ( isDot )
1024 {
1025
1026 throw new LdapSchemaException( I18n.err( I18n.ERR_13786_BAD_OID_DOT_AT_THE_END, pos.lineNumber, pos.start ) );
1027 }
1028
1029 String oidStr = pos.line.substring( start, pos.start );
1030
1031 if ( Oid.isOid( oidStr ) )
1032 {
1033 return oidStr;
1034 }
1035 else
1036 {
1037 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.line, pos.start ) );
1038 }
1039 }
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 private static String getPartialNumericOid( PosSchema pos ) throws LdapSchemaException
1056 {
1057 int start = pos.start;
1058 boolean isDot = false;
1059 boolean isFirstZero = false;
1060 boolean isFirstDigit = true;
1061
1062 while ( !isEmpty( pos ) )
1063 {
1064 if ( isDigit( pos ) )
1065 {
1066 if ( isFirstZero )
1067 {
1068 throw new LdapSchemaException( I18n.err( I18n.ERR_13784_BAD_OID_TWO_ZEROES, pos.lineNumber, pos.start ) );
1069 }
1070
1071 if ( ( pos.line.charAt( pos.start ) == '0' ) && isFirstDigit )
1072 {
1073 isFirstZero = true;
1074 }
1075
1076 isDot = false;
1077 pos.start++;
1078 isFirstDigit = false;
1079 }
1080 else if ( startsWith( pos, DOT ) )
1081 {
1082 if ( isDot )
1083 {
1084
1085 throw new LdapSchemaException( I18n.err( I18n.ERR_13785_BAD_OID_CONSECUTIVE_DOTS, pos.lineNumber, pos.start ) );
1086 }
1087
1088 isFirstZero = false;
1089 isFirstDigit = true;
1090 pos.start++;
1091 isDot = true;
1092 }
1093 else
1094 {
1095 break;
1096 }
1097 }
1098
1099 if ( isDot )
1100 {
1101
1102 throw new LdapSchemaException( I18n.err( I18n.ERR_13786_BAD_OID_DOT_AT_THE_END, pos.lineNumber, pos.start ) );
1103 }
1104
1105 return pos.line.substring( start, pos.start );
1106 }
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138 private static String getOidAndMacroRelaxed( PosSchema pos,
1139 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws LdapSchemaException
1140 {
1141 if ( isEmpty( pos ) )
1142 {
1143 return "";
1144 }
1145
1146
1147 int start = pos.start;
1148 char c = pos.line.charAt( pos.start );
1149 boolean isDigit = Character.isDigit( c );
1150
1151 while ( isDigit || Character.isAlphabetic( c ) || ( c == HYPHEN ) || ( c == UNDERSCORE )
1152 || ( c == SEMI_COLON ) || ( c == DOT ) || ( c == SHARP ) )
1153 {
1154 pos.start++;
1155
1156 if ( isEmpty( pos ) )
1157 {
1158 break;
1159 }
1160
1161 c = pos.line.charAt( pos.start );
1162 isDigit = Character.isDigit( c );
1163 }
1164
1165 String oidName = pos.line.substring( start, pos.start );
1166
1167 if ( Strings.isEmpty( oidName ) )
1168 {
1169 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
1170 }
1171
1172
1173 if ( startsWith( pos, COLON ) )
1174 {
1175 pos.start++;
1176 String oid = getPartialNumericOid( pos );
1177
1178 return objectIdentifierMacros.get( oidName ).getRawOidOrNameSuffix() + DOT + oid;
1179 }
1180 else
1181 {
1182
1183 OpenLdapObjectIdentifierMacro macro = objectIdentifierMacros.get( oidName );
1184
1185 if ( macro == null )
1186 {
1187 return oidName;
1188 }
1189 else
1190 {
1191 return macro.getRawOidOrNameSuffix();
1192 }
1193 }
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218 private static String getOidStrict( PosSchema pos ) throws LdapSchemaException
1219 {
1220 if ( isEmpty( pos ) )
1221 {
1222 return "";
1223 }
1224
1225 if ( isAlpha( pos ) )
1226 {
1227
1228 return getDescrStrict( pos );
1229 }
1230 else if ( isDigit( pos ) )
1231 {
1232
1233 return getNumericOid( pos );
1234 }
1235 else
1236 {
1237
1238 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
1239 }
1240 }
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 private static String getOidRelaxed( PosSchema pos, boolean hadQuote ) throws LdapSchemaException
1273 {
1274 if ( isEmpty( pos ) )
1275 {
1276 return "";
1277 }
1278
1279 boolean hasQuote = false;
1280
1281 char c = pos.line.charAt( pos.start );
1282
1283 if ( c == SQUOTE )
1284 {
1285 if ( hadQuote )
1286 {
1287 return "";
1288 }
1289
1290 hasQuote = true;
1291 pos.start++;
1292
1293 if ( isEmpty( pos ) )
1294 {
1295 return "";
1296 }
1297
1298 c = pos.line.charAt( pos.start );
1299 }
1300
1301 String oid;
1302
1303 if ( Character.isAlphabetic( c ) )
1304 {
1305
1306 oid = getDescrRelaxed( pos );
1307 }
1308 else if ( Character.isDigit( c ) )
1309 {
1310
1311 oid = getNumericOid( pos );
1312 }
1313 else
1314 {
1315
1316 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED,
1317 pos.lineNumber, pos.start ) );
1318 }
1319
1320 if ( isEmpty( pos ) )
1321 {
1322 if ( hasQuote || hadQuote )
1323 {
1324 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
1325 pos.lineNumber, pos.start ) );
1326 }
1327 else
1328 {
1329 return oid;
1330 }
1331 }
1332
1333 c = pos.line.charAt( pos.start );
1334
1335 if ( ( c == SQUOTE ) && !hadQuote )
1336 {
1337 if ( hasQuote )
1338 {
1339 pos.start++;
1340 }
1341 else
1342 {
1343 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
1344 pos.lineNumber, pos.start ) );
1345 }
1346 }
1347
1348 return oid;
1349 }
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373 private static String getDescrStrict( PosSchema pos ) throws LdapSchemaException
1374 {
1375 int start = pos.start;
1376 boolean isFirst = true;
1377
1378 while ( !isEmpty( pos ) )
1379 {
1380 if ( isFirst )
1381 {
1382 isFirst = false;
1383
1384 if ( isAlpha( pos ) )
1385 {
1386
1387 pos.start++;
1388 }
1389 else
1390 {
1391
1392 throw new LdapSchemaException( I18n.err( I18n.ERR_13788_LEAD_KEY_CHAR_EXPECTED,
1393 pos.lineNumber, pos.start ) );
1394 }
1395 }
1396 else
1397 {
1398 char c = pos.line.charAt( pos.start );
1399
1400 if ( Character.isAlphabetic( c ) || Character.isDigit( c ) || ( c == HYPHEN ) )
1401 {
1402 pos.start++;
1403 }
1404 else
1405 {
1406
1407 return pos.line.substring( start, pos.start );
1408 }
1409 }
1410 }
1411
1412 return pos.line.substring( start, pos.start );
1413 }
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443 private static String getDescrRelaxed( PosSchema pos ) throws LdapSchemaException
1444 {
1445 int start = pos.start;
1446 boolean isFirst = true;
1447
1448 while ( !isEmpty( pos ) )
1449 {
1450 if ( isFirst )
1451 {
1452 isFirst = false;
1453
1454 char c = pos.line.charAt( pos.start );
1455
1456 if ( Character.isAlphabetic( c ) || ( c == HYPHEN ) || ( c == UNDERSCORE )
1457 || ( c == SEMI_COLON ) || ( c == DOT ) || ( c == COLON ) || ( c == SHARP ) )
1458 {
1459
1460 pos.start++;
1461 }
1462 else
1463 {
1464
1465 throw new LdapSchemaException( I18n.err( I18n.ERR_13788_LEAD_KEY_CHAR_EXPECTED,
1466 pos.lineNumber, pos.start ) );
1467 }
1468 }
1469 else
1470 {
1471 char c = pos.line.charAt( pos.start );
1472
1473 if ( Character.isAlphabetic( c ) || Character.isDigit( c ) || ( c == HYPHEN )
1474 || ( c == UNDERSCORE ) || ( c == SEMI_COLON ) || ( c == DOT ) || ( c == COLON ) || ( c == SHARP ) )
1475 {
1476 pos.start++;
1477 }
1478 else
1479 {
1480
1481 return pos.line.substring( start, pos.start );
1482 }
1483 }
1484 }
1485
1486 return pos.line.substring( start, pos.start );
1487 }
1488
1489
1490
1491
1492
1493
1494
1495
1496 private String getMacro( PosSchema pos ) throws LdapSchemaException
1497 {
1498 if ( isQuirksModeEnabled )
1499 {
1500 int start = pos.start;
1501 boolean isFirst = true;
1502
1503 while ( !isEmpty( pos ) )
1504 {
1505 if ( isFirst )
1506 {
1507 isFirst = false;
1508
1509 char c = pos.line.charAt( pos.start );
1510
1511 if ( Character.isAlphabetic( c ) || ( c == HYPHEN ) || ( c == UNDERSCORE )
1512 || ( c == SEMI_COLON ) || ( c == DOT ) || ( c == SHARP ) )
1513 {
1514
1515 pos.start++;
1516 }
1517 else
1518 {
1519
1520 throw new LdapSchemaException( I18n.err( I18n.ERR_13788_LEAD_KEY_CHAR_EXPECTED,
1521 pos.lineNumber, pos.start ) );
1522 }
1523 }
1524 else
1525 {
1526 char c = pos.line.charAt( pos.start );
1527
1528 if ( Character.isAlphabetic( c ) || Character.isDigit( c ) || ( c == HYPHEN )
1529 || ( c == UNDERSCORE ) || ( c == SEMI_COLON ) || ( c == DOT ) || ( c == SHARP ) )
1530 {
1531 pos.start++;
1532 }
1533 else
1534 {
1535
1536 return pos.line.substring( start, pos.start );
1537 }
1538 }
1539 }
1540
1541 return pos.line.substring( start, pos.start );
1542 }
1543 else
1544 {
1545 int start = pos.start;
1546 boolean isFirst = true;
1547
1548 while ( !isEmpty( pos ) )
1549 {
1550 if ( isFirst )
1551 {
1552 isFirst = false;
1553
1554 if ( isAlpha( pos ) )
1555 {
1556
1557 pos.start++;
1558 }
1559 else
1560 {
1561
1562 throw new LdapSchemaException( I18n.err( I18n.ERR_13788_LEAD_KEY_CHAR_EXPECTED,
1563 pos.lineNumber, pos.start ) );
1564 }
1565 }
1566 else
1567 {
1568 char c = pos.line.charAt( pos.start );
1569
1570 if ( Character.isAlphabetic( c ) || Character.isDigit( c ) || ( c == HYPHEN ) )
1571 {
1572 pos.start++;
1573 }
1574 else
1575 {
1576
1577 return pos.line.substring( start, pos.start );
1578 }
1579 }
1580 }
1581
1582 return pos.line.substring( start, pos.start );
1583 }
1584 }
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611 private static String getQDescrStrict( Reader reader, PosSchema pos ) throws LdapSchemaException, IOException
1612 {
1613
1614 if ( !startsWith( reader, pos, SQUOTE ) )
1615 {
1616 throw new LdapSchemaException( I18n.err( I18n.ERR_13789_SIMPLE_QUOTE_EXPECTED_AT_START,
1617 pos.lineNumber, pos.start ) );
1618 }
1619
1620 pos.start++;
1621 int start = pos.start;
1622 boolean isFirst = true;
1623
1624 while ( !startsWith( pos, SQUOTE ) )
1625 {
1626 if ( isFirst )
1627 {
1628 isFirst = false;
1629
1630 if ( !isEmpty( pos ) && isAlpha( pos ) )
1631 {
1632
1633 pos.start++;
1634 }
1635 else
1636 {
1637
1638 throw new LdapSchemaException( I18n.err( I18n.ERR_13788_LEAD_KEY_CHAR_EXPECTED,
1639 pos.lineNumber, pos.start ) );
1640 }
1641 }
1642 else
1643 {
1644 if ( isEmpty( pos ) )
1645 {
1646
1647 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
1648 pos.lineNumber, pos.start ) );
1649 }
1650
1651 char c = pos.line.charAt( pos.start );
1652
1653 if ( Character.isAlphabetic( c ) || Character.isDigit( c ) || ( c == HYPHEN ) )
1654 {
1655 pos.start++;
1656 }
1657 else
1658 {
1659
1660 throw new LdapSchemaException( I18n.err( I18n.ERR_13791_KEYCHAR_EXPECTED, c,
1661 pos.lineNumber, pos.start ) );
1662 }
1663 }
1664 }
1665
1666 if ( startsWith( pos, SQUOTE ) )
1667 {
1668
1669 pos.start++;
1670
1671 return pos.line.substring( start, pos.start - 1 );
1672 }
1673 else
1674 {
1675
1676 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
1677 pos.lineNumber, pos.start ) );
1678 }
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 private static String getQDescrRelaxed( Reader reader, PosSchema pos ) throws LdapSchemaException, IOException
1707 {
1708 if ( startsWith( reader, pos, SQUOTE ) )
1709 {
1710 pos.start++;
1711 int start = pos.start;
1712
1713 while ( !startsWith( pos, SQUOTE ) )
1714 {
1715 if ( isEmpty( pos ) )
1716 {
1717 throw new LdapSchemaException( I18n.err( I18n.ERR_13789_SIMPLE_QUOTE_EXPECTED_AT_START,
1718 pos.lineNumber, pos.start ) );
1719 }
1720
1721 char c = pos.line.charAt( pos.start );
1722
1723 if ( Character.isDigit( c ) || Character.isAlphabetic( c ) || ( c == HYPHEN ) || ( c == UNDERSCORE )
1724 || ( c == SEMI_COLON ) || ( c == DOT ) || ( c == COLON ) || ( c == SHARP ) )
1725 {
1726 pos.start++;
1727 }
1728 else if ( c != SQUOTE )
1729 {
1730 throw new LdapSchemaException( I18n.err( I18n.ERR_13790_NOT_A_KEYSTRING, pos.lineNumber, pos.start ) );
1731 }
1732 }
1733
1734 pos.start++;
1735
1736 return pos.line.substring( start, pos.start - 1 );
1737 }
1738 else
1739 {
1740 int start = pos.start;
1741
1742 while ( !isEmpty( pos ) )
1743 {
1744 char c = pos.line.charAt( pos.start );
1745
1746 if ( Character.isDigit( c ) || Character.isAlphabetic( c ) || ( c == HYPHEN ) || ( c == UNDERSCORE )
1747 || ( c == SEMI_COLON ) || ( c == DOT ) || ( c == COLON ) || ( c == SHARP ) )
1748 {
1749 pos.start++;
1750 }
1751 else
1752 {
1753 break;
1754 }
1755 }
1756
1757 return pos.line.substring( start, pos.start );
1758 }
1759 }
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785 private static String getQDString( Reader reader, PosSchema pos ) throws LdapSchemaException, IOException
1786 {
1787
1788 if ( !startsWith( reader, pos, SQUOTE ) )
1789 {
1790 throw new LdapSchemaException( I18n.err( I18n.ERR_13789_SIMPLE_QUOTE_EXPECTED_AT_START,
1791 pos.lineNumber, pos.start ) );
1792 }
1793
1794 pos.start++;
1795 int start = pos.start;
1796 int nbEscapes = 0;
1797
1798 while ( !isEmpty( pos ) && !startsWith( pos, SQUOTE ) )
1799 {
1800
1801 if ( startsWith( pos, ESCAPE ) )
1802 {
1803 nbEscapes++;
1804 }
1805
1806 pos.start++;
1807
1808 }
1809
1810 if ( startsWith( pos, SQUOTE ) )
1811 {
1812
1813 pos.start++;
1814
1815
1816 char[] unescaped = new char[pos.start - 1 - start - nbEscapes * 2];
1817 int newPos = 0;
1818
1819 for ( int i = start; i < pos.start - 1; i++ )
1820 {
1821 char c = pos.line.charAt( i );
1822
1823 if ( c == ESCAPE )
1824 {
1825 if ( i + 2 > pos.start )
1826 {
1827
1828 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
1829 pos.lineNumber, pos.start ) );
1830 }
1831
1832 int u = Character.digit( pos.line.charAt( i + 1 ), 16 );
1833 int l = Character.digit( pos.line.charAt( i + 2 ), 16 );
1834
1835 unescaped[newPos] = ( char ) ( ( u << 4 ) + l );
1836 i += 2;
1837 }
1838 else
1839 {
1840 unescaped[newPos] = c;
1841 }
1842
1843 newPos++;
1844 }
1845
1846 return new String( unescaped );
1847 }
1848 else
1849 {
1850
1851 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
1852 pos.lineNumber, pos.start ) );
1853 }
1854 }
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875 private static List<String> getQDescrs( Reader reader, PosSchema pos, boolean relaxed )
1876 throws LdapSchemaException, IOException
1877 {
1878 List<String> qdescrs = new ArrayList<>();
1879
1880
1881 if ( startsWith( reader, pos, LPAREN ) )
1882 {
1883 pos.start++;
1884
1885
1886 skipWhites( reader, pos, false );
1887
1888 while ( !startsWith( reader, pos, RPAREN ) )
1889 {
1890 String qdescr;
1891
1892 if ( relaxed )
1893 {
1894 qdescr = getQDescrRelaxed( reader, pos );
1895 }
1896 else
1897 {
1898 qdescr = getQDescrStrict( reader, pos );
1899 }
1900
1901 qdescrs.add( qdescr );
1902
1903 if ( startsWith( reader, pos, RPAREN ) )
1904 {
1905 break;
1906 }
1907
1908 skipWhites( reader, pos, true );
1909 }
1910
1911 if ( !startsWith( reader, pos, RPAREN ) )
1912 {
1913 throw new LdapSchemaException( I18n.err( I18n.ERR_13793_NO_CLOSING_PAREN,
1914 pos.lineNumber, pos.start ) );
1915 }
1916
1917 pos.start++;
1918 }
1919 else
1920 {
1921
1922 String qDescr;
1923
1924 if ( relaxed )
1925 {
1926 qDescr = getQDescrRelaxed( reader, pos );
1927 }
1928 else
1929 {
1930 qDescr = getQDescrStrict( reader, pos );
1931 }
1932
1933 if ( Strings.isEmpty( qDescr ) )
1934 {
1935 throw new LdapSchemaException( I18n.err( I18n.ERR_13732_NAME_CANNOT_BE_NULL, pos.lineNumber, pos.start ) );
1936 }
1937
1938 qdescrs.add( qDescr );
1939 }
1940
1941 return qdescrs;
1942 }
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959 private static List<String> getQDStrings( Reader reader, PosSchema pos )
1960 throws LdapSchemaException, IOException
1961 {
1962 List<String> qdStrings = new ArrayList<>();
1963
1964
1965 if ( startsWith( reader, pos, LPAREN ) )
1966 {
1967 pos.start++;
1968
1969
1970 skipWhites( reader, pos, false );
1971
1972 while ( !startsWith( reader, pos, RPAREN ) )
1973 {
1974 qdStrings.add( getQDString( reader, pos ) );
1975
1976 if ( startsWith( reader, pos, RPAREN ) )
1977 {
1978 break;
1979 }
1980
1981 skipWhites( reader, pos, true );
1982 }
1983
1984 if ( !startsWith( reader, pos, RPAREN ) )
1985 {
1986 throw new LdapSchemaException( I18n.err( I18n.ERR_13793_NO_CLOSING_PAREN,
1987 pos.lineNumber, pos.start ) );
1988 }
1989
1990 pos.start++;
1991 }
1992 else
1993 {
1994
1995 qdStrings.add( getQDString( reader, pos ) );
1996 }
1997
1998 return qdStrings;
1999 }
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014 private static List<String> getOidsStrict( Reader reader, PosSchema pos ) throws LdapSchemaException, IOException
2015 {
2016 List<String> oids = new ArrayList<>();
2017
2018
2019 if ( startsWith( reader, pos, LPAREN ) )
2020 {
2021 pos.start++;
2022
2023
2024 skipWhites( reader, pos, false );
2025 boolean moreExpected = false;
2026
2027 while ( !startsWith( reader, pos, RPAREN ) )
2028 {
2029 moreExpected = false;
2030
2031 oids.add( getOidStrict( pos ) );
2032
2033 if ( startsWith( reader, pos, RPAREN ) )
2034 {
2035 break;
2036 }
2037
2038 skipWhites( reader, pos, false );
2039
2040 if ( startsWith( reader, pos, DOLLAR ) )
2041 {
2042 pos.start++;
2043 moreExpected = true;
2044 }
2045
2046 skipWhites( reader, pos, false );
2047 }
2048
2049 if ( !startsWith( reader, pos, RPAREN ) )
2050 {
2051 throw new LdapSchemaException( I18n.err( I18n.ERR_13793_NO_CLOSING_PAREN,
2052 pos.lineNumber, pos.start ) );
2053 }
2054
2055 if ( moreExpected )
2056 {
2057 throw new LdapSchemaException( I18n.err( I18n.ERR_13794_MORE_OIDS_EXPECTED,
2058 pos.lineNumber, pos.start ) );
2059 }
2060
2061 pos.start++;
2062 }
2063 else
2064 {
2065
2066 oids.add( getOidStrict( pos ) );
2067 }
2068
2069 return oids;
2070 }
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085 private static List<String> getOidsRelaxed( Reader reader, PosSchema pos ) throws LdapSchemaException, IOException
2086 {
2087 List<String> oids = new ArrayList<>();
2088
2089
2090 if ( startsWith( reader, pos, LPAREN ) )
2091 {
2092 pos.start++;
2093
2094
2095 skipWhites( reader, pos, false );
2096 boolean moreExpected = false;
2097
2098 while ( !startsWith( reader, pos, RPAREN ) )
2099 {
2100 moreExpected = false;
2101
2102 oids.add( getOidRelaxed( pos, UN_QUOTED ) );
2103
2104 if ( startsWith( reader, pos, RPAREN ) )
2105 {
2106 break;
2107 }
2108
2109 skipWhites( reader, pos, false );
2110
2111 if ( startsWith( reader, pos, DOLLAR ) )
2112 {
2113 pos.start++;
2114 moreExpected = true;
2115 }
2116
2117 skipWhites( reader, pos, false );
2118 }
2119
2120 if ( !startsWith( reader, pos, RPAREN ) )
2121 {
2122 throw new LdapSchemaException( I18n.err( I18n.ERR_13793_NO_CLOSING_PAREN,
2123 pos.lineNumber, pos.start ) );
2124 }
2125
2126 if ( moreExpected )
2127 {
2128 throw new LdapSchemaException( I18n.err( I18n.ERR_13794_MORE_OIDS_EXPECTED,
2129 pos.lineNumber, pos.start ) );
2130 }
2131
2132 pos.start++;
2133 }
2134 else
2135 {
2136
2137 oids.add( getOidRelaxed( pos, UN_QUOTED ) );
2138 }
2139
2140 return oids;
2141 }
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153 private static void getNoidLenStrict( AttributeType attributeType, PosSchema pos ) throws LdapSchemaException
2154 {
2155
2156 String oid = getOidStrict( pos );
2157
2158 if ( oid.length() == 0 )
2159 {
2160 throw new LdapSchemaException( I18n.err( I18n.ERR_13828_MISSING_SYNTAX_OID, pos.line, pos.start ) );
2161 }
2162
2163 attributeType.setSyntaxOid( oid );
2164
2165
2166 if ( startsWith( pos, LBRACE ) )
2167 {
2168 pos.start++;
2169 int start = pos.start;
2170
2171 while ( !isEmpty( pos ) && isDigit( pos ) )
2172 {
2173 pos.start++;
2174 }
2175
2176 if ( startsWith( pos, RBRACE ) )
2177 {
2178 String lenStr = pos.line.substring( start, pos.start );
2179
2180 if ( lenStr.length() == 0 )
2181 {
2182 throw new LdapSchemaException( I18n.err( I18n.ERR_13827_EMPTY_SYNTAX_LEN, pos.line, pos.start ) );
2183 }
2184
2185 pos.start++;
2186
2187 if ( Strings.isEmpty( lenStr ) )
2188 {
2189 attributeType.setSyntaxLength( -1L );
2190 }
2191 else
2192 {
2193 attributeType.setSyntaxLength( Long.parseLong( lenStr ) );
2194 }
2195 }
2196 else
2197 {
2198
2199 throw new LdapSchemaException( I18n.err( I18n.ERR_13795_OPENED_BRACKET_NOT_CLOSED,
2200 pos.lineNumber, pos.start ) );
2201 }
2202 }
2203 }
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215 private static void getNoidLenRelaxed( AttributeType attributeType, PosSchema pos ) throws LdapSchemaException
2216 {
2217
2218 boolean hasQuote = false;
2219
2220 char c = pos.line.charAt( pos.start );
2221
2222 if ( c == SQUOTE )
2223 {
2224 hasQuote = true;
2225 pos.start++;
2226
2227 if ( isEmpty( pos ) )
2228 {
2229 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
2230 pos.lineNumber, pos.start ) );
2231 }
2232 }
2233
2234
2235 String oid = getOidRelaxed( pos, hasQuote );
2236
2237 if ( oid.length() == 0 )
2238 {
2239 throw new LdapSchemaException( I18n.err( I18n.ERR_13828_MISSING_SYNTAX_OID, pos.line, pos.start ) );
2240 }
2241
2242 attributeType.setSyntaxOid( oid );
2243
2244
2245 if ( startsWith( pos, LBRACE ) )
2246 {
2247 pos.start++;
2248 int start = pos.start;
2249
2250 while ( !isEmpty( pos ) && isDigit( pos ) )
2251 {
2252 pos.start++;
2253 }
2254
2255 if ( startsWith( pos, RBRACE ) )
2256 {
2257 String lenStr = pos.line.substring( start, pos.start );
2258
2259 pos.start++;
2260
2261 if ( Strings.isEmpty( lenStr ) )
2262 {
2263 attributeType.setSyntaxLength( -1L );
2264 }
2265 else
2266 {
2267 attributeType.setSyntaxLength( Long.parseLong( lenStr ) );
2268 }
2269 }
2270 else
2271 {
2272
2273 throw new LdapSchemaException( I18n.err( I18n.ERR_13795_OPENED_BRACKET_NOT_CLOSED,
2274 pos.lineNumber, pos.start ) );
2275 }
2276 }
2277
2278 if ( hasQuote )
2279 {
2280 if ( isEmpty( pos ) )
2281 {
2282 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
2283 pos.lineNumber, pos.start ) );
2284 }
2285
2286 c = pos.line.charAt( pos.start );
2287
2288 if ( c == SQUOTE )
2289 {
2290 pos.start++;
2291 }
2292 else
2293 {
2294 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
2295 pos.lineNumber, pos.start ) );
2296 }
2297 }
2298 }
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314 private static int getRuleId( PosSchema pos ) throws LdapSchemaException
2315 {
2316 int start = pos.start;
2317
2318 while ( !isEmpty( pos ) && isDigit( pos ) )
2319 {
2320 pos.start++;
2321 }
2322
2323 if ( start == pos.start )
2324 {
2325
2326 throw new LdapSchemaException( I18n.err( I18n.ERR_13811_INVALID_RULE_ID,
2327 pos.lineNumber, pos.start ) );
2328 }
2329
2330 String lenStr = pos.line.substring( start, pos.start );
2331
2332 return Integer.parseInt( lenStr );
2333 }
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348 private static List<Integer> getRuleIds( Reader reader, PosSchema pos ) throws LdapSchemaException, IOException
2349 {
2350 List<Integer> ruleIds = new ArrayList<>();
2351
2352
2353 if ( startsWith( reader, pos, LPAREN ) )
2354 {
2355 pos.start++;
2356
2357
2358 skipWhites( reader, pos, false );
2359 boolean moreExpected = false;
2360
2361 while ( !startsWith( reader, pos, RPAREN ) )
2362 {
2363 moreExpected = false;
2364
2365 ruleIds.add( getRuleId( pos ) );
2366
2367 if ( startsWith( reader, pos, RPAREN ) )
2368 {
2369 break;
2370 }
2371
2372 skipWhites( reader, pos, false );
2373
2374 if ( startsWith( reader, pos, DOLLAR ) )
2375 {
2376 pos.start++;
2377 moreExpected = true;
2378 }
2379
2380 skipWhites( reader, pos, false );
2381 }
2382
2383 if ( !startsWith( reader, pos, RPAREN ) )
2384 {
2385 throw new LdapSchemaException( I18n.err( I18n.ERR_13793_NO_CLOSING_PAREN,
2386 pos.lineNumber, pos.start ) );
2387 }
2388
2389 if ( moreExpected )
2390 {
2391 throw new LdapSchemaException( I18n.err( I18n.ERR_13813_MORE_RULE_IDS_EXPECTED,
2392 pos.lineNumber, pos.start ) );
2393 }
2394
2395 pos.start++;
2396 }
2397 else
2398 {
2399
2400 ruleIds.add( getRuleId( pos ) );
2401 }
2402
2403 return ruleIds;
2404 }
2405
2406
2407
2408
2409
2410
2411
2412
2413 private static UsageEnum getUsageStrict( PosSchema pos ) throws LdapSchemaException
2414 {
2415 if ( isEmpty( pos ) )
2416 {
2417 throw new LdapSchemaException( I18n.err( I18n.ERR_13796_USAGE_EXPECTED,
2418 pos.lineNumber, pos.start ) );
2419 }
2420
2421 if ( startsWith( pos, USER_APPLICATIONS_STR ) )
2422 {
2423 pos.start += USER_APPLICATIONS_STR.length();
2424
2425 return UsageEnum.USER_APPLICATIONS;
2426 }
2427 else if ( startsWith( pos, DIRECTORY_OPERATION_STR ) )
2428 {
2429 pos.start += DIRECTORY_OPERATION_STR.length();
2430
2431 return UsageEnum.DIRECTORY_OPERATION;
2432 }
2433 else if ( startsWith( pos, DISTRIBUTED_OPERATION_STR ) )
2434 {
2435 pos.start += DISTRIBUTED_OPERATION_STR.length();
2436
2437 return UsageEnum.DISTRIBUTED_OPERATION;
2438 }
2439 else if ( startsWith( pos, DSA_OPERATION_STR ) )
2440 {
2441 pos.start += DSA_OPERATION_STR.length();
2442
2443 return UsageEnum.DSA_OPERATION;
2444 }
2445 else
2446 {
2447 throw new LdapSchemaException( I18n.err( I18n.ERR_13797_USAGE_UNKNOWN,
2448 pos.lineNumber, pos.start ) );
2449 }
2450 }
2451
2452
2453
2454
2455
2456
2457
2458
2459 private static UsageEnum getUsageRelaxed( PosSchema pos ) throws LdapSchemaException
2460 {
2461 if ( isEmpty( pos ) )
2462 {
2463 throw new LdapSchemaException( I18n.err( I18n.ERR_13796_USAGE_EXPECTED,
2464 pos.lineNumber, pos.start ) );
2465 }
2466
2467 boolean isSQuoted = false;
2468 boolean isDQuoted = false;
2469
2470 if ( pos.line.charAt( pos.start ) == SQUOTE )
2471 {
2472 isSQuoted = true;
2473 pos.start++;
2474
2475 if ( isEmpty( pos ) )
2476 {
2477 throw new LdapSchemaException( I18n.err( I18n.ERR_13796_USAGE_EXPECTED,
2478 pos.lineNumber, pos.start ) );
2479 }
2480 }
2481 else if ( pos.line.charAt( pos.start ) == DQUOTE )
2482 {
2483 isDQuoted = true;
2484 pos.start++;
2485
2486 if ( isEmpty( pos ) )
2487 {
2488 throw new LdapSchemaException( I18n.err( I18n.ERR_13796_USAGE_EXPECTED,
2489 pos.lineNumber, pos.start ) );
2490 }
2491 }
2492
2493 UsageEnum usage = UsageEnum.USER_APPLICATIONS;
2494
2495 if ( startsWith( pos, USER_APPLICATIONS_STR ) )
2496 {
2497 pos.start += USER_APPLICATIONS_STR.length();
2498
2499 usage = UsageEnum.USER_APPLICATIONS;
2500 }
2501 else if ( startsWith( pos, DIRECTORY_OPERATION_STR ) )
2502 {
2503 pos.start += DIRECTORY_OPERATION_STR.length();
2504
2505 usage = UsageEnum.DIRECTORY_OPERATION;
2506 }
2507 else if ( startsWith( pos, DISTRIBUTED_OPERATION_STR ) )
2508 {
2509 pos.start += DISTRIBUTED_OPERATION_STR.length();
2510
2511 usage = UsageEnum.DISTRIBUTED_OPERATION;
2512 }
2513 else if ( startsWith( pos, DSA_OPERATION_STR ) )
2514 {
2515 pos.start += DSA_OPERATION_STR.length();
2516
2517 usage = UsageEnum.DSA_OPERATION;
2518 }
2519 else
2520 {
2521 throw new LdapSchemaException( I18n.err( I18n.ERR_13797_USAGE_UNKNOWN,
2522 pos.lineNumber, pos.start ) );
2523 }
2524
2525 if ( isSQuoted )
2526 {
2527 if ( isEmpty( pos ) )
2528 {
2529 throw new LdapSchemaException( I18n.err( I18n.ERR_13796_USAGE_EXPECTED,
2530 pos.lineNumber, pos.start ) );
2531 }
2532
2533 if ( pos.line.charAt( pos.start ) != SQUOTE )
2534 {
2535 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
2536 pos.lineNumber, pos.start ) );
2537 }
2538
2539 pos.start++;
2540 }
2541 else if ( isDQuoted )
2542 {
2543 if ( isEmpty( pos ) )
2544 {
2545 throw new LdapSchemaException( I18n.err( I18n.ERR_13796_USAGE_EXPECTED,
2546 pos.lineNumber, pos.start ) );
2547 }
2548
2549 if ( pos.line.charAt( pos.start ) != DQUOTE )
2550 {
2551 throw new LdapSchemaException( I18n.err( I18n.ERR_13792_SIMPLE_QUOTE_EXPECTED_AT_END,
2552 pos.lineNumber, pos.start ) );
2553 }
2554
2555 pos.start++;
2556 }
2557
2558 return usage;
2559 }
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578 private static void processExtension( Reader reader, PosSchema pos, SchemaObject schemaObject )
2579 throws LdapSchemaException, IOException
2580 {
2581
2582 String extensionKey = getXString( pos );
2583
2584 skipWhites( reader, pos, true );
2585
2586 List<String> extensionValues = getQDStrings( reader, pos );
2587
2588 if ( schemaObject.hasExtension( extensionKey ) )
2589 {
2590 throw new LdapSchemaException(
2591 I18n.err( I18n.ERR_13780_SCHEMA_OBJECT_DESCRIPTION_HAS_ELEMENT_TWICE, extensionKey,
2592 pos.lineNumber, pos.start ) );
2593 }
2594
2595 schemaObject.addExtension( extensionKey, extensionValues );
2596 }
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608 private static String getXString( PosSchema pos ) throws LdapSchemaException
2609 {
2610 int start = pos.start;
2611
2612 if ( startsWith( pos, EXTENSION_PREFIX ) )
2613 {
2614 pos.start += 2;
2615
2616
2617 while ( !isEmpty( pos ) && ( isAlpha( pos ) || startsWith( pos, HYPHEN ) || startsWith( pos, UNDERSCORE ) ) )
2618 {
2619 pos.start++;
2620 }
2621
2622 return pos.line.substring( start, pos.start );
2623 }
2624 else
2625 {
2626 throw new LdapSchemaException( I18n.err( I18n.ERR_13802_EXTENSION_SHOULD_START_WITH_X,
2627 pos.lineNumber, pos.start ) );
2628 }
2629 }
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643 private static String getFqcn( PosSchema pos ) throws LdapSchemaException
2644 {
2645 if ( ( pos.line == null ) || ( pos.line.length() - pos.start < 1 ) )
2646 {
2647 return "";
2648 }
2649
2650 int start = pos.start;
2651 boolean isFirst = true;
2652 boolean dotSeen = false;
2653
2654 while ( true )
2655 {
2656 char c = pos.line.charAt( pos.start );
2657
2658 if ( isFirst )
2659 {
2660 if ( !Character.isJavaIdentifierStart( c ) )
2661 {
2662 throw new LdapSchemaException( I18n.err( I18n.ERR_13822_INVALID_FQCN_BAD_IDENTIFIER_START,
2663 pos.lineNumber, pos.start ) );
2664 }
2665
2666 isFirst = false;
2667 dotSeen = false;
2668 pos.start++;
2669 }
2670 else
2671 {
2672 if ( c == DOT )
2673 {
2674 if ( dotSeen )
2675 {
2676 throw new LdapSchemaException( I18n.err( I18n.ERR_13823_INVALID_FQCN_DOUBLE_DOT,
2677 pos.lineNumber, pos.start ) );
2678 }
2679 else
2680 {
2681 isFirst = true;
2682 dotSeen = true;
2683 pos.start++;
2684 }
2685 }
2686 else
2687 {
2688 if ( Character.isJavaIdentifierPart( c ) )
2689 {
2690 pos.start++;
2691 dotSeen = false;
2692 }
2693 else
2694 {
2695 return pos.line.substring( start, pos.start );
2696 }
2697 }
2698 }
2699
2700 if ( pos.line.length() - pos.start < 1 )
2701 {
2702 return pos.line.substring( start, pos.start );
2703 }
2704 }
2705 }
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717 private static String getByteCode( PosSchema pos )
2718 {
2719 if ( ( pos.line == null ) || ( pos.line.length() - pos.start < 1 ) )
2720 {
2721 return "";
2722 }
2723
2724 int start = pos.start;
2725
2726
2727 while ( !isEmpty( pos ) && ( isAlpha( pos ) || isDigit( pos ) || startsWith( pos, PLUS )
2728 || startsWith( pos, SLASH ) || startsWith( pos, EQUAL ) ) )
2729 {
2730 pos.start++;
2731
2732 if ( ( pos.line == null ) || ( pos.line.length() - pos.start < 1 ) )
2733 {
2734 return pos.line.substring( start, pos.start );
2735 }
2736 }
2737
2738 return pos.line.substring( start, pos.start );
2739 }
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750 private static int checkElement( int elementsSeen, SchemaObjectElements element, PosSchema pos ) throws LdapSchemaException
2751 {
2752 if ( ( elementsSeen & element.getValue() ) != 0 )
2753 {
2754 throw new LdapSchemaException( I18n.err( I18n.ERR_13780_SCHEMA_OBJECT_DESCRIPTION_HAS_ELEMENT_TWICE,
2755 element, pos.lineNumber, pos.start ) );
2756 }
2757
2758 elementsSeen |= element.getValue();
2759
2760 return elementsSeen;
2761 }
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798 public AttributeType parseAttributeType( String attributeTypeDescription ) throws ParseException
2799 {
2800 if ( ( attributeTypeDescription == null ) || Strings.isEmpty( attributeTypeDescription.trim() ) )
2801 {
2802 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
2803 }
2804
2805 try ( Reader reader = new BufferedReader( new StringReader( attributeTypeDescription ) ) )
2806 {
2807 PosSchema pos = new PosSchema();
2808
2809 if ( isQuirksModeEnabled )
2810 {
2811 return parseAttributeTypeRelaxed( reader, pos, objectIdentifierMacros );
2812 }
2813 else
2814 {
2815 return parseAttributeTypeStrict( reader, pos, objectIdentifierMacros );
2816 }
2817 }
2818 catch ( IOException | LdapSchemaException e )
2819 {
2820
2821 LOG.trace( I18n.err( I18n.ERR_13865_ERROR_PARSING_AT, attributeTypeDescription, e.getMessage() ), e );
2822 throw new ParseException( e.getMessage(), 0 );
2823 }
2824 }
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864 private static AttributeType parseAttributeTypeStrict( Reader reader, PosSchema pos,
2865 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
2866 {
2867
2868 skipWhites( reader, pos, false );
2869
2870
2871 if ( pos.line.charAt( pos.start ) != LPAREN )
2872 {
2873 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
2874 pos.lineNumber, pos.start ) );
2875 }
2876 else
2877 {
2878 pos.start++;
2879 }
2880
2881
2882 skipWhites( reader, pos, false );
2883
2884
2885 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
2886
2887
2888 if ( !Oid.isOid( oid ) )
2889 {
2890 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
2891 }
2892
2893 AttributeType attributeType = new AttributeType( oid );
2894 boolean hasSup = false;
2895 boolean hasSyntax = false;
2896 int elementsSeen = 0;
2897
2898 while ( true )
2899 {
2900 if ( startsWith( reader, pos, RPAREN ) )
2901 {
2902 pos.start++;
2903 break;
2904 }
2905
2906 skipWhites( reader, pos, true );
2907
2908 if ( startsWith( pos, NAME_STR ) )
2909 {
2910 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.NAME, pos );
2911
2912 pos.start += NAME_STR.length();
2913
2914 skipWhites( reader, pos, true );
2915
2916 attributeType.setNames( getQDescrs( reader, pos, STRICT ) );
2917 }
2918 else if ( startsWith( pos, DESC_STR ) )
2919 {
2920 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.DESC, pos );
2921
2922 pos.start += DESC_STR.length();
2923
2924 skipWhites( reader, pos, true );
2925
2926 attributeType.setDescription( getQDString( reader, pos ) );
2927 }
2928 else if ( startsWith( pos, OBSOLETE_STR ) )
2929 {
2930 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.OBSOLETE, pos );
2931
2932 pos.start += OBSOLETE_STR.length();
2933
2934 attributeType.setObsolete( true );
2935 }
2936 else if ( startsWith( pos, SUP_STR ) )
2937 {
2938 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.SUP, pos );
2939
2940 pos.start += SUP_STR.length();
2941
2942 skipWhites( reader, pos, true );
2943
2944 String superiorOid = getOidStrict( pos );
2945
2946 attributeType.setSuperiorOid( superiorOid );
2947 hasSup = true;
2948 }
2949 else if ( startsWith( pos, EQUALITY_STR ) )
2950 {
2951 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.EQUALITY, pos );
2952
2953 pos.start += EQUALITY_STR.length();
2954
2955 skipWhites( reader, pos, true );
2956
2957 String equalityOid = getOidStrict( pos );
2958
2959 attributeType.setEqualityOid( equalityOid );
2960 }
2961 else if ( startsWith( pos, ORDERING_STR ) )
2962 {
2963 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.ORDERING, pos );
2964
2965 pos.start += ORDERING_STR.length();
2966
2967 skipWhites( reader, pos, true );
2968
2969 String orderingOid = getOidStrict( pos );
2970
2971 attributeType.setOrderingOid( orderingOid );
2972 }
2973 else if ( startsWith( pos, SUBSTR_STR ) )
2974 {
2975 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.SUBSTR, pos );
2976
2977 pos.start += SUBSTR_STR.length();
2978
2979 skipWhites( reader, pos, true );
2980
2981 String substrOid = getOidStrict( pos );
2982
2983 attributeType.setSubstringOid( substrOid );
2984 }
2985 else if ( startsWith( pos, SYNTAX_STR ) )
2986 {
2987 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.SYNTAX, pos );
2988
2989 pos.start += SYNTAX_STR.length();
2990
2991 skipWhites( reader, pos, true );
2992
2993 getNoidLenStrict( attributeType, pos );
2994
2995 hasSyntax = true;
2996 }
2997 else if ( startsWith( pos, SINGLE_VALUE_STR ) )
2998 {
2999 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.SINGLE_VALUE, pos );
3000
3001 pos.start += SINGLE_VALUE_STR.length();
3002
3003 attributeType.setSingleValued( true );
3004 }
3005 else if ( startsWith( pos, COLLECTIVE_STR ) )
3006 {
3007 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.COLLECTIVE, pos );
3008
3009 pos.start += COLLECTIVE_STR.length();
3010
3011 attributeType.setCollective( true );
3012 }
3013 else if ( startsWith( pos, NO_USER_MODIFICATION_STR ) )
3014 {
3015 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.NO_USER_MODIFICATION, pos );
3016
3017 pos.start += NO_USER_MODIFICATION_STR.length();
3018
3019 attributeType.setUserModifiable( false );
3020 }
3021 else if ( startsWith( pos, USAGE_STR ) )
3022 {
3023 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.USAGE, pos );
3024
3025 pos.start += USAGE_STR.length();
3026
3027 skipWhites( reader, pos, true );
3028
3029 UsageEnum usage = getUsageStrict( pos );
3030
3031 attributeType.setUsage( usage );
3032 }
3033 else if ( startsWith( pos, EXTENSION_PREFIX ) )
3034 {
3035 processExtension( reader, pos, attributeType );
3036 }
3037 else if ( startsWith( reader, pos, RPAREN ) )
3038 {
3039 pos.start++;
3040 break;
3041 }
3042 else
3043 {
3044
3045 throw new LdapSchemaException( I18n.err( I18n.ERR_13798_AT_DESCRIPTION_INVALID,
3046 pos.lineNumber, pos.start ) );
3047 }
3048 }
3049
3050
3051 if ( !hasSup && !hasSyntax )
3052 {
3053 throw new LdapSchemaException( I18n.err( I18n.ERR_13799_SYNTAX_OR_SUP_REQUIRED,
3054 pos.lineNumber, pos.start ) );
3055 }
3056
3057 if ( attributeType.isCollective() && ( attributeType.getUsage() != UsageEnum.USER_APPLICATIONS ) )
3058 {
3059 throw new LdapSchemaException( I18n.err( I18n.ERR_13800_COLLECTIVE_REQUIRES_USER_APPLICATION,
3060 pos.lineNumber, pos.start ) );
3061 }
3062
3063
3064 if ( !attributeType.isUserModifiable() && ( attributeType.getUsage() == UsageEnum.USER_APPLICATIONS ) )
3065 {
3066 throw new LdapSchemaException( I18n.err( I18n.ERR_13801_NO_USER_MOD_REQUIRE_OPERATIONAL,
3067 pos.lineNumber, pos.start ) );
3068 }
3069
3070 return attributeType;
3071 }
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111 private static AttributeType parseAttributeTypeRelaxed( Reader reader, PosSchema pos,
3112 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
3113 {
3114
3115 skipWhites( reader, pos, false );
3116
3117
3118 if ( pos.line.charAt( pos.start ) != LPAREN )
3119 {
3120 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
3121 pos.lineNumber, pos.start ) );
3122 }
3123 else
3124 {
3125 pos.start++;
3126 }
3127
3128
3129 skipWhites( reader, pos, false );
3130
3131
3132 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
3133
3134 AttributeType attributeType = new AttributeType( oid );
3135 int elementsSeen = 0;
3136
3137 while ( true )
3138 {
3139 if ( startsWith( reader, pos, RPAREN ) )
3140 {
3141 pos.start++;
3142 break;
3143 }
3144
3145
3146
3147 skipWhites( reader, pos, false );
3148
3149 if ( startsWith( pos, NAME_STR ) )
3150 {
3151 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.NAME, pos );
3152
3153 pos.start += NAME_STR.length();
3154
3155 skipWhites( reader, pos, true );
3156
3157 attributeType.setNames( getQDescrs( reader, pos, RELAXED ) );
3158 }
3159 else if ( startsWith( pos, DESC_STR ) )
3160 {
3161 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.DESC, pos );
3162
3163 pos.start += DESC_STR.length();
3164
3165 skipWhites( reader, pos, true );
3166
3167 attributeType.setDescription( getQDString( reader, pos ) );
3168 }
3169 else if ( startsWith( pos, OBSOLETE_STR ) )
3170 {
3171 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.OBSOLETE, pos );
3172
3173 pos.start += OBSOLETE_STR.length();
3174
3175 attributeType.setObsolete( true );
3176 }
3177 else if ( startsWith( pos, SUP_STR ) )
3178 {
3179 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.SUP, pos );
3180
3181 pos.start += SUP_STR.length();
3182
3183 skipWhites( reader, pos, true );
3184
3185 String superiorOid = getOidRelaxed( pos, false );
3186
3187 attributeType.setSuperiorOid( superiorOid );
3188 }
3189 else if ( startsWith( pos, EQUALITY_STR ) )
3190 {
3191 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.EQUALITY, pos );
3192
3193 pos.start += EQUALITY_STR.length();
3194
3195 skipWhites( reader, pos, true );
3196
3197 String equalityOid = getOidRelaxed( pos, false );
3198
3199 attributeType.setEqualityOid( equalityOid );
3200 }
3201 else if ( startsWith( pos, ORDERING_STR ) )
3202 {
3203 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.ORDERING, pos );
3204
3205 pos.start += ORDERING_STR.length();
3206
3207 skipWhites( reader, pos, true );
3208
3209 String orderingOid = getOidRelaxed( pos, false );
3210
3211 attributeType.setOrderingOid( orderingOid );
3212 }
3213 else if ( startsWith( pos, SUBSTR_STR ) )
3214 {
3215 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.SUBSTR, pos );
3216
3217 pos.start += SUBSTR_STR.length();
3218
3219 skipWhites( reader, pos, true );
3220
3221 String substrOid = getOidRelaxed( pos, false );
3222
3223 attributeType.setSubstringOid( substrOid );
3224 }
3225 else if ( startsWith( pos, SYNTAX_STR ) )
3226 {
3227 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.SYNTAX, pos );
3228
3229 pos.start += SYNTAX_STR.length();
3230
3231 skipWhites( reader, pos, true );
3232
3233 getNoidLenRelaxed( attributeType, pos );
3234 }
3235 else if ( startsWith( pos, SINGLE_VALUE_STR ) )
3236 {
3237 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.SINGLE_VALUE, pos );
3238
3239 pos.start += SINGLE_VALUE_STR.length();
3240
3241 attributeType.setSingleValued( true );
3242 }
3243 else if ( startsWith( pos, COLLECTIVE_STR ) )
3244 {
3245 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.COLLECTIVE, pos );
3246
3247 pos.start += COLLECTIVE_STR.length();
3248
3249 attributeType.setCollective( true );
3250 }
3251 else if ( startsWith( pos, NO_USER_MODIFICATION_STR ) )
3252 {
3253 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.NO_USER_MODIFICATION, pos );
3254
3255 pos.start += NO_USER_MODIFICATION_STR.length();
3256
3257 attributeType.setUserModifiable( false );
3258 }
3259 else if ( startsWith( pos, USAGE_STR ) )
3260 {
3261 elementsSeen = checkElement( elementsSeen, AttributeTypeElements.USAGE, pos );
3262
3263 pos.start += USAGE_STR.length();
3264
3265 skipWhites( reader, pos, true );
3266
3267 UsageEnum usage = getUsageRelaxed( pos );
3268
3269 attributeType.setUsage( usage );
3270 }
3271 else if ( startsWith( pos, EXTENSION_PREFIX ) )
3272 {
3273 processExtension( reader, pos, attributeType );
3274 }
3275 else if ( startsWith( reader, pos, RPAREN ) )
3276 {
3277 pos.start++;
3278 break;
3279 }
3280 else
3281 {
3282
3283 throw new LdapSchemaException( I18n.err( I18n.ERR_13798_AT_DESCRIPTION_INVALID,
3284 pos.lineNumber, pos.start ) );
3285 }
3286 }
3287
3288 return attributeType;
3289 }
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313 public DitContentRule parseDitContentRule( String ditContentRuleDescription ) throws ParseException
3314 {
3315 if ( ( ditContentRuleDescription == null ) || Strings.isEmpty( ditContentRuleDescription.trim() ) )
3316 {
3317 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
3318 }
3319
3320 try ( Reader reader = new BufferedReader( new StringReader( ditContentRuleDescription ) ) )
3321 {
3322 PosSchema pos = new PosSchema();
3323
3324 if ( isQuirksModeEnabled )
3325 {
3326 return parseDitContentRuleRelaxed( reader, pos, objectIdentifierMacros );
3327 }
3328 else
3329 {
3330 return parseDitContentRuleStrict( reader, pos, objectIdentifierMacros );
3331 }
3332 }
3333 catch ( IOException | LdapSchemaException e )
3334 {
3335 throw new ParseException( e.getMessage(), 0 );
3336 }
3337 }
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364 private static DitContentRule parseDitContentRuleStrict( Reader reader, PosSchema pos,
3365 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
3366 {
3367
3368 skipWhites( reader, pos, false );
3369
3370
3371 if ( pos.line.charAt( pos.start ) != LPAREN )
3372 {
3373 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
3374 pos.lineNumber, pos.start ) );
3375 }
3376 else
3377 {
3378 pos.start++;
3379 }
3380
3381
3382 skipWhites( reader, pos, false );
3383
3384
3385 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
3386
3387
3388 if ( !Oid.isOid( oid ) )
3389 {
3390 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
3391 }
3392
3393 DitContentRule ditContentRule = new DitContentRule( oid );
3394 int elementsSeen = 0;
3395
3396 while ( true )
3397 {
3398 if ( startsWith( reader, pos, RPAREN ) )
3399 {
3400 pos.start++;
3401 break;
3402 }
3403
3404 skipWhites( reader, pos, true );
3405
3406 if ( startsWith( pos, NAME_STR ) )
3407 {
3408 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.NAME, pos );
3409
3410 pos.start += NAME_STR.length();
3411
3412 skipWhites( reader, pos, true );
3413
3414 ditContentRule.setNames( getQDescrs( reader, pos, STRICT ) );
3415 }
3416 else if ( startsWith( pos, DESC_STR ) )
3417 {
3418 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.DESC, pos );
3419
3420 pos.start += DESC_STR.length();
3421
3422 skipWhites( reader, pos, true );
3423
3424 ditContentRule.setDescription( getQDString( reader, pos ) );
3425 }
3426 else if ( startsWith( pos, OBSOLETE_STR ) )
3427 {
3428 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.OBSOLETE, pos );
3429
3430 pos.start += OBSOLETE_STR.length();
3431
3432 ditContentRule.setObsolete( true );
3433 }
3434 else if ( startsWith( pos, AUX_STR ) )
3435 {
3436 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.AUX, pos );
3437
3438 pos.start += AUX_STR.length();
3439
3440 skipWhites( reader, pos, true );
3441
3442 List<String> aux = getOidsStrict( reader, pos );
3443
3444 ditContentRule.setAuxObjectClassOids( aux );
3445 }
3446 else if ( startsWith( pos, MUST_STR ) )
3447 {
3448 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.MUST, pos );
3449
3450 pos.start += MUST_STR.length();
3451
3452 skipWhites( reader, pos, true );
3453
3454 List<String> must = getOidsStrict( reader, pos );
3455
3456 ditContentRule.setMustAttributeTypeOids( must );
3457 }
3458 else if ( startsWith( pos, MAY_STR ) )
3459 {
3460 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.MAY, pos );
3461
3462 pos.start += MAY_STR.length();
3463
3464 skipWhites( reader, pos, true );
3465
3466 List<String> may = getOidsStrict( reader, pos );
3467
3468 ditContentRule.setMayAttributeTypeOids( may );
3469 }
3470 else if ( startsWith( pos, NOT_STR ) )
3471 {
3472 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.NOT, pos );
3473
3474 pos.start += NOT_STR.length();
3475
3476 skipWhites( reader, pos, true );
3477
3478 List<String> not = getOidsStrict( reader, pos );
3479
3480 ditContentRule.setNotAttributeTypeOids( not );
3481 }
3482 else if ( startsWith( pos, EXTENSION_PREFIX ) )
3483 {
3484 processExtension( reader, pos, ditContentRule );
3485 }
3486 else if ( startsWith( reader, pos, RPAREN ) )
3487 {
3488 pos.start++;
3489
3490 break;
3491 }
3492 else
3493 {
3494
3495 throw new LdapSchemaException( I18n.err( I18n.ERR_13809_DCR_DESCRIPTION_INVALID,
3496 pos.lineNumber, pos.start ) );
3497 }
3498 }
3499
3500 return ditContentRule;
3501 }
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528 private static DitContentRule parseDitContentRuleRelaxed( Reader reader, PosSchema pos,
3529 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
3530 {
3531
3532 skipWhites( reader, pos, false );
3533
3534
3535 if ( pos.line.charAt( pos.start ) != LPAREN )
3536 {
3537 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
3538 pos.lineNumber, pos.start ) );
3539 }
3540 else
3541 {
3542 pos.start++;
3543 }
3544
3545
3546 skipWhites( reader, pos, false );
3547
3548
3549 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
3550
3551
3552 DitContentRule ditContentRule = new DitContentRule( oid );
3553 int elementsSeen = 0;
3554
3555 while ( true )
3556 {
3557 if ( startsWith( reader, pos, RPAREN ) )
3558 {
3559 pos.start++;
3560 break;
3561 }
3562
3563 skipWhites( reader, pos, true );
3564
3565 if ( startsWith( pos, NAME_STR ) )
3566 {
3567 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.NAME, pos );
3568
3569 pos.start += NAME_STR.length();
3570
3571 skipWhites( reader, pos, true );
3572
3573 ditContentRule.setNames( getQDescrs( reader, pos, RELAXED ) );
3574 }
3575 else if ( startsWith( pos, DESC_STR ) )
3576 {
3577 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.DESC, pos );
3578
3579 pos.start += DESC_STR.length();
3580
3581 skipWhites( reader, pos, true );
3582
3583 ditContentRule.setDescription( getQDString( reader, pos ) );
3584 }
3585 else if ( startsWith( pos, OBSOLETE_STR ) )
3586 {
3587 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.OBSOLETE, pos );
3588
3589 pos.start += OBSOLETE_STR.length();
3590
3591 ditContentRule.setObsolete( true );
3592 }
3593 else if ( startsWith( pos, AUX_STR ) )
3594 {
3595 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.AUX, pos );
3596
3597 pos.start += AUX_STR.length();
3598
3599 skipWhites( reader, pos, true );
3600
3601 List<String> aux = getOidsRelaxed( reader, pos );
3602
3603 ditContentRule.setAuxObjectClassOids( aux );
3604 }
3605 else if ( startsWith( pos, MUST_STR ) )
3606 {
3607 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.MUST, pos );
3608
3609 pos.start += MUST_STR.length();
3610
3611 skipWhites( reader, pos, true );
3612
3613 List<String> must = getOidsRelaxed( reader, pos );
3614
3615 ditContentRule.setMustAttributeTypeOids( must );
3616 }
3617 else if ( startsWith( pos, MAY_STR ) )
3618 {
3619 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.MAY, pos );
3620
3621 pos.start += MAY_STR.length();
3622
3623 skipWhites( reader, pos, true );
3624
3625 List<String> may = getOidsRelaxed( reader, pos );
3626
3627 ditContentRule.setMayAttributeTypeOids( may );
3628 }
3629 else if ( startsWith( pos, NOT_STR ) )
3630 {
3631 elementsSeen = checkElement( elementsSeen, DitContentRuleElements.NOT, pos );
3632
3633 pos.start += NOT_STR.length();
3634
3635 skipWhites( reader, pos, true );
3636
3637 List<String> not = getOidsRelaxed( reader, pos );
3638
3639 ditContentRule.setNotAttributeTypeOids( not );
3640 }
3641 else if ( startsWith( pos, EXTENSION_PREFIX ) )
3642 {
3643 processExtension( reader, pos, ditContentRule );
3644 }
3645 else if ( startsWith( reader, pos, RPAREN ) )
3646 {
3647 pos.start++;
3648
3649 break;
3650 }
3651 else
3652 {
3653
3654 throw new LdapSchemaException( I18n.err( I18n.ERR_13809_DCR_DESCRIPTION_INVALID,
3655 pos.lineNumber, pos.start ) );
3656 }
3657 }
3658
3659 return ditContentRule;
3660 }
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686 public DitStructureRule parseDitStructureRule( String ditStructureRuleDescription ) throws ParseException
3687 {
3688 if ( ( ditStructureRuleDescription == null ) || Strings.isEmpty( ditStructureRuleDescription.trim() ) )
3689 {
3690 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
3691 }
3692
3693 try ( Reader reader = new BufferedReader( new StringReader( ditStructureRuleDescription ) ) )
3694 {
3695 PosSchema pos = new PosSchema();
3696
3697 if ( isQuirksModeEnabled )
3698 {
3699 return parseDitStructureRuleRelaxed( reader, pos, objectIdentifierMacros );
3700 }
3701 else
3702 {
3703 return parseDitStructureRuleStrict( reader, pos );
3704 }
3705 }
3706 catch ( IOException | LdapSchemaException e )
3707 {
3708 throw new ParseException( e.getMessage(), 0 );
3709 }
3710 }
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738 private static DitStructureRule parseDitStructureRuleStrict( Reader reader, PosSchema pos )
3739 throws IOException, LdapSchemaException
3740 {
3741
3742 skipWhites( reader, pos, false );
3743
3744
3745 if ( pos.line.charAt( pos.start ) != LPAREN )
3746 {
3747 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
3748 pos.lineNumber, pos.start ) );
3749 }
3750 else
3751 {
3752 pos.start++;
3753 }
3754
3755
3756 skipWhites( reader, pos, false );
3757
3758
3759 int ruleId = getRuleId( pos );
3760
3761 DitStructureRule ditStructureRule = new DitStructureRule( ruleId );
3762 int elementsSeen = 0;
3763 boolean hasForm = false;
3764
3765 while ( true )
3766 {
3767 if ( startsWith( reader, pos, RPAREN ) )
3768 {
3769 pos.start++;
3770 break;
3771 }
3772
3773 skipWhites( reader, pos, true );
3774
3775 if ( startsWith( pos, NAME_STR ) )
3776 {
3777 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.NAME, pos );
3778
3779 pos.start += NAME_STR.length();
3780
3781 skipWhites( reader, pos, true );
3782
3783 ditStructureRule.setNames( getQDescrs( reader, pos, STRICT ) );
3784 }
3785 else if ( startsWith( pos, DESC_STR ) )
3786 {
3787 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.DESC, pos );
3788
3789 pos.start += DESC_STR.length();
3790
3791 skipWhites( reader, pos, true );
3792
3793 ditStructureRule.setDescription( getQDString( reader, pos ) );
3794 }
3795 else if ( startsWith( pos, OBSOLETE_STR ) )
3796 {
3797 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.OBSOLETE, pos );
3798
3799 pos.start += OBSOLETE_STR.length();
3800
3801 ditStructureRule.setObsolete( true );
3802 }
3803 else if ( startsWith( pos, FORM_STR ) )
3804 {
3805 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.FORM, pos );
3806
3807 pos.start += FORM_STR.length();
3808
3809 skipWhites( reader, pos, true );
3810
3811 String form = getOidStrict( pos );
3812
3813 ditStructureRule.setForm( form );
3814 hasForm = true;
3815 }
3816 else if ( startsWith( pos, SUP_STR ) )
3817 {
3818 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.SUP, pos );
3819
3820 pos.start += SUP_STR.length();
3821
3822 skipWhites( reader, pos, true );
3823
3824 List<Integer> superRules = getRuleIds( reader, pos );
3825
3826 ditStructureRule.setSuperRules( superRules );
3827 }
3828 else if ( startsWith( pos, EXTENSION_PREFIX ) )
3829 {
3830 processExtension( reader, pos, ditStructureRule );
3831 }
3832 else if ( startsWith( reader, pos, RPAREN ) )
3833 {
3834 pos.start++;
3835 break;
3836 }
3837 else
3838 {
3839
3840 throw new LdapSchemaException( I18n.err( I18n.ERR_13809_DCR_DESCRIPTION_INVALID,
3841 pos.lineNumber, pos.start ) );
3842 }
3843 }
3844
3845
3846 if ( !hasForm )
3847 {
3848 throw new LdapSchemaException( I18n.err( I18n.ERR_13812_FORM_REQUIRED,
3849 pos.lineNumber, pos.start ) );
3850 }
3851
3852 return ditStructureRule;
3853 }
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882 private static DitStructureRule parseDitStructureRuleRelaxed( Reader reader, PosSchema pos,
3883 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
3884 throws IOException, LdapSchemaException
3885 {
3886
3887 skipWhites( reader, pos, false );
3888
3889
3890 if ( pos.line.charAt( pos.start ) != LPAREN )
3891 {
3892 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
3893 pos.lineNumber, pos.start ) );
3894 }
3895 else
3896 {
3897 pos.start++;
3898 }
3899
3900
3901 skipWhites( reader, pos, false );
3902
3903
3904 int ruleId = getRuleId( pos );
3905
3906 DitStructureRule ditStructureRule = new DitStructureRule( ruleId );
3907 int elementsSeen = 0;
3908 boolean hasForm = false;
3909
3910 while ( true )
3911 {
3912 if ( startsWith( reader, pos, RPAREN ) )
3913 {
3914 pos.start++;
3915 break;
3916 }
3917
3918 skipWhites( reader, pos, true );
3919
3920 if ( startsWith( pos, NAME_STR ) )
3921 {
3922 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.NAME, pos );
3923
3924 pos.start += NAME_STR.length();
3925
3926 skipWhites( reader, pos, true );
3927
3928 ditStructureRule.setNames( getQDescrs( reader, pos, RELAXED ) );
3929 }
3930 else if ( startsWith( pos, DESC_STR ) )
3931 {
3932 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.DESC, pos );
3933
3934 pos.start += DESC_STR.length();
3935
3936 skipWhites( reader, pos, true );
3937
3938 ditStructureRule.setDescription( getQDString( reader, pos ) );
3939 }
3940 else if ( startsWith( pos, OBSOLETE_STR ) )
3941 {
3942 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.OBSOLETE, pos );
3943
3944 pos.start += OBSOLETE_STR.length();
3945
3946 ditStructureRule.setObsolete( true );
3947 }
3948 else if ( startsWith( pos, FORM_STR ) )
3949 {
3950 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.FORM, pos );
3951
3952 pos.start += FORM_STR.length();
3953
3954 skipWhites( reader, pos, true );
3955
3956 String form = getOidRelaxed( pos, UN_QUOTED );
3957
3958 ditStructureRule.setForm( form );
3959 hasForm = true;
3960 }
3961 else if ( startsWith( pos, SUP_STR ) )
3962 {
3963 elementsSeen = checkElement( elementsSeen, DitStructureRuleElements.SUP, pos );
3964
3965 pos.start += SUP_STR.length();
3966
3967 skipWhites( reader, pos, true );
3968
3969 List<Integer> superRules = getRuleIds( reader, pos );
3970
3971 ditStructureRule.setSuperRules( superRules );
3972 }
3973 else if ( startsWith( pos, EXTENSION_PREFIX ) )
3974 {
3975 processExtension( reader, pos, ditStructureRule );
3976 }
3977 else if ( startsWith( reader, pos, RPAREN ) )
3978 {
3979 pos.start++;
3980 break;
3981 }
3982 else
3983 {
3984
3985 throw new LdapSchemaException( I18n.err( I18n.ERR_13809_DCR_DESCRIPTION_INVALID,
3986 pos.lineNumber, pos.start ) );
3987 }
3988 }
3989
3990 if ( !hasForm )
3991 {
3992 throw new LdapSchemaException( I18n.err( I18n.ERR_13812_FORM_REQUIRED,
3993 pos.lineNumber, pos.start ) );
3994 }
3995
3996 return ditStructureRule;
3997 }
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022 public LdapComparatorDescription parseLdapComparator( String ldapComparatorDescription ) throws ParseException
4023 {
4024 if ( ( ldapComparatorDescription == null ) || Strings.isEmpty( ldapComparatorDescription.trim() ) )
4025 {
4026 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
4027 }
4028
4029 try ( Reader reader = new BufferedReader( new StringReader( ldapComparatorDescription ) ) )
4030 {
4031 PosSchema pos = new PosSchema();
4032
4033 if ( isQuirksModeEnabled )
4034 {
4035 return parseLdapComparatorRelaxed( reader, pos, objectIdentifierMacros );
4036 }
4037 else
4038 {
4039 return parseLdapComparatorStrict( reader, pos, objectIdentifierMacros );
4040 }
4041 }
4042 catch ( IOException | LdapSchemaException e )
4043 {
4044 throw new ParseException( e.getMessage(), 0 );
4045 }
4046 }
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074 private static LdapComparatorDescription parseLdapComparatorStrict( Reader reader, PosSchema pos,
4075 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
4076 {
4077
4078 skipWhites( reader, pos, false );
4079
4080
4081 if ( pos.line.charAt( pos.start ) != LPAREN )
4082 {
4083 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
4084 pos.lineNumber, pos.start ) );
4085 }
4086 else
4087 {
4088 pos.start++;
4089 }
4090
4091
4092 skipWhites( reader, pos, false );
4093
4094
4095 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
4096
4097
4098 if ( !Oid.isOid( oid ) )
4099 {
4100 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
4101 }
4102
4103 LdapComparatorDescription ldapComparator = new LdapComparatorDescription( oid );
4104 int elementsSeen = 0;
4105 boolean hasFqcn = false;
4106 boolean hasByteCode = false;
4107
4108 while ( true )
4109 {
4110 if ( startsWith( reader, pos, RPAREN ) )
4111 {
4112 pos.start++;
4113 break;
4114 }
4115
4116 skipWhites( reader, pos, true );
4117
4118 if ( startsWith( pos, DESC_STR ) )
4119 {
4120 elementsSeen = checkElement( elementsSeen, LdapComparatorElements.DESC, pos );
4121
4122 pos.start += DESC_STR.length();
4123
4124 skipWhites( reader, pos, true );
4125
4126 ldapComparator.setDescription( getQDString( reader, pos ) );
4127 }
4128 else if ( startsWith( pos, FQCN_STR ) )
4129 {
4130 elementsSeen = checkElement( elementsSeen, LdapComparatorElements.FQCN, pos );
4131
4132 pos.start += FQCN_STR.length();
4133
4134 skipWhites( reader, pos, true );
4135
4136 String fqcn = getFqcn( pos );
4137 ldapComparator.setFqcn( fqcn );
4138 hasFqcn = true;
4139 }
4140 else if ( startsWith( pos, BYTECODE_STR ) )
4141 {
4142 elementsSeen = checkElement( elementsSeen, LdapComparatorElements.BYTECODE, pos );
4143
4144 pos.start += BYTECODE_STR.length();
4145
4146 skipWhites( reader, pos, true );
4147
4148 String byteCode = getByteCode( pos );
4149 ldapComparator.setBytecode( byteCode );
4150 hasByteCode = true;
4151 }
4152 else if ( startsWith( pos, EXTENSION_PREFIX ) )
4153 {
4154 processExtension( reader, pos, ldapComparator );
4155 }
4156 else if ( startsWith( reader, pos, RPAREN ) )
4157 {
4158 pos.start++;
4159 break;
4160 }
4161 else
4162 {
4163
4164 throw new LdapSchemaException( I18n.err( I18n.ERR_13825_COMP_DESCRIPTION_INVALID,
4165 pos.lineNumber, pos.start ) );
4166 }
4167 }
4168
4169
4170 if ( !hasFqcn )
4171 {
4172 throw new LdapSchemaException( I18n.err( I18n.ERR_13819_FQCN_REQUIRED,
4173 pos.lineNumber, pos.start ) );
4174 }
4175
4176 if ( ( hasByteCode ) && ( ldapComparator.getBytecode().length() % 4 != 0 ) )
4177 {
4178 throw new LdapSchemaException( I18n.err( I18n.ERR_13820_BYTE_CODE_REQUIRED,
4179 pos.lineNumber, pos.start ) );
4180 }
4181
4182 return ldapComparator;
4183 }
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211 private static LdapComparatorDescription parseLdapComparatorRelaxed( Reader reader, PosSchema pos,
4212 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
4213 throws IOException, LdapSchemaException
4214 {
4215
4216 skipWhites( reader, pos, false );
4217
4218
4219 if ( pos.line.charAt( pos.start ) != LPAREN )
4220 {
4221 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
4222 pos.lineNumber, pos.start ) );
4223 }
4224 else
4225 {
4226 pos.start++;
4227 }
4228
4229
4230 skipWhites( reader, pos, false );
4231
4232
4233 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
4234
4235 LdapComparatorDescription ldapComparator = new LdapComparatorDescription( oid );
4236 int elementsSeen = 0;
4237
4238 while ( true )
4239 {
4240 if ( startsWith( reader, pos, RPAREN ) )
4241 {
4242 pos.start++;
4243 break;
4244 }
4245
4246 skipWhites( reader, pos, true );
4247
4248 if ( startsWith( pos, DESC_STR ) )
4249 {
4250 elementsSeen = checkElement( elementsSeen, LdapComparatorElements.DESC, pos );
4251
4252 pos.start += DESC_STR.length();
4253
4254 skipWhites( reader, pos, true );
4255
4256 ldapComparator.setDescription( getQDString( reader, pos ) );
4257 }
4258 else if ( startsWith( pos, FQCN_STR ) )
4259 {
4260 elementsSeen = checkElement( elementsSeen, LdapComparatorElements.FQCN, pos );
4261
4262 pos.start += FQCN_STR.length();
4263
4264 skipWhites( reader, pos, true );
4265
4266 String fqcn = getFqcn( pos );
4267 ldapComparator.setFqcn( fqcn );
4268 }
4269 else if ( startsWith( pos, BYTECODE_STR ) )
4270 {
4271 elementsSeen = checkElement( elementsSeen, LdapComparatorElements.BYTECODE, pos );
4272
4273 pos.start += BYTECODE_STR.length();
4274
4275 skipWhites( reader, pos, true );
4276
4277 String byteCode = getByteCode( pos );
4278 ldapComparator.setBytecode( byteCode );
4279 }
4280 else if ( startsWith( pos, EXTENSION_PREFIX ) )
4281 {
4282 processExtension( reader, pos, ldapComparator );
4283 }
4284 else if ( startsWith( reader, pos, RPAREN ) )
4285 {
4286 pos.start++;
4287 break;
4288 }
4289 else
4290 {
4291
4292 throw new LdapSchemaException( I18n.err( I18n.ERR_13825_COMP_DESCRIPTION_INVALID,
4293 pos.lineNumber, pos.start ) );
4294 }
4295 }
4296
4297 return ldapComparator;
4298 }
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316 public LdapSyntax parseLdapSyntax( String ldapSyntaxDescription ) throws ParseException
4317 {
4318 if ( ( ldapSyntaxDescription == null ) || Strings.isEmpty( ldapSyntaxDescription.trim() ) )
4319 {
4320 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
4321 }
4322
4323 try ( Reader reader = new BufferedReader( new StringReader( ldapSyntaxDescription ) ) )
4324 {
4325 PosSchema pos = new PosSchema();
4326
4327 if ( isQuirksModeEnabled )
4328 {
4329 return parseLdapSyntaxRelaxed( reader, pos, objectIdentifierMacros );
4330 }
4331 else
4332 {
4333 return parseLdapSyntaxStrict( reader, pos, objectIdentifierMacros );
4334 }
4335 }
4336 catch ( IOException | LdapSchemaException e )
4337 {
4338 throw new ParseException( e.getMessage(), 0 );
4339 }
4340 }
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361 private static LdapSyntax parseLdapSyntaxStrict( Reader reader, PosSchema pos,
4362 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
4363 {
4364
4365 skipWhites( reader, pos, false );
4366
4367
4368 if ( pos.line.charAt( pos.start ) != LPAREN )
4369 {
4370 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
4371 pos.lineNumber, pos.start ) );
4372 }
4373 else
4374 {
4375 pos.start++;
4376 }
4377
4378
4379 skipWhites( reader, pos, false );
4380
4381
4382 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
4383
4384
4385 if ( !Oid.isOid( oid ) )
4386 {
4387 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
4388 }
4389
4390 LdapSyntax ldapSyntax = new LdapSyntax( oid );
4391 int elementsSeen = 0;
4392
4393 while ( true )
4394 {
4395 if ( startsWith( reader, pos, RPAREN ) )
4396 {
4397 pos.start++;
4398 break;
4399 }
4400
4401 skipWhites( reader, pos, true );
4402
4403 if ( startsWith( pos, DESC_STR ) )
4404 {
4405 elementsSeen = checkElement( elementsSeen, LdapSyntaxElements.DESC, pos );
4406
4407 pos.start += DESC_STR.length();
4408
4409 skipWhites( reader, pos, true );
4410
4411 ldapSyntax.setDescription( getQDString( reader, pos ) );
4412 }
4413 else if ( startsWith( pos, EXTENSION_PREFIX ) )
4414 {
4415 processExtension( reader, pos, ldapSyntax );
4416 }
4417 else if ( startsWith( reader, pos, RPAREN ) )
4418 {
4419 pos.start++;
4420 break;
4421 }
4422 else
4423 {
4424
4425 throw new LdapSchemaException( I18n.err( I18n.ERR_13807_SYN_DESCRIPTION_INVALID,
4426 pos.lineNumber, pos.start ) );
4427 }
4428 }
4429
4430 return ldapSyntax;
4431 }
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452 private static LdapSyntax parseLdapSyntaxRelaxed( Reader reader, PosSchema pos,
4453 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
4454 {
4455
4456 skipWhites( reader, pos, false );
4457
4458
4459 if ( pos.line.charAt( pos.start ) != LPAREN )
4460 {
4461 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
4462 pos.lineNumber, pos.start ) );
4463 }
4464 else
4465 {
4466 pos.start++;
4467 }
4468
4469
4470 skipWhites( reader, pos, false );
4471
4472
4473 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
4474
4475 LdapSyntax ldapSyntax = new LdapSyntax( oid );
4476 int elementsSeen = 0;
4477
4478 while ( true )
4479 {
4480 if ( startsWith( reader, pos, RPAREN ) )
4481 {
4482 pos.start++;
4483 break;
4484 }
4485
4486 skipWhites( reader, pos, true );
4487
4488 if ( startsWith( pos, DESC_STR ) )
4489 {
4490 elementsSeen = checkElement( elementsSeen, LdapSyntaxElements.DESC, pos );
4491
4492 pos.start += DESC_STR.length();
4493
4494 skipWhites( reader, pos, true );
4495
4496 ldapSyntax.setDescription( getQDString( reader, pos ) );
4497 }
4498 else if ( startsWith( pos, EXTENSION_PREFIX ) )
4499 {
4500 processExtension( reader, pos, ldapSyntax );
4501 }
4502 else if ( startsWith( reader, pos, RPAREN ) )
4503 {
4504 pos.start++;
4505 break;
4506 }
4507 else
4508 {
4509
4510 throw new LdapSchemaException( I18n.err( I18n.ERR_13807_SYN_DESCRIPTION_INVALID,
4511 pos.lineNumber, pos.start ) );
4512 }
4513 }
4514
4515 return ldapSyntax;
4516 }
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537 public MatchingRule parseMatchingRule( String matchingRuleDescription ) throws ParseException
4538 {
4539 if ( ( matchingRuleDescription == null ) || Strings.isEmpty( matchingRuleDescription.trim() ) )
4540 {
4541 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
4542 }
4543
4544 try ( Reader reader = new BufferedReader( new StringReader( matchingRuleDescription ) ) )
4545 {
4546 PosSchema pos = new PosSchema();
4547
4548 if ( isQuirksModeEnabled )
4549 {
4550 return parseMatchingRuleRelaxed( reader, pos, objectIdentifierMacros );
4551 }
4552 else
4553 {
4554 return parseMatchingRuleStrict( reader, pos, objectIdentifierMacros );
4555 }
4556 }
4557 catch ( IOException | LdapSchemaException e )
4558 {
4559 throw new ParseException( e.getMessage(), 0 );
4560 }
4561 }
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585 private static MatchingRule parseMatchingRuleStrict( Reader reader, PosSchema pos,
4586 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
4587 {
4588
4589 skipWhites( reader, pos, false );
4590
4591
4592 if ( pos.line.charAt( pos.start ) != LPAREN )
4593 {
4594 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
4595 pos.lineNumber, pos.start ) );
4596 }
4597 else
4598 {
4599 pos.start++;
4600 }
4601
4602
4603 skipWhites( reader, pos, false );
4604
4605
4606 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
4607
4608
4609 if ( !Oid.isOid( oid ) )
4610 {
4611 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
4612 }
4613
4614 MatchingRule matchingRule = new MatchingRule( oid );
4615 int elementsSeen = 0;
4616 boolean hasSyntax = false;
4617
4618 while ( true )
4619 {
4620 if ( startsWith( reader, pos, RPAREN ) )
4621 {
4622 pos.start++;
4623 break;
4624 }
4625
4626 skipWhites( reader, pos, true );
4627
4628 if ( startsWith( pos, NAME_STR ) )
4629 {
4630 elementsSeen = checkElement( elementsSeen, MatchingRuleElements.NAME, pos );
4631
4632 pos.start += NAME_STR.length();
4633
4634 skipWhites( reader, pos, true );
4635
4636 matchingRule.setNames( getQDescrs( reader, pos, STRICT ) );
4637 }
4638 else if ( startsWith( pos, DESC_STR ) )
4639 {
4640 elementsSeen = checkElement( elementsSeen, MatchingRuleElements.DESC, pos );
4641
4642 pos.start += DESC_STR.length();
4643
4644 skipWhites( reader, pos, true );
4645
4646 matchingRule.setDescription( getQDString( reader, pos ) );
4647 }
4648 else if ( startsWith( pos, OBSOLETE_STR ) )
4649 {
4650 elementsSeen = checkElement( elementsSeen, MatchingRuleElements.OBSOLETE, pos );
4651
4652 pos.start += OBSOLETE_STR.length();
4653
4654 matchingRule.setObsolete( true );
4655 }
4656 else if ( startsWith( pos, SYNTAX_STR ) )
4657 {
4658 elementsSeen = checkElement( elementsSeen, MatchingRuleElements.SYNTAX, pos );
4659
4660 pos.start += SYNTAX_STR.length();
4661
4662 skipWhites( reader, pos, true );
4663
4664 String syntaxOid = getNumericOid( pos );
4665
4666 matchingRule.setSyntaxOid( syntaxOid );
4667 hasSyntax = true;
4668 }
4669 else if ( startsWith( pos, EXTENSION_PREFIX ) )
4670 {
4671 processExtension( reader, pos, matchingRule );
4672 }
4673 else if ( startsWith( reader, pos, RPAREN ) )
4674 {
4675 pos.start++;
4676 break;
4677 }
4678 else
4679 {
4680
4681 throw new LdapSchemaException( I18n.err( I18n.ERR_13781_MR_DESCRIPTION_INVALID,
4682 pos.lineNumber, pos.start ) );
4683 }
4684 }
4685
4686
4687 if ( !hasSyntax )
4688 {
4689 throw new LdapSchemaException( I18n.err( I18n.ERR_13808_SYNTAX_REQUIRED,
4690 pos.lineNumber, pos.start ) );
4691 }
4692
4693 return matchingRule;
4694 }
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718 private static MatchingRule parseMatchingRuleRelaxed( Reader reader, PosSchema pos,
4719 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
4720 throws IOException, LdapSchemaException
4721 {
4722
4723 skipWhites( reader, pos, false );
4724
4725
4726 if ( pos.line.charAt( pos.start ) != LPAREN )
4727 {
4728 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
4729 pos.lineNumber, pos.start ) );
4730 }
4731 else
4732 {
4733 pos.start++;
4734 }
4735
4736
4737 skipWhites( reader, pos, false );
4738
4739
4740 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
4741
4742 MatchingRule matchingRule = new MatchingRule( oid );
4743 int elementsSeen = 0;
4744
4745 while ( true )
4746 {
4747 if ( startsWith( reader, pos, RPAREN ) )
4748 {
4749 pos.start++;
4750 break;
4751 }
4752
4753 skipWhites( reader, pos, true );
4754
4755 if ( startsWith( pos, NAME_STR ) )
4756 {
4757 elementsSeen = checkElement( elementsSeen, MatchingRuleElements.NAME, pos );
4758
4759 pos.start += NAME_STR.length();
4760
4761 skipWhites( reader, pos, true );
4762
4763 matchingRule.setNames( getQDescrs( reader, pos, RELAXED ) );
4764 }
4765 else if ( startsWith( pos, DESC_STR ) )
4766 {
4767 elementsSeen = checkElement( elementsSeen, MatchingRuleElements.DESC, pos );
4768
4769 pos.start += DESC_STR.length();
4770
4771 skipWhites( reader, pos, true );
4772
4773 matchingRule.setDescription( getQDString( reader, pos ) );
4774 }
4775 else if ( startsWith( pos, OBSOLETE_STR ) )
4776 {
4777 elementsSeen = checkElement( elementsSeen, MatchingRuleElements.OBSOLETE, pos );
4778
4779 pos.start += OBSOLETE_STR.length();
4780
4781 matchingRule.setObsolete( true );
4782 }
4783 else if ( startsWith( pos, SYNTAX_STR ) )
4784 {
4785 elementsSeen = checkElement( elementsSeen, MatchingRuleElements.SYNTAX, pos );
4786
4787 pos.start += SYNTAX_STR.length();
4788
4789 skipWhites( reader, pos, true );
4790
4791 String syntaxOid = getNumericOid( pos );
4792
4793 matchingRule.setSyntaxOid( syntaxOid );
4794 }
4795 else if ( startsWith( pos, EXTENSION_PREFIX ) )
4796 {
4797 processExtension( reader, pos, matchingRule );
4798 }
4799 else if ( startsWith( reader, pos, RPAREN ) )
4800 {
4801 pos.start++;
4802 break;
4803 }
4804 else
4805 {
4806
4807 throw new LdapSchemaException( I18n.err( I18n.ERR_13781_MR_DESCRIPTION_INVALID,
4808 pos.lineNumber, pos.start ) );
4809 }
4810 }
4811
4812 return matchingRule;
4813 }
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834 public MatchingRuleUse parseMatchingRuleUse( String matchingRuleUseDescription ) throws ParseException
4835 {
4836 if ( ( matchingRuleUseDescription == null ) || Strings.isEmpty( matchingRuleUseDescription.trim() ) )
4837 {
4838 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
4839 }
4840
4841 try ( Reader reader = new BufferedReader( new StringReader( matchingRuleUseDescription ) ) )
4842 {
4843 PosSchema pos = new PosSchema();
4844
4845 if ( isQuirksModeEnabled )
4846 {
4847 return parseMatchingRuleUseRelaxed( reader, pos, objectIdentifierMacros );
4848 }
4849 else
4850 {
4851 return parseMatchingRuleUseStrict( reader, pos, objectIdentifierMacros );
4852 }
4853 }
4854 catch ( IOException | LdapSchemaException e )
4855 {
4856 throw new ParseException( e.getMessage(), 0 );
4857 }
4858 }
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882 private static MatchingRuleUse parseMatchingRuleUseStrict( Reader reader, PosSchema pos,
4883 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
4884 {
4885
4886 skipWhites( reader, pos, false );
4887
4888
4889 if ( pos.line.charAt( pos.start ) != LPAREN )
4890 {
4891 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
4892 pos.lineNumber, pos.start ) );
4893 }
4894 else
4895 {
4896 pos.start++;
4897 }
4898
4899
4900 skipWhites( reader, pos, false );
4901
4902
4903 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
4904
4905
4906 if ( !Oid.isOid( oid ) )
4907 {
4908 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
4909 }
4910
4911 MatchingRuleUse matchingRuleUse = new MatchingRuleUse( oid );
4912 int elementsSeen = 0;
4913 boolean hasApplies = false;
4914
4915 while ( true )
4916 {
4917 if ( startsWith( reader, pos, RPAREN ) )
4918 {
4919 pos.start++;
4920 break;
4921 }
4922
4923 skipWhites( reader, pos, false );
4924
4925 if ( startsWith( pos, NAME_STR ) )
4926 {
4927 elementsSeen = checkElement( elementsSeen, MatchingRuleUseElements.NAME, pos );
4928
4929 pos.start += NAME_STR.length();
4930
4931 skipWhites( reader, pos, true );
4932
4933 matchingRuleUse.setNames( getQDescrs( reader, pos, STRICT ) );
4934 }
4935 else if ( startsWith( pos, DESC_STR ) )
4936 {
4937 elementsSeen = checkElement( elementsSeen, MatchingRuleUseElements.DESC, pos );
4938
4939 pos.start += DESC_STR.length();
4940
4941 skipWhites( reader, pos, true );
4942
4943 matchingRuleUse.setDescription( getQDString( reader, pos ) );
4944 }
4945 else if ( startsWith( pos, OBSOLETE_STR ) )
4946 {
4947 elementsSeen = checkElement( elementsSeen, MatchingRuleUseElements.OBSOLETE, pos );
4948
4949 pos.start += OBSOLETE_STR.length();
4950
4951 matchingRuleUse.setObsolete( true );
4952 }
4953 else if ( startsWith( pos, APPLIES_STR ) )
4954 {
4955 elementsSeen = checkElement( elementsSeen, MatchingRuleUseElements.APPLIES, pos );
4956
4957 pos.start += APPLIES_STR.length();
4958
4959 skipWhites( reader, pos, true );
4960
4961 List<String> oids = getOidsStrict( reader, pos );
4962
4963 matchingRuleUse.setApplicableAttributeOids( oids );
4964 hasApplies = true;
4965 }
4966 else if ( startsWith( pos, EXTENSION_PREFIX ) )
4967 {
4968 processExtension( reader, pos, matchingRuleUse );
4969 }
4970 else if ( startsWith( reader, pos, RPAREN ) )
4971 {
4972 pos.start++;
4973 break;
4974 }
4975 else
4976 {
4977
4978 throw new LdapSchemaException( I18n.err( I18n.ERR_13815_MRU_DESCRIPTION_INVALID,
4979 pos.lineNumber, pos.start ) );
4980 }
4981 }
4982
4983
4984 if ( !hasApplies )
4985 {
4986 throw new LdapSchemaException( I18n.err( I18n.ERR_13814_APPLIES_REQUIRED,
4987 pos.lineNumber, pos.start ) );
4988 }
4989
4990 return matchingRuleUse;
4991 }
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015 private static MatchingRuleUse parseMatchingRuleUseRelaxed( Reader reader, PosSchema pos,
5016 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
5017 throws IOException, LdapSchemaException
5018 {
5019
5020 skipWhites( reader, pos, false );
5021
5022
5023 if ( pos.line.charAt( pos.start ) != LPAREN )
5024 {
5025 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
5026 pos.lineNumber, pos.start ) );
5027 }
5028 else
5029 {
5030 pos.start++;
5031 }
5032
5033
5034 skipWhites( reader, pos, false );
5035
5036
5037 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
5038
5039 MatchingRuleUse matchingRuleUse = new MatchingRuleUse( oid );
5040 int elementsSeen = 0;
5041
5042 while ( true )
5043 {
5044 if ( startsWith( reader, pos, RPAREN ) )
5045 {
5046 pos.start++;
5047 break;
5048 }
5049
5050 skipWhites( reader, pos, true );
5051
5052 if ( startsWith( pos, NAME_STR ) )
5053 {
5054 elementsSeen = checkElement( elementsSeen, MatchingRuleUseElements.NAME, pos );
5055
5056 pos.start += NAME_STR.length();
5057
5058 skipWhites( reader, pos, true );
5059
5060 matchingRuleUse.setNames( getQDescrs( reader, pos, RELAXED ) );
5061 }
5062 else if ( startsWith( pos, DESC_STR ) )
5063 {
5064 elementsSeen = checkElement( elementsSeen, MatchingRuleUseElements.DESC, pos );
5065
5066 pos.start += DESC_STR.length();
5067
5068 skipWhites( reader, pos, true );
5069
5070 matchingRuleUse.setDescription( getQDString( reader, pos ) );
5071 }
5072 else if ( startsWith( pos, OBSOLETE_STR ) )
5073 {
5074 elementsSeen = checkElement( elementsSeen, MatchingRuleUseElements.OBSOLETE, pos );
5075
5076 pos.start += OBSOLETE_STR.length();
5077
5078 matchingRuleUse.setObsolete( true );
5079 }
5080 else if ( startsWith( pos, APPLIES_STR ) )
5081 {
5082 elementsSeen = checkElement( elementsSeen, MatchingRuleUseElements.APPLIES, pos );
5083
5084 pos.start += APPLIES_STR.length();
5085
5086 skipWhites( reader, pos, true );
5087
5088 List<String> oids = getOidsRelaxed( reader, pos );
5089
5090 matchingRuleUse.setApplicableAttributeOids( oids );
5091 }
5092 else if ( startsWith( pos, EXTENSION_PREFIX ) )
5093 {
5094 processExtension( reader, pos, matchingRuleUse );
5095 }
5096 else if ( startsWith( reader, pos, RPAREN ) )
5097 {
5098 pos.start++;
5099 break;
5100 }
5101 else
5102 {
5103
5104 throw new LdapSchemaException( I18n.err( I18n.ERR_13815_MRU_DESCRIPTION_INVALID,
5105 pos.lineNumber, pos.start ) );
5106 }
5107 }
5108
5109 return matchingRuleUse;
5110 }
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133 public NameForm parseNameForm( String nameFormDescription ) throws ParseException
5134 {
5135 if ( ( nameFormDescription == null ) || Strings.isEmpty( nameFormDescription.trim() ) )
5136 {
5137 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
5138 }
5139
5140 try ( Reader reader = new BufferedReader( new StringReader( nameFormDescription ) ) )
5141 {
5142 PosSchema pos = new PosSchema();
5143
5144 if ( isQuirksModeEnabled )
5145 {
5146 return parseNameFormRelaxed( reader, pos, objectIdentifierMacros );
5147 }
5148 else
5149 {
5150 return parseNameFormStrict( reader, pos, objectIdentifierMacros );
5151 }
5152 }
5153 catch ( IOException | LdapSchemaException e )
5154 {
5155 throw new ParseException( e.getMessage(), 0 );
5156 }
5157 }
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183 private static NameForm parseNameFormStrict( Reader reader, PosSchema pos,
5184 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
5185 {
5186
5187 skipWhites( reader, pos, false );
5188
5189
5190 if ( pos.line.charAt( pos.start ) != LPAREN )
5191 {
5192 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
5193 pos.lineNumber, pos.start ) );
5194 }
5195 else
5196 {
5197 pos.start++;
5198 }
5199
5200
5201 skipWhites( reader, pos, false );
5202
5203
5204 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
5205
5206
5207 if ( !Oid.isOid( oid ) )
5208 {
5209 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
5210 }
5211
5212 NameForm nameForm = new NameForm( oid );
5213 int elementsSeen = 0;
5214 boolean hasOc = false;
5215 boolean hasMust = false;
5216
5217 while ( true )
5218 {
5219 if ( startsWith( reader, pos, RPAREN ) )
5220 {
5221 pos.start++;
5222 break;
5223 }
5224
5225 skipWhites( reader, pos, true );
5226
5227 if ( startsWith( pos, NAME_STR ) )
5228 {
5229 elementsSeen = checkElement( elementsSeen, NameFormElements.NAME, pos );
5230
5231 pos.start += NAME_STR.length();
5232
5233 skipWhites( reader, pos, true );
5234
5235 nameForm.setNames( getQDescrs( reader, pos, STRICT ) );
5236 }
5237 else if ( startsWith( pos, DESC_STR ) )
5238 {
5239 elementsSeen = checkElement( elementsSeen, NameFormElements.DESC, pos );
5240
5241 pos.start += DESC_STR.length();
5242
5243 skipWhites( reader, pos, true );
5244
5245 nameForm.setDescription( getQDString( reader, pos ) );
5246 }
5247 else if ( startsWith( pos, OBSOLETE_STR ) )
5248 {
5249 elementsSeen = checkElement( elementsSeen, NameFormElements.OBSOLETE, pos );
5250
5251 pos.start += OBSOLETE_STR.length();
5252
5253 nameForm.setObsolete( true );
5254 }
5255 else if ( startsWith( pos, OC_STR ) )
5256 {
5257 elementsSeen = checkElement( elementsSeen, NameFormElements.OC, pos );
5258
5259 pos.start += OC_STR.length();
5260
5261 skipWhites( reader, pos, true );
5262
5263 String oc = getOidStrict( pos );
5264
5265 nameForm.setStructuralObjectClassOid( oc );
5266 hasOc = true;
5267 }
5268 else if ( startsWith( pos, MUST_STR ) )
5269 {
5270 elementsSeen = checkElement( elementsSeen, NameFormElements.MUST, pos );
5271
5272 pos.start += MUST_STR.length();
5273
5274 skipWhites( reader, pos, true );
5275
5276 List<String> must = getOidsStrict( reader, pos );
5277
5278 nameForm.setMustAttributeTypeOids( must );
5279 hasMust = true;
5280 }
5281 else if ( startsWith( pos, MAY_STR ) )
5282 {
5283 elementsSeen = checkElement( elementsSeen, NameFormElements.MAY, pos );
5284
5285 pos.start += MAY_STR.length();
5286
5287 skipWhites( reader, pos, true );
5288
5289 List<String> may = getOidsStrict( reader, pos );
5290
5291 nameForm.setMayAttributeTypeOids( may );
5292 }
5293 else if ( startsWith( pos, EXTENSION_PREFIX ) )
5294 {
5295 processExtension( reader, pos, nameForm );
5296 }
5297 else if ( startsWith( reader, pos, RPAREN ) )
5298 {
5299 pos.start++;
5300 break;
5301 }
5302 else
5303 {
5304
5305 throw new LdapSchemaException( I18n.err( I18n.ERR_13816_NF_DESCRIPTION_INVALID,
5306 pos.lineNumber, pos.start ) );
5307 }
5308 }
5309
5310
5311 if ( !hasOc )
5312 {
5313 throw new LdapSchemaException( I18n.err( I18n.ERR_13817_STRUCTURAL_OBJECT_CLASS_REQUIRED,
5314 pos.lineNumber, pos.start ) );
5315 }
5316
5317 if ( !hasMust )
5318 {
5319 throw new LdapSchemaException( I18n.err( I18n.ERR_13818_MUST_REQUIRED,
5320 pos.lineNumber, pos.start ) );
5321 }
5322
5323 return nameForm;
5324 }
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350 private static NameForm parseNameFormRelaxed( Reader reader, PosSchema pos,
5351 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
5352 throws IOException, LdapSchemaException
5353 {
5354
5355 skipWhites( reader, pos, false );
5356
5357
5358 if ( pos.line.charAt( pos.start ) != LPAREN )
5359 {
5360 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
5361 pos.lineNumber, pos.start ) );
5362 }
5363 else
5364 {
5365 pos.start++;
5366 }
5367
5368
5369 skipWhites( reader, pos, false );
5370
5371
5372 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
5373
5374 NameForm nameForm = new NameForm( oid );
5375 int elementsSeen = 0;
5376
5377 while ( true )
5378 {
5379 if ( startsWith( reader, pos, RPAREN ) )
5380 {
5381 pos.start++;
5382 break;
5383 }
5384
5385 skipWhites( reader, pos, true );
5386
5387 if ( startsWith( pos, NAME_STR ) )
5388 {
5389 elementsSeen = checkElement( elementsSeen, NameFormElements.NAME, pos );
5390
5391 pos.start += NAME_STR.length();
5392
5393 skipWhites( reader, pos, true );
5394
5395 nameForm.setNames( getQDescrs( reader, pos, RELAXED ) );
5396 }
5397 else if ( startsWith( pos, DESC_STR ) )
5398 {
5399 elementsSeen = checkElement( elementsSeen, NameFormElements.DESC, pos );
5400
5401 pos.start += DESC_STR.length();
5402
5403 skipWhites( reader, pos, true );
5404
5405 nameForm.setDescription( getQDString( reader, pos ) );
5406 }
5407 else if ( startsWith( pos, OBSOLETE_STR ) )
5408 {
5409 elementsSeen = checkElement( elementsSeen, NameFormElements.OBSOLETE, pos );
5410
5411 pos.start += OBSOLETE_STR.length();
5412
5413 nameForm.setObsolete( true );
5414 }
5415 else if ( startsWith( pos, OC_STR ) )
5416 {
5417 elementsSeen = checkElement( elementsSeen, NameFormElements.OC, pos );
5418
5419 pos.start += OC_STR.length();
5420
5421 skipWhites( reader, pos, true );
5422
5423 String oc = getOidRelaxed( pos, UN_QUOTED );
5424
5425 nameForm.setStructuralObjectClassOid( oc );
5426 }
5427 else if ( startsWith( pos, MUST_STR ) )
5428 {
5429 elementsSeen = checkElement( elementsSeen, NameFormElements.MUST, pos );
5430
5431 pos.start += MUST_STR.length();
5432
5433 skipWhites( reader, pos, true );
5434
5435 List<String> must = getOidsRelaxed( reader, pos );
5436
5437 nameForm.setMustAttributeTypeOids( must );
5438 }
5439 else if ( startsWith( pos, MAY_STR ) )
5440 {
5441 elementsSeen = checkElement( elementsSeen, NameFormElements.MAY, pos );
5442
5443 pos.start += MAY_STR.length();
5444
5445 skipWhites( reader, pos, true );
5446
5447 List<String> may = getOidsRelaxed( reader, pos );
5448
5449 nameForm.setMayAttributeTypeOids( may );
5450 }
5451 else if ( startsWith( pos, EXTENSION_PREFIX ) )
5452 {
5453 processExtension( reader, pos, nameForm );
5454 }
5455 else if ( startsWith( reader, pos, RPAREN ) )
5456 {
5457 pos.start++;
5458 break;
5459 }
5460 else
5461 {
5462
5463 throw new LdapSchemaException( I18n.err( I18n.ERR_13816_NF_DESCRIPTION_INVALID,
5464 pos.lineNumber, pos.start ) );
5465 }
5466 }
5467
5468 return nameForm;
5469 }
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494 public NormalizerDescription parseNormalizer( String normalizerDescription ) throws ParseException
5495 {
5496 if ( ( normalizerDescription == null ) || Strings.isEmpty( normalizerDescription.trim() ) )
5497 {
5498 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
5499 }
5500
5501 try ( Reader reader = new BufferedReader( new StringReader( normalizerDescription ) ) )
5502 {
5503 PosSchema pos = new PosSchema();
5504
5505 if ( isQuirksModeEnabled )
5506 {
5507 return parseNormalizerRelaxed( reader, pos, objectIdentifierMacros );
5508 }
5509 else
5510 {
5511 return parseNormalizerStrict( reader, pos, objectIdentifierMacros );
5512 }
5513 }
5514 catch ( IOException | LdapSchemaException e )
5515 {
5516 throw new ParseException( e.getMessage(), 0 );
5517 }
5518 }
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546 private static NormalizerDescription parseNormalizerStrict( Reader reader, PosSchema pos,
5547 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
5548 {
5549
5550 skipWhites( reader, pos, false );
5551
5552
5553 if ( pos.line.charAt( pos.start ) != LPAREN )
5554 {
5555 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
5556 pos.lineNumber, pos.start ) );
5557 }
5558 else
5559 {
5560 pos.start++;
5561 }
5562
5563
5564 skipWhites( reader, pos, false );
5565
5566
5567 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
5568
5569
5570 if ( !Oid.isOid( oid ) )
5571 {
5572 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
5573 }
5574
5575 NormalizerDescription normalizer = new NormalizerDescription( oid );
5576 int elementsSeen = 0;
5577 boolean hasFqcn = false;
5578 boolean hasByteCode = false;
5579
5580 while ( true )
5581 {
5582 if ( startsWith( reader, pos, RPAREN ) )
5583 {
5584 pos.start++;
5585 break;
5586 }
5587
5588 skipWhites( reader, pos, true );
5589
5590 if ( startsWith( pos, DESC_STR ) )
5591 {
5592 elementsSeen = checkElement( elementsSeen, NormalizerElements.DESC, pos );
5593
5594 pos.start += DESC_STR.length();
5595
5596 skipWhites( reader, pos, true );
5597
5598 normalizer.setDescription( getQDString( reader, pos ) );
5599 }
5600 else if ( startsWith( pos, FQCN_STR ) )
5601 {
5602 elementsSeen = checkElement( elementsSeen, NormalizerElements.FQCN, pos );
5603
5604 pos.start += FQCN_STR.length();
5605
5606 skipWhites( reader, pos, true );
5607
5608 String fqcn = getFqcn( pos );
5609 normalizer.setFqcn( fqcn );
5610 hasFqcn = true;
5611 }
5612 else if ( startsWith( pos, BYTECODE_STR ) )
5613 {
5614 elementsSeen = checkElement( elementsSeen, NormalizerElements.BYTECODE, pos );
5615
5616 pos.start += BYTECODE_STR.length();
5617
5618 skipWhites( reader, pos, true );
5619
5620 String byteCode = getByteCode( pos );
5621 normalizer.setBytecode( byteCode );
5622 hasByteCode = true;
5623 }
5624 else if ( startsWith( pos, EXTENSION_PREFIX ) )
5625 {
5626 processExtension( reader, pos, normalizer );
5627 }
5628 else if ( startsWith( reader, pos, RPAREN ) )
5629 {
5630 pos.start++;
5631 break;
5632 }
5633 else
5634 {
5635
5636 throw new LdapSchemaException( I18n.err( I18n.ERR_13821_NORM_DESCRIPTION_INVALID,
5637 pos.lineNumber, pos.start ) );
5638 }
5639 }
5640
5641
5642 if ( !hasFqcn )
5643 {
5644 throw new LdapSchemaException( I18n.err( I18n.ERR_13819_FQCN_REQUIRED,
5645 pos.lineNumber, pos.start ) );
5646 }
5647
5648 if ( ( hasByteCode ) && ( normalizer.getBytecode().length() % 4 != 0 ) )
5649 {
5650 throw new LdapSchemaException( I18n.err( I18n.ERR_13820_BYTE_CODE_REQUIRED,
5651 pos.lineNumber, pos.start ) );
5652 }
5653
5654 return normalizer;
5655 }
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683 private static NormalizerDescription parseNormalizerRelaxed( Reader reader, PosSchema pos,
5684 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
5685 throws IOException, LdapSchemaException
5686 {
5687
5688 skipWhites( reader, pos, false );
5689
5690
5691 if ( pos.line.charAt( pos.start ) != LPAREN )
5692 {
5693 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
5694 pos.lineNumber, pos.start ) );
5695 }
5696 else
5697 {
5698 pos.start++;
5699 }
5700
5701
5702 skipWhites( reader, pos, false );
5703
5704
5705 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
5706
5707 NormalizerDescription normalizer = new NormalizerDescription( oid );
5708 int elementsSeen = 0;
5709
5710 while ( true )
5711 {
5712 if ( startsWith( reader, pos, RPAREN ) )
5713 {
5714 pos.start++;
5715 break;
5716 }
5717
5718 skipWhites( reader, pos, true );
5719
5720 if ( startsWith( pos, DESC_STR ) )
5721 {
5722 elementsSeen = checkElement( elementsSeen, NormalizerElements.DESC, pos );
5723
5724 pos.start += DESC_STR.length();
5725
5726 skipWhites( reader, pos, true );
5727
5728 normalizer.setDescription( getQDString( reader, pos ) );
5729 }
5730 else if ( startsWith( pos, FQCN_STR ) )
5731 {
5732 elementsSeen = checkElement( elementsSeen, NormalizerElements.FQCN, pos );
5733
5734 pos.start += FQCN_STR.length();
5735
5736 skipWhites( reader, pos, true );
5737
5738 String fqcn = getFqcn( pos );
5739 normalizer.setFqcn( fqcn );
5740 }
5741 else if ( startsWith( pos, BYTECODE_STR ) )
5742 {
5743 elementsSeen = checkElement( elementsSeen, NormalizerElements.BYTECODE, pos );
5744
5745 pos.start += BYTECODE_STR.length();
5746
5747 skipWhites( reader, pos, true );
5748
5749 String byteCode = getByteCode( pos );
5750 normalizer.setBytecode( byteCode );
5751 }
5752 else if ( startsWith( pos, EXTENSION_PREFIX ) )
5753 {
5754 processExtension( reader, pos, normalizer );
5755 }
5756 else if ( startsWith( reader, pos, RPAREN ) )
5757 {
5758 pos.start++;
5759 break;
5760 }
5761 else
5762 {
5763
5764 throw new LdapSchemaException( I18n.err( I18n.ERR_13821_NORM_DESCRIPTION_INVALID,
5765 pos.lineNumber, pos.start ) );
5766 }
5767 }
5768
5769 return normalizer;
5770 }
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796 public ObjectClass parseObjectClass( String objectClassDescription ) throws ParseException
5797 {
5798 if ( ( objectClassDescription == null ) || Strings.isEmpty( objectClassDescription.trim() ) )
5799 {
5800 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
5801 }
5802
5803 try ( Reader reader = new BufferedReader( new StringReader( objectClassDescription ) ) )
5804 {
5805 PosSchema pos = new PosSchema();
5806
5807 if ( isQuirksModeEnabled )
5808 {
5809 return parseObjectClassRelaxed( reader, pos, objectIdentifierMacros );
5810 }
5811 else
5812 {
5813 return parseObjectClassStrict( reader, pos, objectIdentifierMacros );
5814 }
5815 }
5816 catch ( IOException | LdapSchemaException e )
5817 {
5818 throw new ParseException( e.getMessage(), 0 );
5819 }
5820 }
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848 private static ObjectClass parseObjectClassStrict( Reader reader, PosSchema pos,
5849 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
5850 throws IOException, LdapSchemaException
5851 {
5852
5853 skipWhites( reader, pos, false );
5854
5855
5856 if ( pos.line.charAt( pos.start ) != LPAREN )
5857 {
5858 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
5859 pos.lineNumber, pos.start ) );
5860 }
5861 else
5862 {
5863 pos.start++;
5864 }
5865
5866
5867 skipWhites( reader, pos, false );
5868
5869
5870 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
5871
5872
5873 if ( !Oid.isOid( oid ) )
5874 {
5875 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
5876 }
5877
5878 ObjectClass objectClass = new ObjectClass( oid );
5879 int elementsSeen = 0;
5880
5881 while ( true )
5882 {
5883 if ( startsWith( reader, pos, RPAREN ) )
5884 {
5885 pos.start++;
5886 break;
5887 }
5888
5889 skipWhites( reader, pos, true );
5890
5891 if ( startsWith( pos, NAME_STR ) )
5892 {
5893 elementsSeen = checkElement( elementsSeen, ObjectClassElements.NAME, pos );
5894
5895 pos.start += NAME_STR.length();
5896
5897 skipWhites( reader, pos, true );
5898
5899 List<String> names = getQDescrs( reader, pos, STRICT );
5900 objectClass.setNames( names );
5901 }
5902 else if ( startsWith( pos, DESC_STR ) )
5903 {
5904 elementsSeen = checkElement( elementsSeen, ObjectClassElements.DESC, pos );
5905
5906 pos.start += DESC_STR.length();
5907
5908 skipWhites( reader, pos, true );
5909
5910 objectClass.setDescription( getQDString( reader, pos ) );
5911 }
5912 else if ( startsWith( pos, OBSOLETE_STR ) )
5913 {
5914 elementsSeen = checkElement( elementsSeen, ObjectClassElements.OBSOLETE, pos );
5915
5916 pos.start += OBSOLETE_STR.length();
5917
5918 objectClass.setObsolete( true );
5919 }
5920 else if ( startsWith( pos, SUP_STR ) )
5921 {
5922 elementsSeen = checkElement( elementsSeen, ObjectClassElements.SUP, pos );
5923
5924 pos.start += SUP_STR.length();
5925
5926 skipWhites( reader, pos, true );
5927
5928 List<String> superiorOids = getOidsStrict( reader, pos );
5929
5930 objectClass.setSuperiorOids( superiorOids );
5931 }
5932 else if ( startsWith( pos, ABSTRACT_STR ) )
5933 {
5934 elementsSeen = checkElement( elementsSeen, ObjectClassElements.ABSTRACT, pos );
5935
5936 pos.start += ABSTRACT_STR.length();
5937
5938 objectClass.setType( ObjectClassTypeEnum.ABSTRACT );
5939 }
5940 else if ( startsWith( pos, STRUCTURAL_STR ) )
5941 {
5942 elementsSeen = checkElement( elementsSeen, ObjectClassElements.STRUCTURAL, pos );
5943
5944 pos.start += STRUCTURAL_STR.length();
5945
5946 objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
5947 }
5948 else if ( startsWith( pos, AUXILIARY_STR ) )
5949 {
5950 elementsSeen = checkElement( elementsSeen, ObjectClassElements.AUXILIARY, pos );
5951
5952 pos.start += AUXILIARY_STR.length();
5953
5954 objectClass.setType( ObjectClassTypeEnum.AUXILIARY );
5955 }
5956 else if ( startsWith( pos, MUST_STR ) )
5957 {
5958 elementsSeen = checkElement( elementsSeen, ObjectClassElements.MUST, pos );
5959
5960 pos.start += MUST_STR.length();
5961
5962 skipWhites( reader, pos, true );
5963
5964 List<String> mustAttributeTypes = getOidsStrict( reader, pos );
5965 objectClass.setMustAttributeTypeOids( mustAttributeTypes );
5966 }
5967 else if ( startsWith( pos, MAY_STR ) )
5968 {
5969 elementsSeen = checkElement( elementsSeen, ObjectClassElements.MAY, pos );
5970
5971 pos.start += MAY_STR.length();
5972
5973 skipWhites( reader, pos, true );
5974
5975 List<String> mayAttributeTypes = getOidsStrict( reader, pos );
5976 objectClass.setMayAttributeTypeOids( mayAttributeTypes );
5977 }
5978 else if ( startsWith( pos, EXTENSION_PREFIX ) )
5979 {
5980 processExtension( reader, pos, objectClass );
5981 }
5982 else if ( startsWith( reader, pos, RPAREN ) )
5983 {
5984 pos.start++;
5985 break;
5986 }
5987 else
5988 {
5989
5990 throw new LdapSchemaException( I18n.err( I18n.ERR_13803_OC_DESCRIPTION_INVALID,
5991 pos.lineNumber, pos.start ) );
5992 }
5993 }
5994
5995 pos.start++;
5996
5997 return objectClass;
5998 }
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026 private static ObjectClass parseObjectClassRelaxed( Reader reader, PosSchema pos,
6027 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
6028 throws IOException, LdapSchemaException
6029 {
6030
6031 skipWhites( reader, pos, false );
6032
6033
6034 if ( pos.line.charAt( pos.start ) != LPAREN )
6035 {
6036 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
6037 pos.lineNumber, pos.start ) );
6038 }
6039 else
6040 {
6041 pos.start++;
6042 }
6043
6044
6045 skipWhites( reader, pos, false );
6046
6047
6048 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
6049
6050 ObjectClass objectClass = new ObjectClass( oid );
6051 int elementsSeen = 0;
6052
6053 while ( true )
6054 {
6055 if ( startsWith( reader, pos, RPAREN ) )
6056 {
6057 pos.start++;
6058 break;
6059 }
6060
6061 skipWhites( reader, pos, true );
6062
6063 if ( startsWith( pos, NAME_STR ) )
6064 {
6065 elementsSeen = checkElement( elementsSeen, ObjectClassElements.NAME, pos );
6066
6067 pos.start += NAME_STR.length();
6068
6069 skipWhites( reader, pos, true );
6070
6071 List<String> names = getQDescrs( reader, pos, RELAXED );
6072
6073 objectClass.setNames( names );
6074 }
6075 else if ( startsWith( pos, DESC_STR ) )
6076 {
6077 elementsSeen = checkElement( elementsSeen, ObjectClassElements.DESC, pos );
6078
6079 pos.start += DESC_STR.length();
6080
6081 skipWhites( reader, pos, true );
6082
6083 objectClass.setDescription( getQDString( reader, pos ) );
6084 }
6085 else if ( startsWith( pos, OBSOLETE_STR ) )
6086 {
6087 elementsSeen = checkElement( elementsSeen, ObjectClassElements.OBSOLETE, pos );
6088
6089 pos.start += OBSOLETE_STR.length();
6090
6091 objectClass.setObsolete( true );
6092 }
6093 else if ( startsWith( pos, SUP_STR ) )
6094 {
6095 elementsSeen = checkElement( elementsSeen, ObjectClassElements.SUP, pos );
6096
6097 pos.start += SUP_STR.length();
6098
6099 skipWhites( reader, pos, true );
6100
6101 List<String> superiorOids = getOidsRelaxed( reader, pos );
6102
6103 objectClass.setSuperiorOids( superiorOids );
6104 }
6105 else if ( startsWith( pos, ABSTRACT_STR ) )
6106 {
6107 elementsSeen = checkElement( elementsSeen, ObjectClassElements.ABSTRACT, pos );
6108
6109 pos.start += ABSTRACT_STR.length();
6110
6111 objectClass.setType( ObjectClassTypeEnum.ABSTRACT );
6112 }
6113 else if ( startsWith( pos, STRUCTURAL_STR ) )
6114 {
6115 elementsSeen = checkElement( elementsSeen, ObjectClassElements.STRUCTURAL, pos );
6116
6117 pos.start += STRUCTURAL_STR.length();
6118
6119 objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
6120 }
6121 else if ( startsWith( pos, AUXILIARY_STR ) )
6122 {
6123 elementsSeen = checkElement( elementsSeen, ObjectClassElements.AUXILIARY, pos );
6124
6125 pos.start += AUXILIARY_STR.length();
6126
6127 objectClass.setType( ObjectClassTypeEnum.AUXILIARY );
6128 }
6129 else if ( startsWith( pos, MUST_STR ) )
6130 {
6131 elementsSeen = checkElement( elementsSeen, ObjectClassElements.MUST, pos );
6132
6133 pos.start += MUST_STR.length();
6134
6135 skipWhites( reader, pos, true );
6136
6137 List<String> mustAttributeTypes = getOidsRelaxed( reader, pos );
6138 objectClass.setMustAttributeTypeOids( mustAttributeTypes );
6139 }
6140 else if ( startsWith( pos, MAY_STR ) )
6141 {
6142 elementsSeen = checkElement( elementsSeen, ObjectClassElements.MAY, pos );
6143
6144 pos.start += MAY_STR.length();
6145
6146 skipWhites( reader, pos, true );
6147
6148 List<String> mayAttributeTypes = getOidsRelaxed( reader, pos );
6149 objectClass.setMayAttributeTypeOids( mayAttributeTypes );
6150 }
6151 else if ( startsWith( pos, EXTENSION_PREFIX ) )
6152 {
6153 processExtension( reader, pos, objectClass );
6154 }
6155 else if ( startsWith( reader, pos, RPAREN ) )
6156 {
6157 pos.start++;
6158 break;
6159 }
6160 else
6161 {
6162
6163 throw new LdapSchemaException( I18n.err( I18n.ERR_13803_OC_DESCRIPTION_INVALID,
6164 pos.lineNumber, pos.start ) );
6165 }
6166 }
6167
6168 pos.start++;
6169
6170 return objectClass;
6171 }
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196 public SyntaxCheckerDescription parseSyntaxChecker( String syntaxCheckerDescription ) throws ParseException
6197 {
6198 if ( ( syntaxCheckerDescription == null ) || Strings.isEmpty( syntaxCheckerDescription.trim() ) )
6199 {
6200 throw new ParseException( I18n.err( I18n.ERR_13716_NULL_OR_EMPTY_STRING_SCHEMA_OBJECT ), 0 );
6201 }
6202
6203 try ( Reader reader = new BufferedReader( new StringReader( syntaxCheckerDescription ) ) )
6204 {
6205 PosSchema pos = new PosSchema();
6206
6207 if ( isQuirksModeEnabled )
6208 {
6209 return parseSyntaxCheckerRelaxed( reader, pos, objectIdentifierMacros );
6210 }
6211 else
6212 {
6213 return parseSyntaxCheckerStrict( reader, pos, objectIdentifierMacros );
6214 }
6215 }
6216 catch ( IOException | LdapSchemaException e )
6217 {
6218 throw new ParseException( e.getMessage(), 0 );
6219 }
6220 }
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248 private static SyntaxCheckerDescription parseSyntaxCheckerStrict( Reader reader, PosSchema pos,
6249 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros ) throws IOException, LdapSchemaException
6250 {
6251
6252 skipWhites( reader, pos, false );
6253
6254
6255 if ( pos.line.charAt( pos.start ) != LPAREN )
6256 {
6257 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
6258 pos.lineNumber, pos.start ) );
6259 }
6260 else
6261 {
6262 pos.start++;
6263 }
6264
6265
6266 skipWhites( reader, pos, false );
6267
6268
6269 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
6270
6271
6272 if ( !Oid.isOid( oid ) )
6273 {
6274 throw new LdapSchemaException( I18n.err( I18n.ERR_13787_OID_EXPECTED, pos.lineNumber, pos.start ) );
6275 }
6276
6277 SyntaxCheckerDescription syntaxChecker = new SyntaxCheckerDescription( oid );
6278 int elementsSeen = 0;
6279 boolean hasFqcn = false;
6280 boolean hasByteCode = false;
6281
6282 while ( true )
6283 {
6284 if ( startsWith( reader, pos, RPAREN ) )
6285 {
6286 pos.start++;
6287 break;
6288 }
6289
6290 skipWhites( reader, pos, true );
6291
6292 if ( startsWith( pos, DESC_STR ) )
6293 {
6294 elementsSeen = checkElement( elementsSeen, SyntaxCheckerElements.DESC, pos );
6295
6296 pos.start += DESC_STR.length();
6297
6298 skipWhites( reader, pos, true );
6299
6300 syntaxChecker.setDescription( getQDString( reader, pos ) );
6301 }
6302 else if ( startsWith( pos, FQCN_STR ) )
6303 {
6304 elementsSeen = checkElement( elementsSeen, SyntaxCheckerElements.FQCN, pos );
6305
6306 pos.start += FQCN_STR.length();
6307
6308 skipWhites( reader, pos, true );
6309
6310 String fqcn = getFqcn( pos );
6311 syntaxChecker.setFqcn( fqcn );
6312 hasFqcn = true;
6313 }
6314 else if ( startsWith( pos, BYTECODE_STR ) )
6315 {
6316 elementsSeen = checkElement( elementsSeen, SyntaxCheckerElements.BYTECODE, pos );
6317
6318 pos.start += BYTECODE_STR.length();
6319
6320 skipWhites( reader, pos, true );
6321
6322 String byteCode = getByteCode( pos );
6323 syntaxChecker.setBytecode( byteCode );
6324 hasByteCode = true;
6325 }
6326 else if ( startsWith( pos, EXTENSION_PREFIX ) )
6327 {
6328 processExtension( reader, pos, syntaxChecker );
6329 }
6330 else if ( startsWith( reader, pos, RPAREN ) )
6331 {
6332 pos.start++;
6333 break;
6334 }
6335 else
6336 {
6337
6338 throw new LdapSchemaException( I18n.err( I18n.ERR_13826_SC_DESCRIPTION_INVALID,
6339 pos.lineNumber, pos.start ) );
6340 }
6341 }
6342
6343
6344 if ( !hasFqcn )
6345 {
6346 throw new LdapSchemaException( I18n.err( I18n.ERR_13819_FQCN_REQUIRED,
6347 pos.lineNumber, pos.start ) );
6348 }
6349
6350 if ( ( hasByteCode ) && ( syntaxChecker.getBytecode().length() % 4 != 0 ) )
6351 {
6352 throw new LdapSchemaException( I18n.err( I18n.ERR_13820_BYTE_CODE_REQUIRED,
6353 pos.lineNumber, pos.start ) );
6354 }
6355
6356 return syntaxChecker;
6357 }
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385 private static SyntaxCheckerDescription parseSyntaxCheckerRelaxed( Reader reader, PosSchema pos,
6386 Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros )
6387 throws IOException, LdapSchemaException
6388 {
6389
6390 skipWhites( reader, pos, false );
6391
6392
6393 if ( pos.line.charAt( pos.start ) != LPAREN )
6394 {
6395 throw new LdapSchemaException( I18n.err( I18n.ERR_13829_NO_OPENING_PAREN,
6396 pos.lineNumber, pos.start ) );
6397 }
6398 else
6399 {
6400 pos.start++;
6401 }
6402
6403
6404 skipWhites( reader, pos, false );
6405
6406
6407 String oid = getOidAndMacroRelaxed( pos, objectIdentifierMacros );
6408
6409 SyntaxCheckerDescription syntaxChecker = new SyntaxCheckerDescription( oid );
6410 int elementsSeen = 0;
6411
6412 while ( true )
6413 {
6414 if ( startsWith( reader, pos, RPAREN ) )
6415 {
6416 pos.start++;
6417 break;
6418 }
6419
6420 skipWhites( reader, pos, true );
6421
6422 if ( startsWith( pos, DESC_STR ) )
6423 {
6424 elementsSeen = checkElement( elementsSeen, SyntaxCheckerElements.DESC, pos );
6425
6426 pos.start += DESC_STR.length();
6427
6428 skipWhites( reader, pos, true );
6429
6430 syntaxChecker.setDescription( getQDString( reader, pos ) );
6431 }
6432 else if ( startsWith( pos, FQCN_STR ) )
6433 {
6434 elementsSeen = checkElement( elementsSeen, SyntaxCheckerElements.FQCN, pos );
6435
6436 pos.start += FQCN_STR.length();
6437
6438 skipWhites( reader, pos, true );
6439
6440 String fqcn = getFqcn( pos );
6441 syntaxChecker.setFqcn( fqcn );
6442 }
6443 else if ( startsWith( pos, BYTECODE_STR ) )
6444 {
6445 elementsSeen = checkElement( elementsSeen, SyntaxCheckerElements.BYTECODE, pos );
6446
6447 pos.start += BYTECODE_STR.length();
6448
6449 skipWhites( reader, pos, true );
6450
6451 String byteCode = getByteCode( pos );
6452 syntaxChecker.setBytecode( byteCode );
6453 }
6454 else if ( startsWith( pos, EXTENSION_PREFIX ) )
6455 {
6456 processExtension( reader, pos, syntaxChecker );
6457 }
6458 else if ( startsWith( reader, pos, RPAREN ) )
6459 {
6460 pos.start++;
6461 break;
6462 }
6463 else
6464 {
6465
6466 throw new LdapSchemaException( I18n.err( I18n.ERR_13826_SC_DESCRIPTION_INVALID,
6467 pos.lineNumber, pos.start ) );
6468 }
6469 }
6470
6471 return syntaxChecker;
6472 }
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489 private void processObjectIdentifier( Reader reader, PosSchema pos ) throws IOException, LdapSchemaException
6490 {
6491
6492 skipWhites( reader, pos, false );
6493
6494
6495 String name = getDescrStrict( pos );
6496
6497 OpenLdapObjectIdentifierMacro macro = new OpenLdapObjectIdentifierMacro();
6498
6499 skipWhites( reader, pos, true );
6500
6501
6502 if ( isEmpty( pos ) )
6503 {
6504 throw new LdapSchemaException( I18n.err( I18n.ERR_13805_OBJECT_IDENTIFIER_INVALID_OID,
6505 pos.lineNumber, pos.start ) );
6506 }
6507
6508 if ( isAlpha( pos ) )
6509 {
6510
6511 String descr = getMacro( pos );
6512
6513 if ( isEmpty( pos ) )
6514 {
6515 throw new LdapSchemaException( I18n.err( I18n.ERR_13804_OBJECT_IDENTIFIER_HAS_NO_OID,
6516 pos.lineNumber, pos.start ) );
6517 }
6518
6519 if ( startsWith( reader, pos, COLON ) )
6520 {
6521 pos.start++;
6522
6523
6524 String numericOid = getPartialNumericOid( pos );
6525 String realOid = objectIdentifierMacros.get( descr ).getRawOidOrNameSuffix() + DOT + numericOid;
6526 macro.setName( name );
6527 macro.setRawOidOrNameSuffix( realOid );
6528
6529 objectIdentifierMacros.put( name, macro );
6530 }
6531 }
6532 else if ( isDigit( pos ) )
6533 {
6534
6535 String numericOid = getNumericOid( pos );
6536 macro.setRawOidOrNameSuffix( numericOid );
6537 macro.setName( name );
6538
6539 objectIdentifierMacros.put( name, macro );
6540 }
6541 else
6542 {
6543 throw new LdapSchemaException( I18n.err( I18n.ERR_13805_OBJECT_IDENTIFIER_INVALID_OID,
6544 pos.lineNumber, pos.start ) );
6545 }
6546 }
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559 public void parse( Reader reader ) throws LdapSchemaException, IOException
6560 {
6561 PosSchema pos = new PosSchema();
6562
6563 while ( true )
6564 {
6565
6566 skipWhites( reader, pos, false );
6567
6568 if ( pos.line == null )
6569 {
6570
6571 break;
6572 }
6573
6574
6575
6576 if ( startsWith( pos, "objectidentifier" ) )
6577 {
6578 pos.start += "objectidentifier".length();
6579
6580 processObjectIdentifier( reader, pos );
6581 }
6582 else if ( startsWith( pos, "attributetype" ) )
6583 {
6584 pos.start += "attributetype".length();
6585
6586 AttributeType attributeType = parseAttributeTypeStrict( reader, pos, objectIdentifierMacros );
6587 schemaDescriptions.add( attributeType );
6588 }
6589 else if ( startsWith( pos, "objectclass" ) )
6590 {
6591 pos.start += "objectclass".length();
6592
6593 ObjectClass objectClass = parseObjectClassStrict( reader, pos, objectIdentifierMacros );
6594 schemaDescriptions.add( objectClass );
6595 }
6596 else
6597 {
6598
6599 throw new LdapSchemaException( I18n.err( I18n.ERR_13806_UNEXPECTED_ELEMENT_READ,
6600 pos.line.substring( pos.start ), pos.lineNumber, pos.start ) );
6601 }
6602 }
6603 }
6604
6605
6606
6607
6608
6609
6610
6611
6612 public void parse( File schemaFile ) throws ParseException
6613 {
6614 try ( InputStream is = Files.newInputStream( Paths.get( schemaFile.getPath() ) ) )
6615 {
6616 try ( Reader reader = new BufferedReader( new InputStreamReader( is, Charset.defaultCharset() ) ) )
6617 {
6618 parse( reader );
6619 afterParse();
6620 }
6621 catch ( LdapSchemaException | IOException e )
6622 {
6623 throw new ParseException( e.getMessage(), 0 );
6624 }
6625 }
6626 catch ( IOException e )
6627 {
6628 String msg = I18n.err( I18n.ERR_13443_CANNOT_FIND_FILE, schemaFile.getAbsoluteFile() );
6629 LOG.error( msg );
6630 throw new ParseException( e.getMessage(), 0 );
6631 }
6632 }
6633
6634
6635
6636
6637
6638
6639
6640 public boolean isResolveObjectIdentifierMacros()
6641 {
6642 return isResolveObjectIdentifierMacros;
6643 }
6644
6645
6646
6647
6648
6649
6650
6651 public void setResolveObjectIdentifierMacros( boolean resolveObjectIdentifierMacros )
6652 {
6653 this.isResolveObjectIdentifierMacros = resolveObjectIdentifierMacros;
6654 }
6655
6656
6657
6658
6659
6660
6661 public boolean isQuirksMode()
6662 {
6663 return isQuirksModeEnabled;
6664 }
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675 public void setQuirksMode( boolean enabled )
6676 {
6677 isQuirksModeEnabled = enabled;
6678 }
6679 }