JCLOUDS-1334: Guava 23 compatiblity

Reflective creation of SimpleTimeLimiter to allow compatibility with
Guava 23.0.  SimpleTimeLimiter.create(ExecutorService) was introduced
in Guava 22.0 to replace the SimpleTimeLimiter(ExecutorService)
constructor, which was deprecated in Guava 22.0 and removed in Guava
23.0.
This commit is contained in:
Tim Peierls 2017-08-26 10:41:36 -04:00 committed by Andrew Gaul
parent 5e12796a34
commit e08acc6ed6
3 changed files with 62 additions and 5 deletions

View File

@ -20,6 +20,9 @@ import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.concurrent.DynamicExecutors.newScalingThreadPool;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;
@ -54,6 +57,60 @@ import com.google.inject.Provides;
@ConfiguresExecutorService
public class ExecutorServiceModule extends AbstractModule {
private static final Method CREATE_STL;
private static final Constructor<SimpleTimeLimiter> CONSTRUCT_STL;
static {
Method create = null;
Constructor ctor = null;
try {
create = SimpleTimeLimiter.class.getDeclaredMethod("create", ExecutorService.class);
} catch (NoSuchMethodException nsme) {
try {
ctor = SimpleTimeLimiter.class.getConstructor(ExecutorService.class);
} catch (NoSuchMethodException nsme2) {
throw new UnsupportedOperationException(
"Can't find SimpleTimeLimiter creator or constructor taking ExecutorService", nsme2);
}
}
CREATE_STL = create;
CONSTRUCT_STL = ctor;
}
/**
* Reflective creation of SimpleTimeLimiter to allow compatibility with Guava 23.0.
* SimpleTimeLimiter.create(ExecutorService) was introduced in Guava 22.0 to replace
* the SimpleTimeLimiter(ExecutorService) constructor, which was deprecated in
* Guava 22.0 and removed in Guava 23.0. The method is public to allow test methods
* in other packages to use it.
* @param executorService the execution service to use when running time-limited tasks
* @return a new instance of SimpleTimeLimiter that uses executorService
*/
public static SimpleTimeLimiter createSimpleTimeLimiter(ExecutorService executorService) {
try {
if (CREATE_STL != null) {
return (SimpleTimeLimiter) CREATE_STL.invoke(null, executorService);
} else if (CONSTRUCT_STL != null) {
return CONSTRUCT_STL.newInstance(executorService);
}
throw new UnsupportedOperationException(
"Can't find SimpleTimeLimiter creator or constructor taking ExecutorService");
} catch (IllegalAccessException iae) {
throw new UnsupportedOperationException("Can't access SimpleTimeLimiter method/ctor", iae);
} catch (InstantiationException ie) {
throw new UnsupportedOperationException("Can't construct SimpleTimeLimiter", ie);
} catch (InvocationTargetException ite) {
Throwable throwable = ite.getCause();
if (throwable instanceof RuntimeException) {
throw (RuntimeException) throwable;
}
if (throwable instanceof Error) {
throw (Error) throwable;
}
throw new UnsupportedOperationException(
"Checked exception thrown while creating SimpleTimeLimiter", throwable);
}
}
static final class ShutdownExecutorOnClose implements Closeable {
@Resource
private Logger logger = Logger.NULL;
@ -113,7 +170,7 @@ public class ExecutorServiceModule extends AbstractModule {
@Provides
@Singleton
final TimeLimiter timeLimiter(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
return new SimpleTimeLimiter(userExecutor);
return createSimpleTimeLimiter(userExecutor);
}
@Provides

View File

@ -22,6 +22,7 @@ import static com.google.inject.name.Names.named;
import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS;
import static org.jclouds.Constants.PROPERTY_MAX_RETRIES;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.concurrent.config.ExecutorServiceModule.createSimpleTimeLimiter;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
@ -80,7 +81,6 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteSource;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.SimpleTimeLimiter;
import com.google.common.util.concurrent.TimeLimiter;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
@ -235,7 +235,7 @@ public abstract class BaseRestApiExpectTest<S> {
@Provides
@Singleton
TimeLimiter timeLimiter(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
return new SimpleTimeLimiter(userExecutor);
return createSimpleTimeLimiter(userExecutor);
}
}

View File

@ -22,6 +22,7 @@ import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorS
import static com.google.inject.name.Names.named;
import static org.easymock.EasyMock.createMock;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.concurrent.config.ExecutorServiceModule.createSimpleTimeLimiter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@ -50,7 +51,6 @@ import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
import com.google.common.reflect.Invokable;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.SimpleTimeLimiter;
import com.google.common.util.concurrent.TimeLimiter;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
@ -84,7 +84,7 @@ public abstract class BaseRestApiTest {
@Provides
@Singleton
TimeLimiter timeLimiter(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
return new SimpleTimeLimiter(userExecutor);
return createSimpleTimeLimiter(userExecutor);
}
}