INT-3738: Fix FileSplitter

JIRA: https://jira.spring.io/browse/INT-3738

Don't rely on `BufferedReader.ready()` to detect EOF.

Polishing FileSplitter Fix
This commit is contained in:
Gary Russell
2015-06-12 16:37:37 -04:00
committed by Artem Bilan
parent 505bfac2f8
commit c278548216
2 changed files with 25 additions and 10 deletions

View File

@@ -30,6 +30,7 @@ import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException;
import org.springframework.integration.file.splitter.FileSplitter.FileMarker.Mark; import org.springframework.integration.file.splitter.FileSplitter.FileMarker.Mark;
import org.springframework.integration.splitter.AbstractMessageSplitter; import org.springframework.integration.splitter.AbstractMessageSplitter;
@@ -87,7 +88,7 @@ public class FileSplitter extends AbstractMessageSplitter {
* the markers are included in the sequence size. * the markers are included in the sequence size.
* @param iterator true to return an iterator, false to return a list of lines. * @param iterator true to return an iterator, false to return a list of lines.
* @param markers true to emit start of file/end of file marker messages before/after the data. * @param markers true to emit start of file/end of file marker messages before/after the data.
* @since 1.4.5 * @since 4.1.5
*/ */
public FileSplitter(boolean iterator, boolean markers) { public FileSplitter(boolean iterator, boolean markers) {
this.iterator = iterator; this.iterator = iterator;
@@ -165,10 +166,18 @@ public class FileSplitter extends AbstractMessageSplitter {
boolean done; boolean done;
String line;
boolean hasNextCalled;
@Override @Override
public boolean hasNext() { public boolean hasNext() {
this.hasNextCalled = true;
try { try {
boolean ready = !this.done && bufferedReader.ready(); if (this.line == null && !this.done) {
this.line = bufferedReader.readLine();
}
boolean ready = !this.done && this.line != null;
if (!ready) { if (!ready) {
if (this.markers) { if (this.markers) {
this.eof = true; this.eof = true;
@@ -180,6 +189,7 @@ public class FileSplitter extends AbstractMessageSplitter {
catch (IOException e) { catch (IOException e) {
try { try {
bufferedReader.close(); bufferedReader.close();
this.done = true;
} }
catch (IOException e1) {} catch (IOException e1) {}
throw new MessageHandlingException(message, "IOException while iterating", e); throw new MessageHandlingException(message, "IOException while iterating", e);
@@ -188,6 +198,10 @@ public class FileSplitter extends AbstractMessageSplitter {
@Override @Override
public Object next() { public Object next() {
if (!this.hasNextCalled) {
hasNext();
}
this.hasNextCalled = false;
if (this.sof) { if (this.sof) {
this.sof = false; this.sof = false;
return new FileMarker(filePath, Mark.START); return new FileMarker(filePath, Mark.START);
@@ -198,15 +212,14 @@ public class FileSplitter extends AbstractMessageSplitter {
this.done = true; this.done = true;
return new FileMarker(filePath, Mark.END); return new FileMarker(filePath, Mark.END);
} }
try { if (this.line != null) {
return bufferedReader.readLine(); String line = this.line;
this.line = null;
return line;
} }
catch (IOException e) { else {
try { this.done = true;
bufferedReader.close(); throw new NoSuchElementException(filePath + " has been consumed");
}
catch (IOException e1) {}
throw new MessageHandlingException(message, "IOException while iterating", e);
} }
} }

View File

@@ -104,9 +104,11 @@ public class FileSplitterTests {
this.input1.send(new GenericMessage<File>(file)); this.input1.send(new GenericMessage<File>(file));
Message<?> receive = this.output.receive(10000); Message<?> receive = this.output.receive(10000);
assertNotNull(receive); //HelloWorld assertNotNull(receive); //HelloWorld
assertEquals("HelloWorld", receive.getPayload());
assertEquals(2, receive.getHeaders().get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE)); assertEquals(2, receive.getHeaders().get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE));
receive = this.output.receive(10000); receive = this.output.receive(10000);
assertNotNull(receive); //äöüß assertNotNull(receive); //äöüß
assertEquals("äöüß", receive.getPayload());
assertNull(this.output.receive(1)); assertNull(this.output.receive(1));
this.input1.send(new GenericMessage<String>(file.getAbsolutePath())); this.input1.send(new GenericMessage<String>(file.getAbsolutePath()));