0
# LDIF Processing
1
2
Complete support for LDAP Data Interchange Format (LDIF) reading, writing, and manipulation for importing, exporting, and processing LDAP directory data.
3
4
## Capabilities
5
6
### LDIF Reading
7
8
#### LDIFReader
9
10
Primary class for reading LDIF files and processing entries and change records.
11
12
```java { .api }
13
/**
14
* Reader for LDIF (LDAP Data Interchange Format) files
15
*/
16
public class LDIFReader implements Closeable {
17
// Constructors
18
public LDIFReader(String filePath) throws IOException;
19
public LDIFReader(File file) throws IOException;
20
public LDIFReader(InputStream inputStream);
21
public LDIFReader(BufferedReader reader);
22
23
// Reading operations
24
public LDIFRecord readLDIFRecord() throws IOException, LDIFException;
25
public Entry readEntry() throws IOException, LDIFException;
26
public LDIFChangeRecord readChangeRecord() throws IOException, LDIFException;
27
28
// Configuration
29
public void setDuplicateValueBehavior(DuplicateValueBehavior behavior);
30
public DuplicateValueBehavior getDuplicateValueBehavior();
31
public void setTrailingSpaceBehavior(TrailingSpaceBehavior behavior);
32
public TrailingSpaceBehavior getTrailingSpaceBehavior();
33
public void setSchema(Schema schema);
34
public Schema getSchema();
35
36
// Statistics
37
public long getEntriesRead();
38
public long getChangeRecordsRead();
39
public long getLinesRead();
40
41
// Resource management
42
public void close() throws IOException;
43
}
44
45
/**
46
* Behavior for handling duplicate attribute values
47
*/
48
public enum DuplicateValueBehavior {
49
STRIP,
50
RETAIN,
51
REJECT;
52
}
53
54
/**
55
* Behavior for handling trailing spaces in attribute values
56
*/
57
public enum TrailingSpaceBehavior {
58
STRIP,
59
RETAIN,
60
REJECT;
61
}
62
```
63
64
### LDIF Writing
65
66
#### LDIFWriter
67
68
Primary class for writing LDIF files with entries and change records.
69
70
```java { .api }
71
/**
72
* Writer for LDIF files
73
*/
74
public class LDIFWriter implements Closeable {
75
// Constructors
76
public LDIFWriter(String filePath) throws IOException;
77
public LDIFWriter(File file) throws IOException;
78
public LDIFWriter(OutputStream outputStream);
79
public LDIFWriter(BufferedWriter writer);
80
81
// Writing operations
82
public void writeEntry(Entry entry) throws IOException;
83
public void writeEntry(Entry entry, String comment) throws IOException;
84
public void writeChangeRecord(LDIFChangeRecord changeRecord) throws IOException;
85
public void writeChangeRecord(LDIFChangeRecord changeRecord, String comment) throws IOException;
86
public void writeLDIFRecord(LDIFRecord record) throws IOException;
87
public void writeComment(String comment) throws IOException;
88
89
// Configuration
90
public void setWrapColumn(int wrapColumn);
91
public int getWrapColumn();
92
public void setBase64EncodeLength(int base64EncodeLength);
93
public int getBase64EncodeLength();
94
95
// Statistics
96
public long getEntriesWritten();
97
public long getChangeRecordsWritten();
98
99
// Resource management
100
public void close() throws IOException;
101
}
102
```
103
104
### LDIF Records
105
106
#### LDIFRecord
107
108
Base class for all LDIF record types.
109
110
```java { .api }
111
/**
112
* Base class for LDIF records (entries and change records)
113
*/
114
public abstract class LDIFRecord implements Serializable {
115
public abstract String getDN();
116
public abstract int hashCode();
117
public abstract boolean equals(Object obj);
118
public abstract String toString();
119
public abstract String toLDIFString();
120
public abstract String toLDIFString(int wrapColumn);
121
}
122
```
123
124
#### LDIFChangeRecord
125
126
Base class for LDIF change records (add, delete, modify, modifyDN).
127
128
```java { .api }
129
/**
130
* Base class for LDIF change records
131
*/
132
public abstract class LDIFChangeRecord extends LDIFRecord {
133
public abstract ChangeType getChangeType();
134
public abstract LDAPRequest toLDAPRequest();
135
public abstract LDAPResult processChange(LDAPInterface connection) throws LDAPException;
136
137
// Factory methods
138
public static LDIFChangeRecord decode(String... ldifLines) throws LDIFException;
139
public static List<LDIFChangeRecord> parseChangeRecords(String ldifContent) throws LDIFException;
140
}
141
142
/**
143
* Change type enumeration
144
*/
145
public enum ChangeType {
146
ADD("add"),
147
DELETE("delete"),
148
MODIFY("modify"),
149
MODIFY_DN("moddn");
150
151
public String getName();
152
public static ChangeType forName(String name);
153
}
154
```
155
156
#### LDIFAddChangeRecord
157
158
LDIF change record for add operations.
159
160
```java { .api }
161
/**
162
* LDIF change record for add operations
163
*/
164
public class LDIFAddChangeRecord extends LDIFChangeRecord {
165
// Constructors
166
public LDIFAddChangeRecord(String dn, Attribute... attributes);
167
public LDIFAddChangeRecord(String dn, Collection<Attribute> attributes);
168
public LDIFAddChangeRecord(Entry entry);
169
170
// Access methods
171
public String getDN();
172
public List<Attribute> getAttributes();
173
public Attribute getAttribute(String name);
174
public String getAttributeValue(String name);
175
public ChangeType getChangeType(); // Returns ADD
176
177
// Conversion methods
178
public AddRequest toAddRequest();
179
public LDAPRequest toLDAPRequest();
180
public Entry toEntry();
181
public LDAPResult processChange(LDAPInterface connection) throws LDAPException;
182
}
183
```
184
185
#### LDIFDeleteChangeRecord
186
187
LDIF change record for delete operations.
188
189
```java { .api }
190
/**
191
* LDIF change record for delete operations
192
*/
193
public class LDIFDeleteChangeRecord extends LDIFChangeRecord {
194
// Constructors
195
public LDIFDeleteChangeRecord(String dn);
196
197
// Access methods
198
public String getDN();
199
public ChangeType getChangeType(); // Returns DELETE
200
201
// Conversion methods
202
public DeleteRequest toDeleteRequest();
203
public LDAPRequest toLDAPRequest();
204
public LDAPResult processChange(LDAPInterface connection) throws LDAPException;
205
}
206
```
207
208
#### LDIFModifyChangeRecord
209
210
LDIF change record for modify operations.
211
212
```java { .api }
213
/**
214
* LDIF change record for modify operations
215
*/
216
public class LDIFModifyChangeRecord extends LDIFChangeRecord {
217
// Constructors
218
public LDIFModifyChangeRecord(String dn, Modification... modifications);
219
public LDIFModifyChangeRecord(String dn, List<Modification> modifications);
220
221
// Access methods
222
public String getDN();
223
public List<Modification> getModifications();
224
public ChangeType getChangeType(); // Returns MODIFY
225
226
// Conversion methods
227
public ModifyRequest toModifyRequest();
228
public LDAPRequest toLDAPRequest();
229
public LDAPResult processChange(LDAPInterface connection) throws LDAPException;
230
}
231
```
232
233
#### LDIFModifyDNChangeRecord
234
235
LDIF change record for modify DN operations.
236
237
```java { .api }
238
/**
239
* LDIF change record for modify DN operations
240
*/
241
public class LDIFModifyDNChangeRecord extends LDIFChangeRecord {
242
// Constructors
243
public LDIFModifyDNChangeRecord(String dn, String newRDN, boolean deleteOldRDN);
244
public LDIFModifyDNChangeRecord(String dn, String newRDN, boolean deleteOldRDN, String newSuperiorDN);
245
246
// Access methods
247
public String getDN();
248
public String getNewRDN();
249
public boolean deleteOldRDN();
250
public String getNewSuperiorDN();
251
public ChangeType getChangeType(); // Returns MODIFY_DN
252
253
// Conversion methods
254
public ModifyDNRequest toModifyDNRequest();
255
public LDAPRequest toLDAPRequest();
256
public LDAPResult processChange(LDAPInterface connection) throws LDAPException;
257
}
258
```
259
260
### Entry Sources
261
262
#### LDIFEntrySource
263
264
Entry source backed by LDIF data for streaming processing.
265
266
```java { .api }
267
/**
268
* Entry source backed by LDIF data
269
*/
270
public class LDIFEntrySource implements EntrySource {
271
// Constructors
272
public LDIFEntrySource(LDIFReader ldifReader);
273
public LDIFEntrySource(String filePath) throws IOException;
274
public LDIFEntrySource(File file) throws IOException;
275
public LDIFEntrySource(InputStream inputStream);
276
277
// EntrySource implementation
278
public Entry nextEntry() throws EntrySourceException;
279
public void close();
280
281
// Statistics
282
public long getEntriesRead();
283
}
284
```
285
286
## Usage Examples
287
288
### Reading LDIF Files
289
290
```java
291
import com.unboundid.ldap.sdk.*;
292
import com.unboundid.ldif.*;
293
294
// Read entries from LDIF file
295
try (LDIFReader ldifReader = new LDIFReader("data.ldif")) {
296
297
// Configure reader behavior
298
ldifReader.setDuplicateValueBehavior(DuplicateValueBehavior.STRIP);
299
ldifReader.setTrailingSpaceBehavior(TrailingSpaceBehavior.STRIP);
300
301
Entry entry;
302
int entryCount = 0;
303
304
while ((entry = ldifReader.readEntry()) != null) {
305
entryCount++;
306
System.out.println("Entry " + entryCount + ": " + entry.getDN());
307
308
// Process entry attributes
309
for (Attribute attr : entry.getAttributes()) {
310
System.out.println(" " + attr.getName() + ": " + Arrays.toString(attr.getValues()));
311
}
312
}
313
314
System.out.println("Total entries read: " + entryCount);
315
316
} catch (IOException | LDIFException e) {
317
System.err.println("Error reading LDIF: " + e.getMessage());
318
}
319
```
320
321
### Writing LDIF Files
322
323
```java
324
import com.unboundid.ldap.sdk.*;
325
import com.unboundid.ldif.*;
326
327
// Write entries to LDIF file
328
try (LDIFWriter ldifWriter = new LDIFWriter("output.ldif")) {
329
330
// Configure writer
331
ldifWriter.setWrapColumn(80);
332
333
// Write comment
334
ldifWriter.writeComment("Exported user data");
335
ldifWriter.writeComment("Generated on " + new Date());
336
337
// Create and write entries
338
Entry entry1 = new Entry(
339
"cn=John Doe,ou=people,dc=example,dc=com",
340
new Attribute("objectClass", "inetOrgPerson"),
341
new Attribute("cn", "John Doe"),
342
new Attribute("sn", "Doe"),
343
new Attribute("givenName", "John"),
344
new Attribute("mail", "john.doe@example.com")
345
);
346
347
ldifWriter.writeEntry(entry1, "Primary user account");
348
349
Entry entry2 = new Entry(
350
"cn=Jane Smith,ou=people,dc=example,dc=com",
351
new Attribute("objectClass", "inetOrgPerson"),
352
new Attribute("cn", "Jane Smith"),
353
new Attribute("sn", "Smith"),
354
new Attribute("givenName", "Jane"),
355
new Attribute("mail", "jane.smith@example.com")
356
);
357
358
ldifWriter.writeEntry(entry2);
359
360
System.out.println("Entries written: " + ldifWriter.getEntriesWritten());
361
362
} catch (IOException e) {
363
System.err.println("Error writing LDIF: " + e.getMessage());
364
}
365
```
366
367
### Processing Change Records
368
369
```java
370
import com.unboundid.ldap.sdk.*;
371
import com.unboundid.ldif.*;
372
373
// Read and process LDIF change records
374
try (LDIFReader ldifReader = new LDIFReader("changes.ldif")) {
375
376
LDIFRecord record;
377
while ((record = ldifReader.readLDIFRecord()) != null) {
378
379
if (record instanceof LDIFChangeRecord) {
380
LDIFChangeRecord changeRecord = (LDIFChangeRecord) record;
381
382
System.out.println("Change Type: " + changeRecord.getChangeType());
383
System.out.println("DN: " + changeRecord.getDN());
384
385
switch (changeRecord.getChangeType()) {
386
case ADD:
387
LDIFAddChangeRecord addRecord = (LDIFAddChangeRecord) changeRecord;
388
System.out.println("Adding entry with " + addRecord.getAttributes().size() + " attributes");
389
break;
390
391
case DELETE:
392
System.out.println("Deleting entry");
393
break;
394
395
case MODIFY:
396
LDIFModifyChangeRecord modifyRecord = (LDIFModifyChangeRecord) changeRecord;
397
System.out.println("Modifying entry with " + modifyRecord.getModifications().size() + " modifications");
398
for (Modification mod : modifyRecord.getModifications()) {
399
System.out.println(" " + mod.getModificationType() + " " + mod.getAttributeName());
400
}
401
break;
402
403
case MODIFY_DN:
404
LDIFModifyDNChangeRecord modDNRecord = (LDIFModifyDNChangeRecord) changeRecord;
405
System.out.println("Renaming to: " + modDNRecord.getNewRDN());
406
break;
407
}
408
409
System.out.println("---");
410
} else if (record instanceof Entry) {
411
Entry entry = (Entry) record;
412
System.out.println("Entry: " + entry.getDN() + " (" + entry.getAttributes().size() + " attributes)");
413
}
414
}
415
416
} catch (IOException | LDIFException e) {
417
System.err.println("Error processing LDIF: " + e.getMessage());
418
}
419
```
420
421
### Applying Changes to LDAP Server
422
423
```java
424
import com.unboundid.ldap.sdk.*;
425
import com.unboundid.ldif.*;
426
427
// Apply LDIF changes to LDAP server
428
LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);
429
430
try {
431
connection.bind("cn=admin,dc=example,dc=com", "password");
432
433
try (LDIFReader ldifReader = new LDIFReader("changes.ldif")) {
434
435
LDIFChangeRecord changeRecord;
436
int successCount = 0;
437
int errorCount = 0;
438
439
while ((changeRecord = ldifReader.readChangeRecord()) != null) {
440
try {
441
LDAPResult result = changeRecord.processChange(connection);
442
443
if (result.getResultCode() == ResultCode.SUCCESS) {
444
successCount++;
445
System.out.println("Applied " + changeRecord.getChangeType() + " for " + changeRecord.getDN());
446
} else {
447
errorCount++;
448
System.err.println("Failed " + changeRecord.getChangeType() + " for " + changeRecord.getDN() +
449
": " + result.getDiagnosticMessage());
450
}
451
452
} catch (LDAPException e) {
453
errorCount++;
454
System.err.println("Error applying change for " + changeRecord.getDN() + ": " + e.getMessage());
455
}
456
}
457
458
System.out.println("Changes applied successfully: " + successCount);
459
System.out.println("Changes failed: " + errorCount);
460
461
}
462
463
} finally {
464
connection.close();
465
}
466
```
467
468
### LDIF Data Transformation
469
470
```java
471
import com.unboundid.ldap.sdk.*;
472
import com.unboundid.ldif.*;
473
474
// Transform LDIF data during processing
475
try (LDIFReader reader = new LDIFReader("input.ldif");
476
LDIFWriter writer = new LDIFWriter("transformed.ldif")) {
477
478
Entry entry;
479
while ((entry = reader.readEntry()) != null) {
480
481
// Transform the entry
482
Entry transformedEntry = transformEntry(entry);
483
484
if (transformedEntry != null) {
485
writer.writeEntry(transformedEntry);
486
}
487
}
488
489
System.out.println("Transformation complete");
490
}
491
492
private static Entry transformEntry(Entry originalEntry) {
493
// Skip entries without mail attribute
494
if (!originalEntry.hasAttribute("mail")) {
495
return null;
496
}
497
498
// Create new entry with transformed DN
499
String originalDN = originalEntry.getDN();
500
String newDN = originalDN.replace("dc=old,dc=com", "dc=new,dc=com");
501
502
Entry newEntry = new Entry(newDN);
503
504
// Copy and transform attributes
505
for (Attribute attr : originalEntry.getAttributes()) {
506
String attrName = attr.getName();
507
508
if ("mail".equals(attrName)) {
509
// Transform email addresses
510
String[] oldValues = attr.getValues();
511
String[] newValues = new String[oldValues.length];
512
for (int i = 0; i < oldValues.length; i++) {
513
newValues[i] = oldValues[i].replace("@old.com", "@new.com");
514
}
515
newEntry.addAttribute(new Attribute(attrName, newValues));
516
} else if ("telephoneNumber".equals(attrName)) {
517
// Skip telephone numbers in transformation
518
continue;
519
} else {
520
// Copy attribute as-is
521
newEntry.addAttribute(attr);
522
}
523
}
524
525
return newEntry;
526
}
527
```