This is an automated email from the ASF dual-hosted git repository.

reschke pushed a commit to branch OAK-11571
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


The following commit(s) were added to refs/heads/OAK-11571 by this push:
     new 80fd3120ce OAK-11571: commons: add Closer class (similar to Guava 
Closer) - add replacement and switch tests to new class
80fd3120ce is described below

commit 80fd3120ced0339405ce92bfe65766cdc3c5a21c
Author: Julian Reschke <[email protected]>
AuthorDate: Thu Mar 13 16:31:17 2025 +0100

    OAK-11571: commons: add Closer class (similar to Guava Closer) - add 
replacement and switch tests to new class
---
 oak-commons/pom.xml                                |   3 +-
 .../apache/jackrabbit/oak/commons/pio/Closer.java  | 128 +++++++++++++++++++++
 .../jackrabbit/oak/commons/pio/package-info.java   |  28 +++++
 .../jackrabbit/oak/commons/io/CloserTest.java      |  20 ++--
 4 files changed, 169 insertions(+), 10 deletions(-)

diff --git a/oak-commons/pom.xml b/oak-commons/pom.xml
index 385104b03c..c25643f766 100644
--- a/oak-commons/pom.xml
+++ b/oak-commons/pom.xml
@@ -56,7 +56,8 @@
               org.apache.jackrabbit.oak.commons.log,
               org.apache.jackrabbit.oak.commons.sort,
               org.apache.jackrabbit.oak.commons.properties,
-              org.apache.jackrabbit.oak.commons.jdkcompat
+              org.apache.jackrabbit.oak.commons.jdkcompat,
+              org.apache.jackrabbit.oak.commons.io
             </Export-Package>
           </instructions>
         </configuration>
diff --git 
a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/pio/Closer.java 
b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/pio/Closer.java
new file mode 100755
index 0000000000..3cc3cf3101
--- /dev/null
+++ 
b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/pio/Closer.java
@@ -0,0 +1,128 @@
+/*
+ * 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.jackrabbit.oak.commons.pio;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Objects;
+
+/**
+ * Convenience utility to close a list of {@link Closeable}s.
+ * <p>
+ * Inspired by and replacing Guava's Closer.
+ */
+public class Closer {
+
+    private Closer() {
+        // no instances for you
+    }
+
+    // stack of closeables to close
+    private Deque<Closeable> closeables = new ArrayDeque<>();
+
+    // set by rethrow method
+    private Throwable rethrow = null;
+
+    /**
+     * Create instance of Closer.
+     */
+    public static Closer create() {
+        return new Closer();
+    }
+
+    /**
+     * Add a {@link Closeable} to the list.
+     * @param closeable
+     */
+    public void register(@Nullable Closeable closeable) {
+        if (closeable != null) {
+            closeables.add(closeable);
+        }
+    }
+
+    /**
+     * Closes the set of {@link Closeable}s in reverse order.
+     * <p>
+     * Swallows all {@link IOException}s except the first that
+     * was thrown.
+     * <p>
+     * If {@link #rethrow} was called before, throw <em>that</em>
+     * exception instead (wrapped into a {@link RuntimeException}
+     * when necessary).
+     */
+    public void close() throws IOException {
+        // keep track of the IOException to throw
+        IOException toThrow = null;
+
+        // close all in reverse order
+        while (!closeables.isEmpty()) {
+            Closeable closeable = closeables.removeLast();
+            try {
+                closeable.close();
+            } catch (IOException exception) {
+                // remember the first one that occured
+                if (toThrow == null) {
+                    toThrow = exception;
+                }
+            }
+        }
+
+        // consider exceptions passed to rethrow()
+        if (rethrow instanceof IOException) {
+            throw (IOException) rethrow;
+        } else if (rethrow instanceof RuntimeException) {
+            throw (RuntimeException) rethrow;
+        } else if (rethrow != null) {
+            throw new RuntimeException(rethrow);
+        }
+
+        // otherwise throw the IOException we selected
+        if (toThrow != null) {
+            throw toThrow;
+        }
+    }
+
+    /**
+     * Stores a {@link Throwable} for later use in {@link #close()} and
+     * rethrows it (potentially wrapped into {@link RuntimeException} or
+     * {@link Error}.
+     * <p>
+     * {@link #close()} will use the exception passed in the last call of this
+     * method.
+     * @return never returns
+     * @throws IOException
+     */
+    public RuntimeException rethrow(@NotNull Throwable throwable) throws 
IOException {
+        rethrow = Objects.requireNonNull(throwable);
+        if (throwable instanceof IOException) {
+            throw (IOException) throwable;
+        } else if (throwable instanceof RuntimeException) {
+            throw (RuntimeException) throwable;
+        } else if (throwable instanceof Error) {
+            throw (Error) throwable;
+        } else {
+            throw new RuntimeException(throwable);
+        }
+    }
+}
diff --git 
a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/pio/package-info.java
 
b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/pio/package-info.java
new file mode 100644
index 0000000000..d552c968ab
--- /dev/null
+++ 
b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/pio/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/**
+ * Internal ("private") utilities related to IO..
+ */
+@Internal(since = "1.0.0")
+@Version("1.0.0")
+package org.apache.jackrabbit.oak.commons.pio;
+import org.apache.jackrabbit.oak.commons.annotations.Internal;
+import org.osgi.annotation.versioning.Version;
+
diff --git 
a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/io/CloserTest.java
 
b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/io/CloserTest.java
index bc20525288..e6ba84abad 100644
--- 
a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/io/CloserTest.java
+++ 
b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/io/CloserTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.jackrabbit.oak.commons.io;
 
-import org.apache.jackrabbit.guava.common.io.Closer;
+import org.apache.jackrabbit.oak.commons.pio.Closer;
 import org.junit.Test;
 
 import java.io.Closeable;
@@ -33,11 +33,11 @@ import static org.junit.Assert.fail;
 
 public class CloserTest {
 
-    // tests below confirm what Guava actually does
+    // tests below confirm what  actually does
 
     @Test
-    public void testGuavaCloserOrder() throws IOException {
-        // shows that Guava closes in reverse order
+    public void testCloserOrder() throws IOException {
+        // shows that  closes in reverse order
 
         int cnt = 2;
         List<Integer> order = new ArrayList<>();
@@ -62,7 +62,7 @@ public class CloserTest {
     }
 
     @Test
-    public void testGuavaCloseableThrowsRuntimeException() {
+    public void testCloseableThrowsRuntimeException() {
         Closer closer = Closer.create();
         closer.register(() -> {
             throw new RuntimeException();
@@ -71,7 +71,7 @@ public class CloserTest {
     }
 
     @Test
-    public void testGuavaWhichThrows() throws IOException {
+    public void testWhichThrows() throws IOException {
         // shows which exception is not suppressed
 
         int cnt = 2;
@@ -100,7 +100,7 @@ public class CloserTest {
     }
 
     @Test
-    public void testGuavaRethrowRuntime() {
+    public void testRethrowRuntime() {
         try {
             Closer closer = Closer.create();
             try {
@@ -114,13 +114,15 @@ public class CloserTest {
                 closer.close();
             }
         } catch (Exception ex) {
-            assertTrue("should throw the (wrapped) unchecked exception",
+            assertTrue(
+                    "should throw the (wrapped) unchecked exception, but got " 
+
+                    ex.getMessage(),
                     ex.getMessage().contains("unchecked"));
         }
     }
 
     @Test
-    public void testGuavaRethrowChecked() throws IOException {
+    public void testRethrowChecked() throws IOException {
         try {
             Closer closer = Closer.create();
             try {

Reply via email to