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