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<String> 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); + } + } +}