| /* |
| * Copyright 2009-2010 Rickard Öberg AB |
| * |
| * Licensed 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.qi4j.library.circuitbreaker; |
| |
| import org.qi4j.functional.Specification; |
| import org.qi4j.io.Output; |
| import org.qi4j.io.Receiver; |
| import org.qi4j.io.Sender; |
| |
| /** |
| * CircuitBreaker helper methods. |
| */ |
| public class CircuitBreakers |
| { |
| public static <Item, ReceiverThrowable extends Throwable> Output<Item, ReceiverThrowable> withBreaker( final CircuitBreaker breaker, final Output<Item, ReceiverThrowable> output) |
| { |
| return new Output<Item, ReceiverThrowable>() |
| { |
| @Override |
| public <SenderThrowableType extends Throwable> void receiveFrom(final Sender<? extends Item, SenderThrowableType> sender) throws ReceiverThrowable, SenderThrowableType |
| { |
| output.receiveFrom( new Sender<Item, SenderThrowableType>() |
| { |
| @Override |
| public <ReceiverThrowableType extends Throwable> void sendTo(final Receiver<? super Item, ReceiverThrowableType> receiver) throws ReceiverThrowableType, SenderThrowableType |
| { |
| // Check breaker first |
| if (!breaker.isOn()) |
| throw (ReceiverThrowableType) breaker.lastThrowable(); |
| |
| sender.sendTo( new Receiver<Item, ReceiverThrowableType>() |
| { |
| @Override |
| public void receive( Item item ) throws ReceiverThrowableType |
| { |
| try |
| { |
| receiver.receive( item ); |
| |
| // Notify breaker that it went well |
| breaker.success(); |
| } catch (Throwable receiverThrowableType) |
| { |
| // Notify breaker of trouble |
| breaker.throwable( receiverThrowableType ); |
| |
| throw (ReceiverThrowableType) receiverThrowableType; |
| } |
| } |
| }); |
| } |
| }); |
| } |
| }; |
| } |
| |
| /** |
| * Allow all throwables that are equal to or subclasses of given list of throwables. |
| * |
| * @param throwables The Throwable types that are allowed. |
| * @return A Specification that specifies the allowed Throwables. |
| */ |
| public static Specification<Throwable> in( final Class<? extends Throwable>... throwables) |
| { |
| return new Specification<Throwable>() |
| { |
| @Override |
| public boolean satisfiedBy( Throwable item ) |
| { |
| Class<? extends Throwable> throwableClass = item.getClass(); |
| for (Class<? extends Throwable> throwable : throwables) |
| { |
| if (throwable.isAssignableFrom( throwableClass )) |
| return true; |
| } |
| return false; |
| } |
| }; |
| } |
| |
| public static Specification<Throwable> rootCause( final Specification<Throwable> specification) |
| { |
| return new Specification<Throwable>() |
| { |
| @Override |
| public boolean satisfiedBy( Throwable item ) |
| { |
| return specification.satisfiedBy( unwrap(item) ); |
| } |
| |
| private Throwable unwrap(Throwable item) |
| { |
| if (item.getCause() != null) |
| return item.getCause(); |
| else |
| return item; |
| } |
| }; |
| } |
| } |