This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
The following commit(s) were added to refs/heads/master by this push: new 2708527 [IO-706] Add TimetampedObserver. 2708527 is described below commit 27085271e9b881c2001eb70fac80e32c2f778958 Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Sat Jan 30 13:07:19 2021 -0500 [IO-706] Add TimetampedObserver. --- src/changes/changes.xml | 3 + .../commons/io/input/TimetampedObserver.java | 89 ++++++++++++++++++++++ .../commons/io/input/TimetampedObserverTest.java | 68 +++++++++++++++++ 3 files changed, 160 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 39925ed..cbddecf 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -163,6 +163,9 @@ The <action> type attribute can be add,update,fix,remove. <action dev="ggregory" type="add" due-to="Gary Gregory"> Make ObservableInputStream.getObservers() public. </action> + <action issue="IO-706" dev="ggregory" type="add" due-to="Gary Gregory"> + Add TimetampedObserver. + </action> <!-- UPDATES --> <action dev="ggregory" type="update" due-to="Dependabot"> Update junit-jupiter from 5.6.2 to 5.7.0 #153. diff --git a/src/main/java/org/apache/commons/io/input/TimetampedObserver.java b/src/main/java/org/apache/commons/io/input/TimetampedObserver.java new file mode 100644 index 0000000..1123431 --- /dev/null +++ b/src/main/java/org/apache/commons/io/input/TimetampedObserver.java @@ -0,0 +1,89 @@ +/* + * 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.commons.io.input; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; + +import org.apache.commons.io.input.ObservableInputStream.Observer; + +/** + * An observer with timestamps. + * <p> + * For example: + * </p> + * + * <pre> + * final TimetampedObserver timetampedObserver = new TimetampedObserver(); + * try (final ObservableInputStream inputStream = new ObservableInputStream(...), + * timetampedObserver)) { + * ... + * } + * System.out.printf("IO duration: %s%n", timetampedObserver.getOpenToCloseDuration()); + * </pre> + * + * @since 2.9.0 + */ +public class TimetampedObserver extends Observer { + + private volatile Instant closeInstant; + private final Instant openInstant = Instant.now(); + + @Override + public void closed() throws IOException { + closeInstant = Instant.now(); + } + + /** + * Gets the instant for when this instance was closed. + * + * @return the instant for when closed was called. + */ + public Instant getCloseInstant() { + return closeInstant; + } + + /** + * Gets the Duration between creation and close. + * + * @return the Duration between creation and close. + */ + public Duration getOpenToCloseDuration() { + return Duration.between(openInstant, closeInstant); + } + + /** + * Gets the Duration between creation and now. + * + * @return the Duration between creation and now. + */ + public Duration getOpenToNowDuration() { + return Duration.between(openInstant, Instant.now()); + } + + /** + * Gets the instant for when this instance was created. + * + * @return the instant for when this instance was created. + */ + public Instant getOpenInstant() { + return openInstant; + } + +} diff --git a/src/test/java/org/apache/commons/io/input/TimetampedObserverTest.java b/src/test/java/org/apache/commons/io/input/TimetampedObserverTest.java new file mode 100644 index 0000000..c5ed179 --- /dev/null +++ b/src/test/java/org/apache/commons/io/input/TimetampedObserverTest.java @@ -0,0 +1,68 @@ +/* + * 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.commons.io.input; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.time.Instant; + +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link TimetampedObserver}. + */ +public class TimetampedObserverTest { + + @Test + public void test() throws IOException, InterruptedException { + final Instant before = Instant.now(); + Thread.sleep(20); // Some OS' clock granularity may be high. + final TimetampedObserver timetampedObserver = new TimetampedObserver(); + assertTrue(timetampedObserver.getOpenInstant().isAfter(before)); + assertTrue(timetampedObserver.getOpenToNowDuration().toNanos() > 0); + assertNull(timetampedObserver.getCloseInstant()); + final byte[] buffer = MessageDigestCalculatingInputStreamTest + .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); + try (final ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), + timetampedObserver)) { + assertTrue(timetampedObserver.getOpenInstant().isAfter(before)); + assertTrue(timetampedObserver.getOpenToNowDuration().toNanos() > 0); + } + assertTrue(timetampedObserver.getOpenInstant().isAfter(before)); + assertTrue(timetampedObserver.getOpenToNowDuration().toNanos() > 0); + assertTrue(timetampedObserver.getCloseInstant().isAfter(timetampedObserver.getOpenInstant())); + assertTrue(timetampedObserver.getOpenToCloseDuration().toNanos() > 0); + } + + @Test + public void testExample() throws IOException, InterruptedException { + final TimetampedObserver timetampedObserver = new TimetampedObserver(); + final byte[] buffer = MessageDigestCalculatingInputStreamTest + .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); + try (final ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), + timetampedObserver)) { + // + } + System.out.printf("IO duration: %s%n", timetampedObserver.getOpenToCloseDuration()); + } + +}