1 | /** |
2 | * Licensed to jclouds, Inc. (jclouds) under one or more |
3 | * contributor license agreements. See the NOTICE file |
4 | * distributed with this work for additional information |
5 | * regarding copyright ownership. jclouds licenses this file |
6 | * to you under the Apache License, Version 2.0 (the |
7 | * "License"); you may not use this file except in compliance |
8 | * with the License. You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, |
13 | * software distributed under the License is distributed on an |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | * KIND, either express or implied. See the License for the |
16 | * specific language governing permissions and limitations |
17 | * under the License. |
18 | */ |
19 | package org.jclouds.rest.suppliers; |
20 | |
21 | import static com.google.common.base.Suppliers.memoizeWithExpiration; |
22 | |
23 | import java.util.concurrent.TimeUnit; |
24 | import java.util.concurrent.atomic.AtomicReference; |
25 | |
26 | import org.jclouds.concurrent.RetryOnTimeOutExceptionSupplier; |
27 | import org.jclouds.rest.AuthorizationException; |
28 | |
29 | import com.google.common.base.Supplier; |
30 | |
31 | /** |
32 | * This will retry the supplier if it encounters a timeout exception, but not if it encounters an |
33 | * AuthorizationException. |
34 | * <p/> |
35 | * A shared exception reference is used so that anyone who encounters an authorizationexception will |
36 | * be short-circuited. This prevents accounts from being locked out. |
37 | * |
38 | * <h3>details</h3> |
39 | * http://code.google.com/p/google-guice/issues/detail?id=483 guice doesn't remember when singleton |
40 | * providers throw exceptions. in this case, if the supplier fails with an authorization exception, |
41 | * it is called again for each provider method that depends on it. To short-circuit this, we |
42 | * remember the last exception trusting that guice is single-threaded. |
43 | * |
44 | * @author Adrian Cole |
45 | */ |
46 | public class MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> implements Supplier<T> { |
47 | private final Supplier<T> delegate; |
48 | private final long seconds; |
49 | |
50 | public MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier( |
51 | AtomicReference<AuthorizationException> authException, long seconds, Supplier<T> delegate) { |
52 | this.delegate = memoizeWithExpiration(new RetryOnTimeOutExceptionSupplier<T>( |
53 | new SetAndThrowAuthorizationExceptionSupplier<T>(delegate, authException)), seconds, TimeUnit.SECONDS); |
54 | this.seconds = seconds; |
55 | } |
56 | |
57 | @Override |
58 | public T get() { |
59 | return delegate.get(); |
60 | } |
61 | |
62 | @Override |
63 | public String toString() { |
64 | return "memoizeWithExpiration(" + delegate + ", seconds=" + seconds + ")"; |
65 | } |
66 | } |