TAMAYA-39 Added helper class to have a better way available to close overhanded streams in the formats module.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/9b941f83 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/9b941f83 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/9b941f83 Branch: refs/heads/master Commit: 9b941f839c74dfe7f0edd26e0384183ffef035b6 Parents: e471c4d Author: Oliver B. Fischer <ple...@apache.org> Authored: Sat Feb 28 11:25:15 2015 +0100 Committer: Oliver B. Fischer <ple...@apache.org> Committed: Sat Feb 28 23:41:21 2015 +0100 ---------------------------------------------------------------------- modules/formats/pom.xml | 6 + .../apache/tamaya/format/InputStreamCloser.java | 93 ++++++++++ .../tamaya/format/InputStreamCloserTest.java | 169 +++++++++++++++++++ .../modules/json/JSONConfigurationFormat.java | 42 +++++ 4 files changed, 310 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9b941f83/modules/formats/pom.xml ---------------------------------------------------------------------- diff --git a/modules/formats/pom.xml b/modules/formats/pom.xml index 39fca56..6cb185e 100644 --- a/modules/formats/pom.xml +++ b/modules/formats/pom.xml @@ -48,9 +48,15 @@ under the License. <version>${project.version}</version> <scope>test</scope> </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + </dependency> </dependencies> </project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9b941f83/modules/formats/src/main/java/org/apache/tamaya/format/InputStreamCloser.java ---------------------------------------------------------------------- diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/InputStreamCloser.java b/modules/formats/src/main/java/org/apache/tamaya/format/InputStreamCloser.java new file mode 100644 index 0000000..70056e6 --- /dev/null +++ b/modules/formats/src/main/java/org/apache/tamaya/format/InputStreamCloser.java @@ -0,0 +1,93 @@ +/* + * 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.tamaya.format; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Objects; + +/** + * Wrapper for a given {@link InputStream} to be able to close + * it via the try-with-resources construct of Java 7. + * + * <h1>Usage example</h1> + * + * <pre> + *public void readIt(InputStream inputStream) { + * try (InputStream is = new InputStreamCloser(inputStream) { + * // Consume the stream + * } + *} + * </pre> + */ +public class InputStreamCloser extends InputStream { + private InputStream wrapped; + + public InputStreamCloser(InputStream original) { + Objects.requireNonNull(original); + + wrapped = original; + } + + + @Override + public int read(byte[] b) throws IOException { + return wrapped.read(b); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return wrapped.read(b, off, len); + } + + @Override + public long skip(long n) throws IOException { + return wrapped.skip(n); + } + + @Override + public int available() throws IOException { + return wrapped.available(); + } + + @Override + public void close() throws IOException { + wrapped.close(); + } + + @Override + public synchronized void mark(int readlimit) { + wrapped.mark(readlimit); + } + + @Override + public synchronized void reset() throws IOException { + wrapped.reset(); + } + + @Override + public boolean markSupported() { + return wrapped.markSupported(); + } + + @Override + public int read() throws IOException { + return wrapped.read(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9b941f83/modules/formats/src/test/java/org/apache/tamaya/format/InputStreamCloserTest.java ---------------------------------------------------------------------- diff --git a/modules/formats/src/test/java/org/apache/tamaya/format/InputStreamCloserTest.java b/modules/formats/src/test/java/org/apache/tamaya/format/InputStreamCloserTest.java new file mode 100644 index 0000000..52c4b0e --- /dev/null +++ b/modules/formats/src/test/java/org/apache/tamaya/format/InputStreamCloserTest.java @@ -0,0 +1,169 @@ +/* + * 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.tamaya.format; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import java.io.IOException; +import java.io.InputStream; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class InputStreamCloserTest { + + @Test(expected = NullPointerException.class) + public void ctorEnforcesNonNullOriginal() { + new InputStreamCloser(null); + } + + @Test + public void callToReadIsForwardedCallToWrapped() throws IOException { + InputStream stream = mock(InputStream.class); + + doReturn(34).when(stream).read(Mockito.anyVararg()); + + InputStreamCloser closer = new InputStreamCloser(stream); + + byte[] byteArray = new byte[4]; + assertThat(closer.read(byteArray), equalTo(34)); + + verify(stream).read(byteArray); + } + + + @Test + public void callToReadWithOffsetIsForwardedCallToWrapped() throws IOException { + byte[] array = new byte[10]; + ArgumentCaptor<byte[]> arrayCaptor = ArgumentCaptor.forClass(byte[].class); + ArgumentCaptor<Integer> offsetCaptor = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> lengthCaptor = ArgumentCaptor.forClass(Integer.class); + InputStream stream = mock(InputStream.class); + + doReturn(23).when(stream).read(Mockito.anyVararg(), Mockito.anyInt(), Mockito.anyInt()); + + InputStreamCloser closer = new InputStreamCloser(stream); + + assertThat(closer.read(array, 10, 20), equalTo(23)); + + verify(stream).read(arrayCaptor.capture(), offsetCaptor.capture(), lengthCaptor.capture()); + + assertThat(offsetCaptor.getValue(), equalTo(10)); + assertThat(lengthCaptor.getValue(), equalTo(20)); + assertThat(arrayCaptor.getValue(), equalTo(array)); + } + + @Test + public void callToSkipIsForwardedToWrapped() throws IOException { + ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(Long.class); + InputStream stream = mock(InputStream.class); + + doReturn(1234L).when(stream).skip(anyLong()); + + InputStreamCloser closer = new InputStreamCloser(stream); + + assertThat(closer.skip(4567L), equalTo(1234L)); + + verify(stream).skip(captor.capture()); + + assertThat(captor.getValue(), equalTo(4567L)); + } + + + @Test + public void callToAvailableIsForwardedToWrapped() throws IOException { + InputStream stream = mock(InputStream.class); + + doReturn(123).when(stream).available(); + + InputStreamCloser closer = new InputStreamCloser(stream); + + assertThat(closer.available(), equalTo(123)); + + verify(stream).available(); + } + + @Test + public void callToCloseIsForwardedToWrapped() throws IOException { + InputStream stream = mock(InputStream.class); + InputStreamCloser closer = new InputStreamCloser(stream); + + closer.close(); + + verify(stream).close(); + } + + @Test + public void callToMarkIsForwardedToWrapped() { + ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class); + InputStream stream = mock(InputStream.class); + InputStreamCloser closer = new InputStreamCloser(stream); + + closer.mark(456); + + verify(stream).mark(captor.capture()); + + assertThat(captor.getValue(), equalTo(456)); + } + + + @Test + public void callToResetIsForwardedToWrapped() throws IOException { + InputStream stream = mock(InputStream.class); + + InputStreamCloser closer = new InputStreamCloser(stream); + + closer.reset(); + + verify(stream).reset(); + } + + @Test + public void callToMarkSupportedIsForwardedToWrapped() { + InputStream stream = mock(InputStream.class); + + doReturn(false).when(stream).markSupported(); + + InputStreamCloser closer = new InputStreamCloser(stream); + + assertThat(closer.markSupported(), is(false)); + + verify(stream).markSupported(); + } + + @Test + public void callToReadIsForwardedToWrapped() throws IOException { + InputStream stream = mock(InputStream.class); + InputStreamCloser closer = new InputStreamCloser(stream); + + doReturn(4).when(stream).read(); + + assertThat(closer.read(), equalTo(4)); + + verify(stream).read(); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9b941f83/modules/json/src/main/java/org/apache/tamaya/modules/json/JSONConfigurationFormat.java ---------------------------------------------------------------------- diff --git a/modules/json/src/main/java/org/apache/tamaya/modules/json/JSONConfigurationFormat.java b/modules/json/src/main/java/org/apache/tamaya/modules/json/JSONConfigurationFormat.java new file mode 100644 index 0000000..fdc1907 --- /dev/null +++ b/modules/json/src/main/java/org/apache/tamaya/modules/json/JSONConfigurationFormat.java @@ -0,0 +1,42 @@ +/* + * 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.tamaya.modules.json; + +import org.apache.tamaya.format.ConfigurationData; +import org.apache.tamaya.format.ConfigurationFormat; + +import java.io.InputStream; +import java.net.URL; + +/** + * Configuration format able to read JSON files and to turn them in + * {@link org.apache.tamaya.format.ConfigurationData} instances. + */ +public class JSONConfigurationFormat implements ConfigurationFormat { + + @Override + public boolean accepts(URL url) { + throw new java.lang.RuntimeException("Not implemented yet!"); + } + + @Override + public ConfigurationData readConfiguration(String resource, InputStream inputStream) { + throw new java.lang.RuntimeException("Not implemented yet!"); + } +}