CAMEL-8585: camel-csv in lazyLoad mode should close the parser so it can release resources such as file handlers on windows.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/92a39383 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/92a39383 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/92a39383 Branch: refs/heads/camel-2.15.x Commit: 92a393839dcbb9a58ccd8e630330e1bd6d0e9ccb Parents: 54c63fc Author: Claus Ibsen <davscl...@apache.org> Authored: Thu Apr 2 10:44:55 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Thu Apr 2 10:45:11 2015 +0200 ---------------------------------------------------------------------- .../csv/CsvUnmarshalOnCompletion.java | 41 +++++++++++++++++++ .../camel/dataformat/csv/CsvUnmarshaller.java | 22 ++++++++-- .../csv/CsvUnmarshalStreamSpringTest.java | 30 ++++++-------- .../camel/dataformat/csv/CsvUnmarshalTest.java | 42 +++++++++++--------- .../CsvUnmarshalStreamSpringTest-context.xml | 7 +++- 5 files changed, 100 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/92a39383/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshalOnCompletion.java ---------------------------------------------------------------------- diff --git a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshalOnCompletion.java b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshalOnCompletion.java new file mode 100644 index 0000000..2bbb13b --- /dev/null +++ b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshalOnCompletion.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.dataformat.csv; + +import java.io.Closeable; +import java.io.IOException; + +import org.apache.camel.Exchange; +import org.apache.camel.support.SynchronizationAdapter; + +public class CsvUnmarshalOnCompletion extends SynchronizationAdapter { + + private final Closeable closeable; + + public CsvUnmarshalOnCompletion(Closeable closeable) { + this.closeable = closeable; + } + + @Override + public void onDone(Exchange exchange) { + try { + closeable.close(); + } catch (IOException e) { + // ignore + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/92a39383/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshaller.java ---------------------------------------------------------------------- diff --git a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshaller.java b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshaller.java index d5fc315..da0ed54 100644 --- a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshaller.java +++ b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvUnmarshaller.java @@ -16,6 +16,7 @@ */ package org.apache.camel.dataformat.csv; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -111,6 +112,7 @@ abstract class CsvUnmarshaller { */ @SuppressWarnings("unchecked") private static final class StreamCsvUnmarshaller extends CsvUnmarshaller { + private StreamCsvUnmarshaller(CSVFormat format, CsvDataFormat dataFormat) { super(format, dataFormat); } @@ -121,7 +123,10 @@ abstract class CsvUnmarshaller { try { reader = new InputStreamReader(inputStream, IOHelper.getCharsetName(exchange)); CSVParser parser = new CSVParser(reader, format); - return new CsvIterator(parser.iterator(), converter); + CsvIterator answer = new CsvIterator(parser, converter); + // add to UoW so we can close the iterator so it can release any resources + exchange.addOnCompletion(new CsvUnmarshalOnCompletion(answer)); + return answer; } catch (Exception e) { IOHelper.close(reader); throw e; @@ -134,12 +139,14 @@ abstract class CsvUnmarshaller { * * @param <T> Converted type */ - private static final class CsvIterator<T> implements Iterator<T> { + private static final class CsvIterator<T> implements Iterator<T>, Closeable { + private final CSVParser parser; private final Iterator<CSVRecord> iterator; private final CsvRecordConverter<T> converter; - private CsvIterator(Iterator<CSVRecord> iterator, CsvRecordConverter<T> converter) { - this.iterator = iterator; + private CsvIterator(CSVParser parser, CsvRecordConverter<T> converter) { + this.parser = parser; + this.iterator = parser.iterator(); this.converter = converter; } @@ -157,6 +164,13 @@ abstract class CsvUnmarshaller { public void remove() { iterator.remove(); } + + @Override + public void close() throws IOException { + if (!parser.isClosed()) { + parser.close(); + } + } } //endregion } http://git-wip-us.apache.org/repos/asf/camel/blob/92a39383/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest.java ---------------------------------------------------------------------- diff --git a/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest.java b/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest.java index 4c880c4..549e4d0 100644 --- a/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest.java +++ b/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest.java @@ -17,8 +17,7 @@ package org.apache.camel.dataformat.csv; import java.util.Arrays; -import java.util.Iterator; -import java.util.NoSuchElementException; +import java.util.List; import org.apache.camel.EndpointInject; import org.apache.camel.component.mock.MockEndpoint; @@ -29,30 +28,25 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class CsvUnmarshalStreamSpringTest extends CamelSpringTestSupport { - public static final String MESSAGE = "message"; + private static final String CSV_SAMPLE = "A,B,C\r1,2,3\rone,two,three"; - @EndpointInject(uri = "mock:result") - private MockEndpoint result; + @EndpointInject(uri = "mock:line") + private MockEndpoint line; @Test public void testCsvUnMarshal() throws Exception { - result.expectedMessageCount(1); + line.expectedMessageCount(3); - template.sendBody("direct:start", MESSAGE + "\n"); + template.sendBody("direct:start", CSV_SAMPLE); assertMockEndpointsSatisfied(); - Iterator<?> body = result.getReceivedExchanges().get(0).getIn().getBody(Iterator.class); - Iterator iterator = assertIsInstanceOf(Iterator.class, body); - assertTrue(iterator.hasNext()); - assertEquals(Arrays.asList(MESSAGE), iterator.next()); - assertFalse(iterator.hasNext()); - try { - iterator.next(); - fail("Should have thrown exception"); - } catch (NoSuchElementException nsee) { - // expected - } + List body1 = line.getExchanges().get(0).getIn().getBody(List.class); + List body2 = line.getExchanges().get(1).getIn().getBody(List.class); + List body3 = line.getExchanges().get(2).getIn().getBody(List.class); + assertEquals(Arrays.asList("A", "B", "C"), body1); + assertEquals(Arrays.asList("1", "2", "3"), body2); + assertEquals(Arrays.asList("one", "two", "three"), body3); } @Override http://git-wip-us.apache.org/repos/asf/camel/blob/92a39383/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalTest.java ---------------------------------------------------------------------- diff --git a/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalTest.java b/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalTest.java index 0e86e9c..094ee04 100644 --- a/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalTest.java +++ b/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/CsvUnmarshalTest.java @@ -19,6 +19,7 @@ package org.apache.camel.dataformat.csv; import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.apache.camel.EndpointInject; import org.apache.camel.builder.RouteBuilder; @@ -37,6 +38,9 @@ public class CsvUnmarshalTest extends CamelTestSupport { @EndpointInject(uri = "mock:output") MockEndpoint output; + @EndpointInject(uri = "mock:line") + MockEndpoint line; + @Test public void shouldUseDefaultFormat() throws Exception { output.expectedMessageCount(1); @@ -66,16 +70,16 @@ public class CsvUnmarshalTest extends CamelTestSupport { @Test public void shouldUseLazyLoading() throws Exception { - output.expectedMessageCount(1); - + line.expectedMessageCount(3); template.sendBody("direct:lazy", CSV_SAMPLE); - output.assertIsSatisfied(); - - Iterator<?> body = assertIsInstanceOf(Iterator.class, output.getExchanges().get(0).getIn().getBody()); - assertEquals(Arrays.asList("A", "B", "C"), body.next()); - assertEquals(Arrays.asList("1", "2", "3"), body.next()); - assertEquals(Arrays.asList("one", "two", "three"), body.next()); - assertFalse(body.hasNext()); + line.assertIsSatisfied(); + + List body1 = line.getExchanges().get(0).getIn().getBody(List.class); + List body2 = line.getExchanges().get(1).getIn().getBody(List.class); + List body3 = line.getExchanges().get(2).getIn().getBody(List.class); + assertEquals(Arrays.asList("A", "B", "C"), body1); + assertEquals(Arrays.asList("1", "2", "3"), body2); + assertEquals(Arrays.asList("one", "two", "three"), body3); } @Test @@ -93,15 +97,15 @@ public class CsvUnmarshalTest extends CamelTestSupport { @Test public void shouldUseLazyLoadingAndMaps() throws Exception { - output.expectedMessageCount(1); - + line.expectedMessageCount(2); template.sendBody("direct:lazy_map", CSV_SAMPLE); - output.assertIsSatisfied(); + line.assertIsSatisfied(); + + Map map1 = line.getExchanges().get(0).getIn().getBody(Map.class); + Map map2 = line.getExchanges().get(1).getIn().getBody(Map.class); - Iterator<?> body = assertIsInstanceOf(Iterator.class, output.getExchanges().get(0).getIn().getBody()); - assertEquals(asMap("A", "1", "B", "2", "C", "3"), body.next()); - assertEquals(asMap("A", "one", "B", "two", "C", "three"), body.next()); - assertFalse(body.hasNext()); + assertEquals(asMap("A", "1", "B", "2", "C", "3"), map1); + assertEquals(asMap("A", "one", "B", "two", "C", "three"), map2); } @Test @@ -135,7 +139,8 @@ public class CsvUnmarshalTest extends CamelTestSupport { // Lazy load from("direct:lazy") .unmarshal(new CsvDataFormat().setLazyLoad(true)) - .to("mock:output"); + .split().body() + .to("mock:line"); // Use maps from("direct:map") @@ -145,7 +150,8 @@ public class CsvUnmarshalTest extends CamelTestSupport { // Use lazy load and maps from("direct:lazy_map") .unmarshal(new CsvDataFormat().setLazyLoad(true).setUseMaps(true)) - .to("mock:output"); + .split().body() + .to("mock:line"); // Use map without first line and headers from("direct:map_headers") http://git-wip-us.apache.org/repos/asf/camel/blob/92a39383/components/camel-csv/src/test/resources/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest-context.xml ---------------------------------------------------------------------- diff --git a/components/camel-csv/src/test/resources/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest-context.xml b/components/camel-csv/src/test/resources/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest-context.xml index f510201..41c5b56 100644 --- a/components/camel-csv/src/test/resources/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest-context.xml +++ b/components/camel-csv/src/test/resources/org/apache/camel/dataformat/csv/CsvUnmarshalStreamSpringTest-context.xml @@ -24,9 +24,12 @@ <route> <from uri="direct:start" /> <unmarshal> - <csv delimiter="|" lazyLoad="true"/> + <csv delimiter="," lazyLoad="true"/> </unmarshal> - <to uri="mock:result" /> + <split> + <simple>${body}</simple> + <to uri="mock:line" /> + </split> </route> </camelContext> </beans>