Author: brentworden
Date: Tue May 24 18:28:13 2011
New Revision: 1127199

URL: http://svn.apache.org/viewvc?rev=1127199&view=rev
Log:
COLLECTIONS-313.  Added abstract closure that is capable of handling thrown 
exceptions from closure execution.

Added:
    
commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/CatchAndRethrowClosure.java
    
commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/BasicClosureTestBase.java
    
commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestCatchAndRethrowClosure.java

Added: 
commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/CatchAndRethrowClosure.java
URL: 
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/CatchAndRethrowClosure.java?rev=1127199&view=auto
==============================================================================
--- 
commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/CatchAndRethrowClosure.java
 (added)
+++ 
commons/proper/collections/trunk/src/java/org/apache/commons/collections/functors/CatchAndRethrowClosure.java
 Tue May 24 18:28:13 2011
@@ -0,0 +1,76 @@
+/*
+ * 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.collections.functors;
+
+import org.apache.commons.collections.Closure;
+import org.apache.commons.collections.FunctorException;
+
+/**
+ * {@link Closure} that catches any checked exception and re-throws it as a
+ * {@link FunctorException} runtime exception. Example usage:
+ * 
+ * <pre>
+ * // Create a catch and re-throw closure via anonymous subclass
+ * CatchAndRethrowClosure&lt;String&gt; writer = new ThrowingClosure() {
+ *     private java.io.Writer out = // some writer
+ *     
+ *     protected void executeAndThrow(String input) throws IOException {
+ *         out.write(input); // throwing of IOException allowed
+ *     }
+ * };
+ * 
+ * // use catch and re-throw closure
+ * java.util.List<String> strList = // some list
+ * try {
+ *     CollctionUtils.forAllDo(strList, writer);
+ * } catch (FunctorException ex) {
+ *     Throwable originalError = ex.getCause();
+ *     // handle error
+ * }
+ * </pre>
+ * 
+ * @since Commons Collections 4.0
+ * @version $Revision: $ $Date: $
+ */
+public abstract class CatchAndRethrowClosure<E> implements Closure<E> {
+
+    /**
+     * Execute this closure on the specified input object.
+     * 
+     * @param input the input to execute on
+     * @throws ClosureException (runtime) if the closure execution resulted in 
a
+     *             checked exception.
+     */
+    public void execute(E input) {
+        try {
+            executeAndThrow(input);
+        } catch (RuntimeException ex) {
+            throw ex;
+        } catch (Throwable t) {
+            throw new FunctorException(t);
+        }
+    }
+
+    /**
+     * Execute this closure on the specified input object.
+     * 
+     * @param input the input to execute on
+     * @throws Throwable if the closure execution resulted in a checked
+     *             exception.
+     */
+    protected abstract void executeAndThrow(E input) throws Throwable;
+}

Added: 
commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/BasicClosureTestBase.java
URL: 
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/BasicClosureTestBase.java?rev=1127199&view=auto
==============================================================================
--- 
commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/BasicClosureTestBase.java
 (added)
+++ 
commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/BasicClosureTestBase.java
 Tue May 24 18:28:13 2011
@@ -0,0 +1,35 @@
+/*
+ * 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.collections.functors;
+
+import org.apache.commons.collections.Closure;
+import org.junit.Assert;
+import org.junit.Test;
+
+public abstract class BasicClosureTestBase {
+
+    @Test
+    public void closureSanityTests() throws Exception {
+        Closure<?> closure = generateClosure();
+        Assert.assertNotNull(closure);
+    }
+
+    /**
+     * @return a closure for general sanity tests.
+     */
+    protected abstract <T> Closure<T> generateClosure();
+}

Added: 
commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestCatchAndRethrowClosure.java
URL: 
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestCatchAndRethrowClosure.java?rev=1127199&view=auto
==============================================================================
--- 
commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestCatchAndRethrowClosure.java
 (added)
+++ 
commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/TestCatchAndRethrowClosure.java
 Tue May 24 18:28:13 2011
@@ -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.commons.collections.functors;
+
+import java.io.IOException;
+
+import org.apache.commons.collections.Closure;
+import org.apache.commons.collections.FunctorException;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCatchAndRethrowClosure extends BasicClosureTestBase {
+
+    private static <T> Closure<T> generateIOExceptionClosure() {
+        return new CatchAndRethrowClosure<T>() {
+
+            @Override
+            protected void executeAndThrow(T input) throws IOException  {
+                throw new IOException();
+            }
+        };
+    }
+
+    private static <T> Closure<T> generateNullPointerExceptionClosure() {
+        return new CatchAndRethrowClosure<T>() {
+
+            @Override
+            protected void executeAndThrow(T input) {
+                throw new NullPointerException();
+            }
+        };
+    }
+
+    private static <T> Closure<T> generateNoExceptionClosure() {
+        return new CatchAndRethrowClosure<T>() {
+
+            @Override
+            protected void executeAndThrow(T input) {
+            }
+        };
+    }
+
+    @Override
+    protected <T> Closure<T> generateClosure() {
+        return generateNoExceptionClosure();
+    }
+    
+    @Test
+    public void testThrowingClosure() {
+        Closure<Integer> closure = generateNoExceptionClosure();
+        try {
+            closure.execute(Integer.valueOf(0));
+        } catch (FunctorException ex) {
+            Assert.fail();
+        } catch (RuntimeException ex) {
+            Assert.fail();
+        }
+        
+        closure = generateIOExceptionClosure();
+        try {
+            closure.execute(Integer.valueOf(0));
+            Assert.fail();
+        } catch (FunctorException ex) {
+            Assert.assertTrue(ex.getCause() instanceof IOException);
+        } catch (RuntimeException ex) {
+            Assert.fail();
+        }
+
+        closure = generateNullPointerExceptionClosure();
+        try {
+            closure.execute(Integer.valueOf(0));
+            Assert.fail();
+        } catch (FunctorException ex) {
+            Assert.fail();
+        } catch (RuntimeException ex) {
+            Assert.assertTrue(ex instanceof NullPointerException);
+        }
+    }
+}


Reply via email to