File: LdifReader.java

package info (click to toggle)
libspring-ldap-java 1.3.1.RELEASE-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,872 kB
  • sloc: java: 12,509; xml: 4,106; jsp: 36; makefile: 33; sh: 13
file content (152 lines) | stat: -rw-r--r-- 5,673 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
package org.springframework.ldap.ldif.batch;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.parser.LdifParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * The {@link LdifReader LdifReader} is an adaptation of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}
 * built around an {@link LdifParser LdifParser}.
 * <p>
 * Unlike the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link LdifReader LdifReader} 
 * does not require a mapper. Instead, this version of the {@link LdifReader LdifReader} simply returns an {@link LdapAttributes LdapAttributes} 
 * object which can be consumed and manipulated as necessary by {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any 
 * output service. Alternatively, the {@link RecordMapper RecordMapper} interface can be implemented and set in a 
 * {@link MappingLdifReader MappingLdifReader} to map records to objects for return.
 * <p>
 * {@link LdifReader LdifReader} usage is mimics that of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader} 
 * for all intensive purposes. Adjustments have been made to process records instead of lines, however.  As such, the 
 * {@link #recordsToSkip recordsToSkip} attribute indicates the number of records from the top of the file that should not be processed.  
 * Implementations of the {@link RecordCallbackHandler RecordCallbackHandler} interface can be used to execute operations on those skipped records.
 * <p>
 * As with the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link #strict strict} option differentiates
 * between whether or not to require the resource to exist before processing.  In the case of a value set to false, a warning is logged instead of
 * an exception being thrown.
 * 
 * @author Keith Barlow
 *
 */
public class LdifReader extends AbstractItemCountingItemStreamItemReader<LdapAttributes> 
		implements ResourceAwareItemReaderItemStream<LdapAttributes>, InitializingBean {

	private static final Log log = LogFactory.getLog(LdifReader.class);

	private Resource resource;
	
	private LdifParser ldifParser;
	
	private int recordCount = 0;

	private int recordsToSkip = 0;

	private boolean strict = true;
	
	private RecordCallbackHandler skippedRecordsCallback;
	
	public LdifReader() {
		setName(ClassUtils.getShortName(LdifReader.class));
	}

	/**
	 * In strict mode the reader will throw an exception on
	 * {@link #open(org.springframework.batch.item.ExecutionContext)} if the
	 * input resource does not exist.
	 * @param strict false by default
	 */
	public void setStrict(boolean strict) {
		this.strict = strict;
	}
	
	/**
	 * {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to take action on skipped records.
	 * 
	 * @param skippedRecordsCallback will be called for each one of the initial
	 * skipped lines before any items are read.
	 */
	public void setSkippedRecordsCallback(RecordCallbackHandler skippedRecordsCallback) {
		this.skippedRecordsCallback = skippedRecordsCallback;
	}

	/**
	 * Public setter for the number of lines to skip at the start of a file. Can
	 * be used if the file contains a header without useful (column name)
	 * information, and without a comment delimiter at the beginning of the
	 * lines.
	 * 
	 * @param recordsToSkip the number of lines to skip
	 */
	public void setRecordsToSkip(int recordsToSkip) {
		this.recordsToSkip = recordsToSkip;
	}
	
	@Override
	protected void doClose() throws Exception {
		if (ldifParser != null) {
			ldifParser.close();
		}
		this.recordCount = 0;
	}

	@Override
	protected void doOpen() throws Exception {
		if (resource == null) 
			throw new IllegalStateException("A resource has not been set.");
		
		if (!resource.exists()) {
			if (strict) {
				throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): "+resource);
			} else {
				log.warn("Input resource does not exist " + resource.getDescription());
				return;
			}
		}
		
		ldifParser.open();
		
		for (int i = 0; i < recordsToSkip; i++) {
			LdapAttributes record = ldifParser.getRecord();
			if (skippedRecordsCallback != null) {
				skippedRecordsCallback.handleRecord(record);
			}
		}		
	}

	@Override
	protected LdapAttributes doRead() throws Exception {
		LdapAttributes attributes = null;
		
		try {			
			if (ldifParser != null) {
				while (attributes == null && ldifParser.hasMoreRecords()) {
					attributes = ldifParser.getRecord();
				}
				recordCount++;
			}
			
			return attributes;
			
		} catch(Exception ex){
			log.error("Parsing error at record " + recordCount + " in resource=" + 
					resource.getDescription() + ", input=[" + attributes + "]", ex);
			throw ex;
		}
	}

	public void setResource(Resource resource) {
		this.resource = resource;
		this.ldifParser = new LdifParser(resource);		
	}

	public void afterPropertiesSet() throws Exception {
		Assert.notNull(resource, "A resource is required to parse.");
		Assert.notNull(ldifParser);		
	}

}