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.ldif;
21
22
23 import java.io.BufferedReader;
24 import java.io.Closeable;
25 import java.io.DataInputStream;
26 import java.io.File;
27 import java.io.FileNotFoundException;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.io.Reader;
32 import java.io.StringReader;
33 import java.net.MalformedURLException;
34 import java.net.URL;
35 import java.nio.charset.Charset;
36 import java.nio.file.Files;
37 import java.nio.file.Paths;
38 import java.util.ArrayList;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.NoSuchElementException;
42
43 import org.apache.directory.api.asn1.util.Oid;
44 import org.apache.directory.api.i18n.I18n;
45 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
46 import org.apache.directory.api.ldap.model.entry.Attribute;
47 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
48 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
49 import org.apache.directory.api.ldap.model.exception.LdapException;
50 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
51 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
52 import org.apache.directory.api.ldap.model.message.Control;
53 import org.apache.directory.api.ldap.model.name.Ava;
54 import org.apache.directory.api.ldap.model.name.Dn;
55 import org.apache.directory.api.ldap.model.name.Rdn;
56 import org.apache.directory.api.ldap.model.schema.AttributeType;
57 import org.apache.directory.api.ldap.model.schema.MutableAttributeType;
58 import org.apache.directory.api.ldap.model.schema.SchemaManager;
59 import org.apache.directory.api.util.Base64;
60 import org.apache.directory.api.util.Chars;
61 import org.apache.directory.api.util.Strings;
62 import org.apache.directory.api.util.exception.NotImplementedException;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public class LdifReader implements Iterable<LdifEntry>, Closeable
175 {
176
177 private static final Logger LOG = LoggerFactory.getLogger( LdifReader.class );
178
179
180 protected List<String> lines;
181
182
183 protected int position;
184
185
186 protected static final int DEFAULT_VERSION = 1;
187
188
189 protected int version;
190
191
192 protected static final int LDIF_ENTRY = 0;
193
194
195 protected static final int CHANGE = 1;
196
197
198 protected static final int UNKNOWN = 2;
199
200
201 protected long sizeLimit = SIZE_LIMIT_DEFAULT;
202
203
204 protected static final long SIZE_LIMIT_DEFAULT = 1024000;
205
206
207 protected static final int MOD_SPEC = 0;
208
209
210 protected static final int ATTRVAL_SPEC = 1;
211
212
213 protected static final int ATTRVAL_SPEC_OR_SEP = 2;
214
215
216 protected LdifEntry prefetched;
217
218
219 protected Reader reader;
220
221
222 protected boolean containsEntries;
223
224
225 protected boolean containsChanges;
226
227
228 protected SchemaManager schemaManager;
229
230
231
232
233
234 protected Exception error;
235
236
237 protected int entryLen = 0;
238
239
240 protected long entryOffset = 0;
241
242
243 protected long offset = 0;
244
245
246 protected int lineNumber;
247
248
249 protected boolean validateDn = true;
250
251
252 private int oidCounter = 0;
253
254
255
256
257
258 public LdifReader()
259 {
260 lines = new ArrayList<>();
261 position = 0;
262 version = DEFAULT_VERSION;
263 }
264
265
266
267
268
269
270
271 public LdifReader( SchemaManager schemaManager )
272 {
273 lines = new ArrayList<>();
274 position = 0;
275 version = DEFAULT_VERSION;
276 this.schemaManager = schemaManager;
277 }
278
279
280
281
282
283
284
285
286 public LdifReader( String ldifFileName ) throws LdapLdifException
287 {
288 this( new File( ldifFileName ) );
289 }
290
291
292
293
294
295
296
297
298 public LdifReader( Reader in ) throws LdapException
299 {
300 initReader( new BufferedReader( in ) );
301 }
302
303
304
305
306
307
308
309
310 public LdifReader( InputStream in ) throws LdapException
311 {
312 initReader( new BufferedReader( new InputStreamReader( in, Charset.defaultCharset() ) ) );
313 }
314
315
316
317
318
319
320
321
322 public LdifReader( File file ) throws LdapLdifException
323 {
324 this( file, null );
325 }
326
327
328
329
330
331
332
333
334
335 public LdifReader( File file, SchemaManager schemaManager ) throws LdapLdifException
336 {
337 if ( !file.exists() )
338 {
339 String msg = I18n.err( I18n.ERR_12010_CANNOT_FIND_FILE, file.getAbsoluteFile() );
340 LOG.error( msg );
341 throw new LdapLdifException( msg );
342 }
343
344 if ( !file.canRead() )
345 {
346 String msg = I18n.err( I18n.ERR_12011_CANNOT_READ_FILE, file.getName() );
347 LOG.error( msg );
348 throw new LdapLdifException( msg );
349 }
350
351 this.schemaManager = schemaManager;
352
353 try
354 {
355 InputStream is = Files.newInputStream( Paths.get( file.getPath() ) );
356 initReader(
357 new BufferedReader( new InputStreamReader( is, Charset.defaultCharset() ) ) );
358 }
359 catch ( FileNotFoundException fnfe )
360 {
361 String msg = I18n.err( I18n.ERR_12010_CANNOT_FIND_FILE, file.getAbsoluteFile() );
362 LOG.error( msg );
363 throw new LdapLdifException( msg, fnfe );
364 }
365 catch ( LdapInvalidDnException lide )
366 {
367 throw new LdapLdifException( lide.getMessage(), lide );
368 }
369 catch ( IOException ioe )
370 {
371 throw new LdapLdifException( ioe.getMessage(), ioe );
372 }
373 catch ( LdapException le )
374 {
375 throw new LdapLdifException( le.getMessage(), le );
376 }
377 }
378
379
380
381
382
383 private void initReader( BufferedReader reader ) throws LdapException
384 {
385 this.reader = reader;
386 init();
387 }
388
389
390
391
392
393
394
395 public void init() throws LdapException
396 {
397 lines = new ArrayList<>();
398 position = 0;
399 version = DEFAULT_VERSION;
400 containsChanges = false;
401 containsEntries = false;
402
403
404 version = parseVersion();
405 prefetched = parseEntry();
406 }
407
408
409
410
411
412 public int getVersion()
413 {
414 return version;
415 }
416
417
418
419
420
421 public long getSizeLimit()
422 {
423 return sizeLimit;
424 }
425
426
427
428
429
430
431
432 public void setSizeLimit( long sizeLimit )
433 {
434 this.sizeLimit = sizeLimit;
435 }
436
437
438
439 private void parseFill( char[] document )
440 {
441 while ( Chars.isCharASCII( document, position, ' ' ) )
442 {
443 position++;
444 }
445 }
446
447
448
449
450
451
452
453
454
455
456
457
458
459 private String parseNumber( char[] document )
460 {
461 int initPos = position;
462
463 while ( true )
464 {
465 if ( Chars.isDigit( document, position ) )
466 {
467 position++;
468 }
469 else
470 {
471 break;
472 }
473 }
474
475 if ( position == initPos )
476 {
477 return null;
478 }
479 else
480 {
481 return new String( document, initPos, position - initPos );
482 }
483 }
484
485
486
487
488
489
490
491
492 protected ChangeType parseChangeType( String line )
493 {
494 ChangeType operation = ChangeType.Add;
495
496 String modOp = Strings.trim( line.substring( "changetype:".length() ) );
497
498 if ( "add".equalsIgnoreCase( modOp ) )
499 {
500 operation = ChangeType.Add;
501 }
502 else if ( "delete".equalsIgnoreCase( modOp ) )
503 {
504 operation = ChangeType.Delete;
505 }
506 else if ( "modify".equalsIgnoreCase( modOp ) )
507 {
508 operation = ChangeType.Modify;
509 }
510 else if ( "moddn".equalsIgnoreCase( modOp ) )
511 {
512 operation = ChangeType.ModDn;
513 }
514 else if ( "modrdn".equalsIgnoreCase( modOp ) )
515 {
516 operation = ChangeType.ModRdn;
517 }
518
519 return operation;
520 }
521
522
523
524
525
526
527
528
529
530 protected String parseDn( String line ) throws LdapLdifException
531 {
532 String dn;
533
534 String lowerLine = Strings.toLowerCaseAscii( line );
535
536 if ( lowerLine.startsWith( "dn:" ) || lowerLine.startsWith( "Dn:" ) )
537 {
538
539 int length = line.length();
540
541 if ( length == 3 )
542 {
543
544 dn = "";
545 }
546 else if ( line.charAt( 3 ) == ':' )
547 {
548 if ( length > 4 )
549 {
550
551 String trimmedLine = line.substring( 4 ).trim();
552
553 dn = Strings.utf8ToString( Base64.decode( trimmedLine.toCharArray() ) );
554 }
555 else
556 {
557
558 LOG.error( I18n.err( I18n.ERR_12012_EMPTY_DN_NOT_ALLOWED, lineNumber ) );
559 throw new LdapLdifException( I18n.err( I18n.ERR_12013_NO_DN ) );
560 }
561 }
562 else
563 {
564 dn = line.substring( 3 ).trim();
565 }
566 }
567 else
568 {
569 LOG.error( I18n.err( I18n.ERR_12016_DN_EXPECTED, lineNumber ) );
570 throw new LdapLdifException( I18n.err( I18n.ERR_12013_NO_DN ) );
571 }
572
573
574 if ( validateDn && !Dn.isValid( dn ) )
575 {
576 String message = I18n.err( I18n.ERR_12017_INVALID_DN, dn, lineNumber );
577 LOG.error( message );
578 throw new LdapLdifException( message );
579 }
580
581 return dn;
582 }
583
584
585
586
587
588
589
590
591
592 protected static Object parseSimpleValue( String line, int pos )
593 {
594 if ( line.length() > pos + 1 )
595 {
596 char c = line.charAt( pos + 1 );
597
598 if ( c == ':' )
599 {
600 String value = Strings.trim( line.substring( pos + 2 ) );
601
602 return Base64.decode( value.toCharArray() );
603 }
604 else
605 {
606 return Strings.trim( line.substring( pos + 1 ) );
607 }
608 }
609 else
610 {
611 return null;
612 }
613 }
614
615
616 private Object getValue( String attributeName, byte[] value )
617 {
618 if ( schemaManager != null )
619 {
620 AttributeType attributeType = schemaManager.getAttributeType( attributeName );
621
622 if ( attributeType != null )
623 {
624 if ( attributeType.getSyntax().isHumanReadable() )
625 {
626 return Strings.utf8ToString( value );
627 }
628 else
629 {
630 return value;
631 }
632 }
633 else
634 {
635 return value;
636 }
637 }
638 else
639 {
640 return value;
641 }
642 }
643
644
645
646
647
648
649
650
651
652
653
654 protected Object parseValue( String attributeName, String line, int pos ) throws LdapLdifException
655 {
656 if ( line.length() > pos + 1 )
657 {
658 char c = line.charAt( pos + 1 );
659
660 if ( c == ':' )
661 {
662 String value = Strings.trim( line.substring( pos + 2 ) );
663
664 byte[] decoded = Base64.decode( value.toCharArray() );
665
666 return getValue( attributeName, decoded );
667 }
668 else if ( c == '<' )
669 {
670 String urlName = Strings.trim( line.substring( pos + 2 ) );
671
672 try
673 {
674 URL url = new URL( urlName );
675
676 if ( "file".equals( url.getProtocol() ) )
677 {
678 String fileName = url.getFile();
679
680 File file = new File( fileName );
681
682 if ( !file.exists() )
683 {
684 LOG.error( I18n.err( I18n.ERR_12018_FILE_NOT_FOUND, fileName, lineNumber ) );
685 throw new LdapLdifException( I18n.err( I18n.ERR_12019_BAD_URL_FILE_NOT_FOUND ) );
686 }
687 else
688 {
689 long length = file.length();
690
691 if ( length > sizeLimit )
692 {
693 String message = I18n.err( I18n.ERR_12020_FILE_TOO_BIG, fileName, lineNumber );
694 LOG.error( message );
695 throw new LdapLdifException( message );
696 }
697 else
698 {
699 byte[] data = new byte[( int ) length];
700
701 try ( DataInputStream inf = new DataInputStream(
702 Files.newInputStream( Paths.get( fileName ) ) ) )
703 {
704 inf.readFully( data );
705
706 return getValue( attributeName, data );
707 }
708 catch ( FileNotFoundException fnfe )
709 {
710
711
712
713 LOG.error( I18n.err( I18n.ERR_12018_FILE_NOT_FOUND, fileName, lineNumber ) );
714 throw new LdapLdifException( I18n.err( I18n.ERR_12019_BAD_URL_FILE_NOT_FOUND ),
715 fnfe );
716 }
717 catch ( IOException ioe )
718 {
719 LOG.error( I18n.err( I18n.ERR_12022_ERROR_READING_FILE, fileName, lineNumber ) );
720 throw new LdapLdifException( I18n.err( I18n.ERR_12023_ERROR_READING_BAD_URL ), ioe );
721 }
722 }
723 }
724 }
725 else
726 {
727 LOG.error( I18n.err( I18n.ERR_12025_BAD_PROTOCOL ) );
728 throw new LdapLdifException( I18n.err( I18n.ERR_12026_UNSUPPORTED_PROTOCOL, lineNumber ) );
729 }
730 }
731 catch ( MalformedURLException mue )
732 {
733 String message = I18n.err( I18n.ERR_12027_BAD_URL, urlName, lineNumber );
734 LOG.error( message );
735 throw new LdapLdifException( message, mue );
736 }
737 }
738 else
739 {
740 String value = Strings.trimLeft( line.substring( pos + 1 ) );
741 int end = value.length();
742
743 for ( int i = value.length() - 1; i > 0; i-- )
744 {
745 char cc = value.charAt( i );
746
747 if ( cc == ' ' )
748 {
749 if ( value.charAt( i - 1 ) == '\\' )
750 {
751
752 break;
753 }
754 else
755 {
756 end = i;
757 }
758 }
759 else
760 {
761 break;
762 }
763 }
764
765 String result = null;
766
767 result = value.substring( 0, end );
768
769 return result;
770 }
771 }
772 else
773 {
774 return null;
775 }
776 }
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801 private Control parseControl( String line ) throws LdapLdifException
802 {
803 String lowerLine = Strings.toLowerCaseAscii( line ).trim();
804 char[] controlValue = line.trim().toCharArray();
805 int pos = 0;
806 int length = controlValue.length;
807
808
809 if ( pos > length )
810 {
811
812 LOG.error( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID, lineNumber ) );
813 throw new LdapLdifException( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID ) );
814 }
815
816 int initPos = pos;
817
818 while ( Chars.isCharASCII( controlValue, pos, '.' ) || Chars.isDigit( controlValue, pos ) )
819 {
820 pos++;
821 }
822
823 if ( pos == initPos )
824 {
825
826 LOG.error( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID, lineNumber ) );
827 throw new LdapLdifException( I18n.err( I18n.ERR_12029_CONTROL_WITHOUT_OID ) );
828 }
829
830
831 String oidString = lowerLine.substring( 0, pos );
832
833 if ( !Oid.isOid( oidString ) )
834 {
835 String message = I18n.err( I18n.ERR_12031_INVALID_OID, oidString, lineNumber );
836 LOG.error( message );
837 throw new LdapLdifException( message );
838 }
839
840 LdifControl control = new LdifControl( oidString );
841
842
843
844 while ( Chars.isCharASCII( controlValue, pos, ' ' ) )
845 {
846 pos++;
847 }
848
849
850 int criticalPos = lowerLine.indexOf( ':' );
851
852 int criticalLength;
853
854 if ( criticalPos == -1 )
855 {
856 criticalLength = length - pos;
857 }
858 else
859 {
860 criticalLength = criticalPos - pos;
861 }
862
863 if ( ( criticalLength == 4 ) && ( "true".equalsIgnoreCase( lowerLine.substring( pos, pos + 4 ) ) ) )
864 {
865 control.setCritical( true );
866 }
867 else if ( ( criticalLength == 5 ) && ( "false".equalsIgnoreCase( lowerLine.substring( pos, pos + 5 ) ) ) )
868 {
869 control.setCritical( false );
870 }
871 else if ( criticalLength != 0 )
872 {
873
874
875 LOG.error( I18n.err( I18n.ERR_12033_INVALID_CRITICALITY, lineNumber ) );
876 throw new LdapLdifException( I18n.err( I18n.ERR_12033_INVALID_CRITICALITY ) );
877 }
878
879 if ( criticalPos > 0 )
880 {
881
882
883 if ( Chars.isCharASCII( controlValue, criticalPos + 1, ':' ) )
884 {
885
886
887
888 pos = criticalPos + 2;
889
890 while ( Chars.isCharASCII( controlValue, pos, ' ' ) )
891 {
892 pos++;
893 }
894
895 byte[] value = Base64.decode( line.substring( pos ).toCharArray() );
896 control.setValue( value );
897 }
898 else if ( Chars.isCharASCII( controlValue, criticalPos + 1, '<' ) )
899 {
900
901 throw new NotImplementedException( "See DIRSERVER-1547" );
902 }
903 else
904 {
905
906 pos = criticalPos + 1;
907
908 while ( Chars.isCharASCII( controlValue, pos, ' ' ) )
909 {
910 pos++;
911 }
912
913
914 byte[] value = new byte[length - pos];
915
916 for ( int i = 0; i < length - pos; i++ )
917 {
918 value[i] = ( byte ) controlValue[i + pos];
919 }
920
921 control.setValue( value );
922 }
923 }
924
925 return control;
926 }
927
928
929
930
931
932
933
934
935 public static Attribute parseAttributeValue( String line )
936 {
937 int colonIndex = line.indexOf( ':' );
938
939 if ( colonIndex != -1 )
940 {
941 String attributeType = line.substring( 0, colonIndex );
942 Object attributeValue = parseSimpleValue( line, colonIndex );
943
944
945 if ( attributeValue instanceof String )
946 {
947 return new DefaultAttribute( attributeType, ( String ) attributeValue );
948 }
949 else
950 {
951 return new DefaultAttribute( attributeType, ( byte[] ) attributeValue );
952 }
953 }
954 else
955 {
956 return null;
957 }
958 }
959
960
961
962
963
964
965
966
967
968
969 public void parseAttributeValue( LdifEntry entry, String line, String lowerLine ) throws LdapException
970 {
971 int colonIndex = line.indexOf( ':' );
972
973 String attributeType = lowerLine.substring( 0, colonIndex );
974
975
976 if ( "dn".equals( attributeType ) )
977 {
978 LOG.error( I18n.err( I18n.ERR_12002_ENTRY_WITH_TWO_DNS, lineNumber ) );
979 throw new LdapLdifException( I18n.err( I18n.ERR_12003_LDIF_ENTRY_WITH_TWO_DNS ) );
980 }
981
982 Object attributeValue = parseValue( attributeType, line, colonIndex );
983
984 if ( schemaManager != null )
985 {
986 AttributeType at = schemaManager.getAttributeType( attributeType );
987
988 if ( at != null )
989 {
990 if ( at.getSyntax().isHumanReadable() )
991 {
992 if ( attributeValue instanceof byte[] )
993 {
994 attributeValue = Strings.utf8ToString( ( byte[] ) attributeValue );
995 }
996 }
997 else
998 {
999 if ( attributeValue instanceof String )
1000 {
1001 attributeValue = Strings.getBytesUtf8( ( String ) attributeValue );
1002 }
1003 }
1004 }
1005 }
1006
1007
1008 try
1009 {
1010 entry.addAttribute( attributeType, attributeValue );
1011 }
1012 catch ( Exception e )
1013 {
1014
1015 if ( ( schemaManager != null ) && schemaManager.isRelaxed() )
1016 {
1017 MutableAttributeType newAttributeType = new MutableAttributeType( "1.3.6.1.4.1.18060.0.9999." + oidCounter++ );
1018 newAttributeType.setNames( attributeType );
1019 newAttributeType.setSyntax( schemaManager.getLdapSyntaxRegistry().get( SchemaConstants.DIRECTORY_STRING_SYNTAX ) );
1020 schemaManager.add( newAttributeType );
1021 entry.addAttribute( attributeType, attributeValue );
1022 }
1023 }
1024 }
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034 private void parseModRdn( LdifEntry entry, Iterator<String> iter ) throws LdapLdifException
1035 {
1036
1037
1038 if ( iter.hasNext() )
1039 {
1040 String line = iter.next();
1041 String lowerLine = Strings.toLowerCaseAscii( line );
1042
1043 if ( lowerLine.startsWith( "newrdn::" ) || lowerLine.startsWith( "newrdn:" ) )
1044 {
1045 int colonIndex = line.indexOf( ':' );
1046 Object attributeValue = parseValue( null, line, colonIndex );
1047
1048 if ( attributeValue instanceof String )
1049 {
1050 entry.setNewRdn( ( String ) attributeValue );
1051 }
1052 else
1053 {
1054 entry.setNewRdn( Strings.utf8ToString( ( byte[] ) attributeValue ) );
1055 }
1056 }
1057 else
1058 {
1059 LOG.error( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION, lineNumber ) );
1060 throw new LdapLdifException( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION ) );
1061 }
1062 }
1063 else
1064 {
1065 LOG.error( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION, lineNumber ) );
1066 throw new LdapLdifException( I18n.err( I18n.ERR_12035_BAD_MODRDN_OPERATION ) );
1067 }
1068
1069 if ( iter.hasNext() )
1070 {
1071 String line = iter.next();
1072 String lowerLine = Strings.toLowerCaseAscii( line );
1073
1074 if ( lowerLine.startsWith( "deleteoldrdn:" ) )
1075 {
1076 int colonIndex = line.indexOf( ':' );
1077 Object attributeValue = parseValue( null, line, colonIndex );
1078 entry.setDeleteOldRdn( "1".equals( attributeValue ) );
1079 }
1080 else
1081 {
1082 LOG.error( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN, lineNumber ) );
1083 throw new LdapLdifException( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN ) );
1084 }
1085 }
1086 else
1087 {
1088 LOG.error( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN, lineNumber ) );
1089 throw new LdapLdifException( I18n.err( I18n.ERR_12038_NO_DELETEOLDRDN ) );
1090 }
1091 }
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112 private void parseModify( LdifEntry entry, Iterator<String> iter ) throws LdapLdifException
1113 {
1114 int state = MOD_SPEC;
1115 String modified = null;
1116 ModificationOperation modificationType = ModificationOperation.ADD_ATTRIBUTE;
1117 Attribute attribute = null;
1118
1119
1120 boolean isEmptyValue = true;
1121
1122 while ( iter.hasNext() )
1123 {
1124 String line = iter.next();
1125 String lowerLine = Strings.toLowerCaseAscii( line );
1126
1127 if ( lowerLine.startsWith( "-" ) )
1128 {
1129 if ( ( state != ATTRVAL_SPEC_OR_SEP ) && ( state != ATTRVAL_SPEC ) )
1130 {
1131 LOG.error( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR, lineNumber ) );
1132 throw new LdapLdifException( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR ) );
1133 }
1134 else
1135 {
1136 if ( isEmptyValue )
1137 {
1138 if ( state == ATTRVAL_SPEC_OR_SEP )
1139 {
1140 entry.addModification( modificationType, modified );
1141 }
1142 else
1143 {
1144
1145 entry.addModification( modificationType, modified, null );
1146 }
1147 }
1148 else
1149 {
1150
1151 entry.addModification( modificationType, attribute );
1152 }
1153
1154 state = MOD_SPEC;
1155 isEmptyValue = true;
1156 }
1157 }
1158 else if ( lowerLine.startsWith( "add:" ) )
1159 {
1160 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
1161 {
1162 LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
1163 throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
1164 }
1165
1166 modified = Strings.trim( line.substring( "add:".length() ) );
1167 modificationType = ModificationOperation.ADD_ATTRIBUTE;
1168 attribute = new DefaultAttribute( modified );
1169
1170 state = ATTRVAL_SPEC;
1171 }
1172 else if ( lowerLine.startsWith( "delete:" ) )
1173 {
1174 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
1175 {
1176 LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
1177 throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
1178 }
1179
1180 modified = Strings.trim( line.substring( "delete:".length() ) );
1181 modificationType = ModificationOperation.REMOVE_ATTRIBUTE;
1182 attribute = new DefaultAttribute( modified );
1183 isEmptyValue = false;
1184
1185 state = ATTRVAL_SPEC_OR_SEP;
1186 }
1187 else if ( lowerLine.startsWith( "replace:" ) )
1188 {
1189 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
1190 {
1191 LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
1192 throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2 ) );
1193 }
1194
1195 modified = Strings.trim( line.substring( "replace:".length() ) );
1196 modificationType = ModificationOperation.REPLACE_ATTRIBUTE;
1197
1198 if ( schemaManager != null )
1199 {
1200 AttributeType attributeType = schemaManager.getAttributeType( modified );
1201 attribute = new DefaultAttribute( modified, attributeType );
1202 }
1203 else
1204 {
1205 attribute = new DefaultAttribute( modified );
1206 }
1207
1208 state = ATTRVAL_SPEC_OR_SEP;
1209 }
1210 else
1211 {
1212 if ( ( state != ATTRVAL_SPEC ) && ( state != ATTRVAL_SPEC_OR_SEP ) )
1213 {
1214 LOG.error( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR, lineNumber ) );
1215 throw new LdapLdifException( I18n.err( I18n.ERR_12040_BAD_MODIFY_SEPARATOR ) );
1216 }
1217
1218
1219 int colonIndex = line.indexOf( ':' );
1220
1221 String attributeType = line.substring( 0, colonIndex );
1222
1223 if ( !attributeType.equalsIgnoreCase( modified ) )
1224 {
1225 LOG.error( I18n.err( I18n.ERR_12044, lineNumber ) );
1226 throw new LdapLdifException( I18n.err( I18n.ERR_12045 ) );
1227 }
1228
1229
1230 if ( "dn".equalsIgnoreCase( attributeType ) )
1231 {
1232 LOG.error( I18n.err( I18n.ERR_12002_ENTRY_WITH_TWO_DNS, lineNumber ) );
1233 throw new LdapLdifException( I18n.err( I18n.ERR_12003_LDIF_ENTRY_WITH_TWO_DNS ) );
1234 }
1235
1236 Object attributeValue = parseValue( attributeType, line, colonIndex );
1237
1238 try
1239 {
1240 if ( attributeValue instanceof String )
1241 {
1242 attribute.add( ( String ) attributeValue );
1243 }
1244 else
1245 {
1246 attribute.add( ( byte[] ) attributeValue );
1247 }
1248 }
1249 catch ( LdapInvalidAttributeValueException liave )
1250 {
1251 throw new LdapLdifException( liave.getMessage(), liave );
1252 }
1253
1254 isEmptyValue = false;
1255
1256 state = ATTRVAL_SPEC_OR_SEP;
1257 }
1258 }
1259
1260 if ( state != MOD_SPEC )
1261 {
1262 LOG.error( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
1263 throw new LdapLdifException( I18n.err( I18n.ERR_12042_BAD_MODIFY_SEPARATOR_2, lineNumber ) );
1264 }
1265 }
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 private void parseChange( LdifEntry entry, Iterator<String> iter, ChangeType operation ) throws LdapException
1302 {
1303
1304 entry.setChangeType( operation );
1305
1306 switch ( operation )
1307 {
1308 case Delete:
1309
1310
1311 return;
1312
1313 case Add:
1314
1315 while ( iter.hasNext() )
1316 {
1317 String line = iter.next();
1318 String lowerLine = Strings.toLowerCaseAscii( line );
1319 parseAttributeValue( entry, line, lowerLine );
1320 }
1321
1322 return;
1323
1324 case Modify:
1325 parseModify( entry, iter );
1326 return;
1327
1328 case ModDn:
1329
1330
1331 case ModRdn:
1332
1333 parseModRdn( entry, iter );
1334
1335
1336 if ( iter.hasNext() )
1337 {
1338 String line = iter.next();
1339 String lowerLine = Strings.toLowerCaseAscii( line );
1340
1341 if ( lowerLine.startsWith( "newsuperior:" ) )
1342 {
1343 int colonIndex = line.indexOf( ':' );
1344 Object attributeValue = parseValue( null, line, colonIndex );
1345
1346 if ( attributeValue instanceof String )
1347 {
1348 entry.setNewSuperior( ( String ) attributeValue );
1349 }
1350 else
1351 {
1352 entry.setNewSuperior( Strings.utf8ToString( ( byte[] ) attributeValue ) );
1353 }
1354 }
1355 else
1356 {
1357 if ( operation == ChangeType.ModDn )
1358 {
1359 LOG.error( I18n.err( I18n.ERR_12046, lineNumber ) );
1360 throw new LdapLdifException( I18n.err( I18n.ERR_12047 ) );
1361 }
1362 }
1363 }
1364
1365 return;
1366
1367 default:
1368
1369 LOG.error( I18n.err( I18n.ERR_12048, lineNumber ) );
1370 throw new LdapLdifException( I18n.err( I18n.ERR_12049 ) );
1371 }
1372 }
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389 protected LdifEntry parseEntry() throws LdapException
1390 {
1391 if ( ( lines == null ) || lines.isEmpty() )
1392 {
1393 LOG.debug( "The entry is empty : end of ldif file" );
1394 return null;
1395 }
1396
1397
1398 String line = lines.get( 0 );
1399
1400 lineNumber -= ( lines.size() - 1 );
1401
1402 String name = parseDn( line );
1403
1404 Dn dn = null;
1405
1406 try
1407 {
1408 dn = new Dn( schemaManager, name );
1409 }
1410 catch ( LdapInvalidDnException lide )
1411 {
1412
1413
1414 dn = new Dn( name );
1415
1416 Rdn rdn = dn.getRdn();
1417
1418
1419 for ( Ava ava : rdn )
1420 {
1421 if ( ( schemaManager != null ) && ( schemaManager.getAttributeType( ava.getType() ) == null )
1422 && schemaManager.isRelaxed() )
1423 {
1424
1425 MutableAttributeType newAttributeType = new MutableAttributeType( "1.3.6.1.4.1.18060.0.9999." + oidCounter++ );
1426 newAttributeType.setNames( ava.getType() );
1427 newAttributeType.setSyntax( schemaManager.getLdapSyntaxRegistry().get( SchemaConstants.DIRECTORY_STRING_SYNTAX ) );
1428 schemaManager.add( newAttributeType );
1429 }
1430 }
1431
1432 dn = new Dn( schemaManager, name );
1433 }
1434
1435
1436 LdifEntry entry = createLdifEntry( schemaManager );
1437 entry.setLengthBeforeParsing( entryLen );
1438 entry.setOffset( entryOffset );
1439
1440 entry.setDn( dn );
1441
1442
1443 lines.remove( 0 );
1444
1445
1446 Iterator<String> iter = lines.iterator();
1447
1448
1449 int type = LDIF_ENTRY;
1450
1451
1452
1453 boolean controlSeen = false;
1454
1455
1456
1457 boolean changeTypeSeen = false;
1458
1459 ChangeType operation = ChangeType.Add;
1460 String lowerLine;
1461 Control control;
1462
1463 while ( iter.hasNext() )
1464 {
1465 lineNumber++;
1466
1467
1468
1469 line = iter.next();
1470 lowerLine = Strings.toLowerCaseAscii( line );
1471
1472
1473
1474
1475
1476 if ( lowerLine.startsWith( "control:" ) )
1477 {
1478 if ( containsEntries )
1479 {
1480 LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED, lineNumber ) );
1481 throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
1482 }
1483
1484 containsChanges = true;
1485
1486 if ( controlSeen )
1487 {
1488 LOG.error( I18n.err( I18n.ERR_12050, lineNumber ) );
1489 throw new LdapLdifException( I18n.err( I18n.ERR_12051 ) );
1490 }
1491
1492
1493 control = parseControl( line.substring( "control:".length() ) );
1494 entry.addControl( control );
1495 }
1496 else if ( lowerLine.startsWith( "changetype:" ) )
1497 {
1498 if ( containsEntries )
1499 {
1500 LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED, lineNumber ) );
1501 throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
1502 }
1503
1504 containsChanges = true;
1505
1506 if ( changeTypeSeen )
1507 {
1508 LOG.error( I18n.err( I18n.ERR_12052, lineNumber ) );
1509 throw new LdapLdifException( I18n.err( I18n.ERR_12053 ) );
1510 }
1511
1512
1513 type = CHANGE;
1514 controlSeen = true;
1515
1516 operation = parseChangeType( line );
1517
1518
1519 parseChange( entry, iter, operation );
1520 changeTypeSeen = true;
1521 }
1522 else if ( line.indexOf( ':' ) > 0 )
1523 {
1524 if ( containsChanges )
1525 {
1526 LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED, lineNumber ) );
1527 throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
1528 }
1529
1530 containsEntries = true;
1531
1532 if ( controlSeen || changeTypeSeen )
1533 {
1534 LOG.error( I18n.err( I18n.ERR_12054, lineNumber ) );
1535 throw new LdapLdifException( I18n.err( I18n.ERR_12055 ) );
1536 }
1537
1538 parseAttributeValue( entry, line, lowerLine );
1539 type = LDIF_ENTRY;
1540 }
1541 else
1542 {
1543
1544 LOG.error( I18n.err( I18n.ERR_12056, lineNumber ) );
1545 throw new LdapLdifException( I18n.err( I18n.ERR_12057_BAD_ATTRIBUTE ) );
1546 }
1547 }
1548
1549 if ( type == LDIF_ENTRY )
1550 {
1551 LOG.debug( "Read an entry : {}", entry );
1552 }
1553 else if ( type == CHANGE )
1554 {
1555 entry.setChangeType( operation );
1556 LOG.debug( "Read a modification : {}", entry );
1557 }
1558 else
1559 {
1560 LOG.error( I18n.err( I18n.ERR_12058_UNKNOWN_ENTRY_TYPE, lineNumber ) );
1561 throw new LdapLdifException( I18n.err( I18n.ERR_12059_UNKNOWN_ENTRY ) );
1562 }
1563
1564 return entry;
1565 }
1566
1567
1568
1569
1570
1571
1572
1573
1574 protected int parseVersion() throws LdapLdifException
1575 {
1576 int ver = DEFAULT_VERSION;
1577
1578
1579 readLines();
1580
1581 if ( lines.isEmpty() )
1582 {
1583 LOG.warn( "The ldif file is empty" );
1584 return ver;
1585 }
1586
1587
1588 String line = lines.get( 0 );
1589
1590
1591 char[] document = line.toCharArray();
1592 String versionNumber;
1593
1594 if ( line.startsWith( "version:" ) )
1595 {
1596 position += "version:".length();
1597 parseFill( document );
1598
1599
1600 versionNumber = parseNumber( document );
1601
1602
1603 if ( position != document.length )
1604 {
1605 LOG.error( I18n.err( I18n.ERR_12060_VERSION_NOT_A_NUMBER, lineNumber ) );
1606 throw new LdapLdifException( I18n.err( I18n.ERR_12061_LDIF_PARSING_ERROR ) );
1607 }
1608
1609 try
1610 {
1611 ver = Integer.parseInt( versionNumber );
1612 }
1613 catch ( NumberFormatException nfe )
1614 {
1615 LOG.error( I18n.err( I18n.ERR_12060_VERSION_NOT_A_NUMBER, lineNumber ) );
1616 throw new LdapLdifException( I18n.err( I18n.ERR_12061_LDIF_PARSING_ERROR ), nfe );
1617 }
1618
1619 LOG.debug( "Ldif version : {}", versionNumber );
1620
1621
1622 lines.remove( 0 );
1623
1624
1625 if ( lines.isEmpty() )
1626 {
1627
1628 int tmpEntryLen = entryLen;
1629
1630 readLines();
1631
1632 entryLen += tmpEntryLen;
1633 }
1634 }
1635 else
1636 {
1637 LOG.info( "No version information : assuming version: 1" );
1638 }
1639
1640 return ver;
1641 }
1642
1643
1644
1645
1646
1647
1648
1649
1650 protected String getLine() throws IOException
1651 {
1652 return ( ( BufferedReader ) reader ).readLine();
1653 }
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664 protected void readLines() throws LdapLdifException
1665 {
1666 String line;
1667 boolean insideComment = true;
1668 boolean isFirstLine = true;
1669
1670 lines.clear();
1671 entryLen = 0;
1672 entryOffset = offset;
1673
1674 StringBuilder sb = new StringBuilder();
1675
1676 try
1677 {
1678 while ( ( line = getLine() ) != null )
1679 {
1680 lineNumber++;
1681
1682 if ( line.length() == 0 )
1683 {
1684 if ( isFirstLine )
1685 {
1686 continue;
1687 }
1688 else
1689 {
1690
1691 insideComment = false;
1692 offset++;
1693 break;
1694 }
1695 }
1696
1697
1698 switch ( line.charAt( 0 ) )
1699 {
1700 case '#':
1701 insideComment = true;
1702 break;
1703
1704 case ' ':
1705 isFirstLine = false;
1706
1707 if ( insideComment )
1708 {
1709 continue;
1710 }
1711 else if ( sb.length() == 0 )
1712 {
1713 LOG.error( I18n.err( I18n.ERR_12062_EMPTY_CONTINUATION_LINE, lineNumber ) );
1714 throw new LdapLdifException( I18n.err( I18n.ERR_12061_LDIF_PARSING_ERROR ) );
1715 }
1716 else
1717 {
1718 sb.append( line.substring( 1 ) );
1719 }
1720
1721 insideComment = false;
1722 break;
1723
1724 default:
1725 isFirstLine = false;
1726
1727
1728
1729 if ( sb.length() != 0 )
1730 {
1731 lines.add( sb.toString() );
1732 }
1733
1734 sb = new StringBuilder( line );
1735 insideComment = false;
1736 break;
1737 }
1738
1739 byte[] data = Strings.getBytesUtf8( line );
1740
1741 offset += ( data.length + 1 );
1742 entryLen += ( data.length + 1 );
1743 }
1744 }
1745 catch ( IOException ioe )
1746 {
1747 throw new LdapLdifException( I18n.err( I18n.ERR_12063_ERROR_WHILE_READING_LDIF_LINE ), ioe );
1748 }
1749
1750
1751 if ( sb.length() != 0 )
1752 {
1753 lines.add( sb.toString() );
1754 }
1755 }
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765 public List<LdifEntry> parseLdifFile( String fileName ) throws LdapLdifException
1766 {
1767 return parseLdifFile( fileName, Strings.getDefaultCharsetName() );
1768 }
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779 public List<LdifEntry> parseLdifFile( String fileName, String encoding ) throws LdapLdifException
1780 {
1781 if ( Strings.isEmpty( fileName ) )
1782 {
1783 LOG.error( I18n.err( I18n.ERR_12064_EMPTY_FILE_NAME ) );
1784 throw new LdapLdifException( I18n.err( I18n.ERR_12064_EMPTY_FILE_NAME ) );
1785 }
1786
1787 File file = new File( fileName );
1788
1789 if ( !file.exists() )
1790 {
1791 LOG.error( I18n.err( I18n.ERR_12066, fileName ) );
1792 throw new LdapLdifException( I18n.err( I18n.ERR_12067, fileName ) );
1793 }
1794
1795
1796 try (
1797 InputStream is = Files.newInputStream( Paths.get( fileName ) );
1798 BufferedReader bufferReader = new BufferedReader(
1799 new InputStreamReader( is, Charset.forName( encoding ) ) ) )
1800 {
1801 return parseLdif( bufferReader );
1802 }
1803 catch ( FileNotFoundException fnfe )
1804 {
1805 LOG.error( I18n.err( I18n.ERR_12068, fileName ) );
1806 throw new LdapLdifException( I18n.err( I18n.ERR_12067, fileName ), fnfe );
1807 }
1808 catch ( LdapException le )
1809 {
1810 throw new LdapLdifException( le.getMessage(), le );
1811 }
1812 catch ( IOException ioe )
1813 {
1814
1815 throw new LdapLdifException( ioe.getMessage(), ioe );
1816 }
1817 }
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827 public List<LdifEntry> parseLdif( String ldif ) throws LdapLdifException
1828 {
1829 LOG.debug( "Starts parsing ldif buffer" );
1830
1831 if ( Strings.isEmpty( ldif ) )
1832 {
1833 return new ArrayList<>();
1834 }
1835
1836 BufferedReader bufferReader = new BufferedReader( new StringReader( ldif ) );
1837
1838 try
1839 {
1840 List<LdifEntry> entries = parseLdif( bufferReader );
1841
1842 if ( LOG.isDebugEnabled() )
1843 {
1844 LOG.debug( "Parsed {} entries.", Integer.valueOf( entries.size() ) );
1845 }
1846
1847 return entries;
1848 }
1849 catch ( LdapLdifException ne )
1850 {
1851 LOG.error( I18n.err( I18n.ERR_12069, ne.getLocalizedMessage() ) );
1852 throw new LdapLdifException( I18n.err( I18n.ERR_12070 ), ne );
1853 }
1854 catch ( LdapException le )
1855 {
1856 throw new LdapLdifException( le.getMessage(), le );
1857 }
1858 finally
1859 {
1860
1861 try
1862 {
1863 bufferReader.close();
1864 }
1865 catch ( IOException ioe )
1866 {
1867 throw new LdapLdifException( I18n.err( I18n.ERR_12024_CANNOT_CLOSE_FILE ), ioe );
1868 }
1869
1870 }
1871 }
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882 private LdifEntry nextInternal()
1883 {
1884 try
1885 {
1886 LOG.debug( "next(): -- called" );
1887
1888 LdifEntry entry = prefetched;
1889 readLines();
1890
1891 try
1892 {
1893 prefetched = parseEntry();
1894 }
1895 catch ( LdapLdifException ne )
1896 {
1897 error = ne;
1898 throw new NoSuchElementException( ne.getMessage() );
1899 }
1900 catch ( LdapException le )
1901 {
1902 throw new NoSuchElementException( le.getMessage() );
1903 }
1904
1905 LOG.debug( "next(): -- returning ldif {}\n", entry );
1906
1907 return entry;
1908 }
1909 catch ( LdapLdifException ne )
1910 {
1911 LOG.error( I18n.err( I18n.ERR_12071 ) );
1912 error = ne;
1913 return null;
1914 }
1915 }
1916
1917
1918
1919
1920
1921
1922
1923 public LdifEntry next()
1924 {
1925 return nextInternal();
1926 }
1927
1928
1929
1930
1931
1932
1933
1934 public LdifEntry fetch()
1935 {
1936 return prefetched;
1937 }
1938
1939
1940
1941
1942
1943
1944
1945 private boolean hasNextInternal()
1946 {
1947 return null != prefetched;
1948 }
1949
1950
1951
1952
1953
1954
1955
1956 public boolean hasNext()
1957 {
1958 if ( prefetched != null )
1959 {
1960 LOG.debug( "hasNext(): -- returning true" );
1961 }
1962 else
1963 {
1964 LOG.debug( "hasNext(): -- returning false" );
1965 }
1966
1967 return hasNextInternal();
1968 }
1969
1970
1971
1972
1973
1974
1975
1976 private void removeInternal()
1977 {
1978 throw new UnsupportedOperationException();
1979 }
1980
1981
1982
1983
1984
1985
1986
1987 public void remove()
1988 {
1989 removeInternal();
1990 }
1991
1992
1993
1994
1995
1996 @Override
1997 public Iterator<LdifEntry> iterator()
1998 {
1999 return new Iterator<LdifEntry>()
2000 {
2001 @Override
2002 public boolean hasNext()
2003 {
2004 return hasNextInternal();
2005 }
2006
2007
2008 @Override
2009 public LdifEntry next()
2010 {
2011 try
2012 {
2013 return nextInternal();
2014 }
2015 catch ( NoSuchElementException nse )
2016 {
2017 LOG.error( nse.getMessage() );
2018 return null;
2019 }
2020 }
2021
2022
2023 @Override
2024 public void remove()
2025 {
2026 throw new UnsupportedOperationException();
2027 }
2028 };
2029 }
2030
2031
2032
2033
2034
2035 public boolean hasError()
2036 {
2037 return error != null;
2038 }
2039
2040
2041
2042
2043
2044 public Exception getError()
2045 {
2046 return error;
2047 }
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058 public List<LdifEntry> parseLdif( BufferedReader reader ) throws LdapException
2059 {
2060
2061 List<LdifEntry> entries = new ArrayList<>();
2062
2063 this.reader = reader;
2064
2065
2066 version = parseVersion();
2067 prefetched = parseEntry();
2068
2069
2070 for ( LdifEntry entry : this )
2071 {
2072 if ( entry != null )
2073 {
2074 entries.add( entry );
2075 }
2076 else
2077 {
2078 throw new LdapLdifException( I18n.err( I18n.ERR_12072, error.getLocalizedMessage() ) );
2079 }
2080 }
2081
2082 return entries;
2083 }
2084
2085
2086
2087
2088
2089 public boolean containsEntries()
2090 {
2091 return containsEntries;
2092 }
2093
2094
2095
2096
2097
2098 public int getLineNumber()
2099 {
2100 return lineNumber;
2101 }
2102
2103
2104
2105
2106
2107
2108
2109
2110 protected LdifEntry createLdifEntry( SchemaManager schemaManager )
2111 {
2112 if ( schemaManager != null )
2113 {
2114 return new LdifEntry( schemaManager );
2115 }
2116 else
2117 {
2118 return new LdifEntry();
2119 }
2120 }
2121
2122
2123
2124
2125
2126 public boolean isValidateDn()
2127 {
2128 return validateDn;
2129 }
2130
2131
2132
2133
2134
2135
2136
2137 public void setValidateDn( boolean validateDn )
2138 {
2139 this.validateDn = validateDn;
2140 }
2141
2142
2143
2144
2145
2146 public void setSchemaManager( SchemaManager schemaManager )
2147 {
2148 this.schemaManager = schemaManager;
2149 }
2150
2151
2152
2153
2154
2155 @Override
2156 public void close() throws IOException
2157 {
2158 if ( reader != null )
2159 {
2160 position = 0;
2161 reader.close();
2162 containsEntries = false;
2163 containsChanges = false;
2164 offset = 0;
2165 entryOffset = 0;
2166 lineNumber = 0;
2167 }
2168 }
2169 }