@SuppressWarnings("unchecked") private static <S> Supplier<S> constructorOf(Class<S> impl) { try { return (Supplier<S>) Unchecked.supplier(MethodHandles.lookup().findConstructor(impl, MethodType.methodType(void.class))::invoke); } catch (ReflectiveOperationException e) { throw new IllegalArgumentException("Couldn't find public constructor of " + impl, e); } }
@Override public void set(String property, Object value) { Unchecked.biFunction(properties.get(property).setter::invoke).apply(instance, value); }
@Override T newInstance(Object... params) { return Unchecked.<Object[], T>function(constructor::newInstance).apply(params); }
@Override public Object get(T pojo) { return Unchecked.callable(() -> { if (Boolean.TRUE.equals(isSet.invoke(pojo))) { return getter.invoke(pojo); } else { return null; } }).call(); } }
/** * Install a given {@link JdbiPlugin} instance that will configure any * provided {@link Handle} instances. * @param plugin the plugin to install * @return this */ public Jdbi installPlugin(JdbiPlugin plugin) { Unchecked.consumer(plugin::customizeJdbi).accept(this); plugins.add(plugin); return this; }
@Test public void testConcurrent() throws Exception { ExecutorService es = Executors.newFixedThreadPool(3); final CountDownLatch inserted = new CountDownLatch(1); final CountDownLatch committed = new CountDownLatch(1); final Other o = dbRule.getJdbi().onDemand(Other.class); Future<Void> rf = es.submit(Unchecked.callable(() -> { o.insert(inserted, 1, "diwaker"); committed.countDown(); return null; })); Future<Void> tf = es.submit(Unchecked.callable(() -> { inserted.await(); committed.await(); Something s2 = o.find(1); assertThat(s2).isEqualTo(new Something(1, "diwaker")); return null; })); rf.get(); tf.get(); es.shutdown(); }
private static Optional<Supplier<?>> nullaryMethodOf(Class<?> impl, String methodName) { try { return Optional.of(Unchecked.supplier(MethodHandles.lookup() .unreflect(impl.getMethod(methodName))::invoke)); } catch (ReflectiveOperationException e) { return Optional.empty(); } }
@Override public T build() { return defn.cast(Unchecked.function(builderBuild::invoke).apply(b)); } };
@Override public void set(String property, Object value) { Unchecked.biFunction(properties.get(property).setter::invoke).apply(b, value); }
@Test public void testConcurrent() throws Exception { ExecutorService es = Executors.newFixedThreadPool(3); final CountDownLatch inserted = new CountDownLatch(1); final CountDownLatch committed = new CountDownLatch(1); final Other o = dbRule.getJdbi().onDemand(Other.class); Future<Void> rf = es.submit(Unchecked.callable(() -> { o.insert(inserted, 1, "diwaker"); committed.countDown(); return null; })); Future<Void> tf = es.submit(Unchecked.callable(() -> { inserted.await(); committed.await(); Something s2 = o.find(1); assertThat(s2).isEqualTo(new Something(1, "diwaker")); return null; })); rf.get(); tf.get(); es.shutdown(); }
@Override public Optional<RowMapper<?>> build(Type type, ConfigRegistry config) { Class<?> erasedType = getErasedType(type); MapWith mapWith = erasedType.getAnnotation(MapWith.class); return mapWith == null ? Optional.empty() : Optional.of(Unchecked.supplier(mapWith.value()::newInstance).get()); } }
private static Object invoke(Object target, Method method, Object[] args) { if (Proxy.isProxyClass(target.getClass())) { InvocationHandler handler = Proxy.getInvocationHandler(target); return Unchecked.<Object[], Object>function((params) -> handler.invoke(target, method, params)).apply(args); } else { MethodHandle handle = Unchecked.function(MethodHandles.lookup()::unreflect).apply(method).bindTo(target); return Unchecked.<Object[], Object>function(handle::invokeWithArguments).apply(args); } } }
@Override T newInstance(Object... params) { return type.cast(Unchecked.<Object, Object[], Object>biFunction(method::invoke).apply(null, params)); }
@Test public void hidesThrowsClause() { CheckedSupplier<Void> throwing = UncheckedTest::failToGet; assertThatThrownBy(throwing::get) .describedAs("throws a checked exception") .isInstanceOf(SQLException.class); Supplier<Void> muted = Unchecked.supplier(throwing); assertThat(muted) .describedAs("does not declare a checked exception") .isInstanceOf(Supplier.class); assertThatThrownBy(muted::get) .describedAs("still throws a checked exception") .isInstanceOf(SQLException.class); }
@Override public Object invoke(Object target, Object[] args, HandleSupplier handle) { return Unchecked.<Object[], Object>function(methodHandle.bindTo(target)::invokeWithArguments).apply(args); }
DefaultMethodHandler(Method method) { Class<?> declaringClass = method.getDeclaringClass(); methodHandle = Unchecked.biFunction(lookupFor(declaringClass)::unreflectSpecial).apply(method, declaringClass); }
@Override public Optional<RowMapper<?>> build(Type type, ConfigRegistry config) { Class<?> erasedType = getErasedType(type); MapWith mapWith = erasedType.getAnnotation(MapWith.class); return mapWith == null ? Optional.empty() : Optional.of(Unchecked.supplier(mapWith.value()::newInstance).get()); } }
static MethodHandles.Lookup lookupFor(Class<?> clazz) { if (PRIVATE_LOOKUP_IN != null) { try { return (MethodHandles.Lookup) PRIVATE_LOOKUP_IN.invoke(null, clazz, MethodHandles.lookup()); } catch (IllegalAccessException | InvocationTargetException e) { String message = String.format( "Error invoking MethodHandles.privateLookupIn(%s.class, MethodHandles.lookup()) in JDK 9+ runtime", clazz); throw new RuntimeException(message, e); } } // TERRIBLE, HORRIBLE, NO GOOD, VERY BAD HACK // Courtesy of: // https://rmannibucau.wordpress.com/2014/03/27/java-8-default-interface-methods-and-jdk-dynamic-proxies/ // We can use MethodHandles to look up and invoke the super method, but since this class is not an // implementation of method.getDeclaringClass(), MethodHandles.Lookup will throw an exception since // this class doesn't have access to the super method, according to Java's access rules. This horrible, // awful workaround allows us to directly invoke MethodHandles.Lookup's private constructor, bypassing // the usual access checks. // This workaround is only used in JDK 8.x runtimes. JDK 9+ runtimes use MethodHandles.privateLookupIn() // above. return PRIVATE_LOOKUPS.computeIfAbsent(clazz, Unchecked.function(DefaultMethodHandler::getConstructorLookup)); }
@Override public Optional<Handler> buildHandler(Class<?> sqlObjectType, Method method) { if (!method.isBridge()) { return Optional.empty(); } return Stream.of(sqlObjectType.getMethods()) .filter(candidate -> !candidate.isBridge() && Objects.equals(candidate.getName(), method.getName()) && candidate.getParameterCount() == method.getParameterCount()) .filter(candidate -> { Class<?>[] candidateParamTypes = candidate.getParameterTypes(); Class<?>[] methodParamTypes = method.getParameterTypes(); return IntStream.range(0, method.getParameterCount()) .allMatch(i -> methodParamTypes[i].isAssignableFrom(candidateParamTypes[i])); }) .<Handler>map(m -> { final MethodHandle mh = unreflect(sqlObjectType, m); return (target, args, handle) -> Unchecked.<Object[], Object>function(mh.bindTo(target)::invokeWithArguments).apply(args); }) .findFirst(); }