Example usage for java.lang.invoke MethodHandle invokeExact

List of usage examples for java.lang.invoke MethodHandle invokeExact

Introduction

In this page you can find the example usage for java.lang.invoke MethodHandle invokeExact.

Prototype

@HotSpotIntrinsicCandidate
public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;

Source Link

Document

Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.

Usage

From source file:me.rojo8399.placeholderapi.impl.utils.TypeUtils.java

@SuppressWarnings("unchecked")
public static <T> Optional<T> tryCast(Object val, final Class<T> expected) {
    if (val == null) {
        return Optional.empty();
    }/*from www .  j a v  a 2  s  . c om*/
    if (expected == null) {
        throw new IllegalArgumentException("Must provide an expected class!");
    }
    if (val instanceof BaseValue<?> && !BaseValue.class.isAssignableFrom(expected)) {
        return tryCast(((BaseValue<?>) val).get(), expected);
    }
    if (val instanceof Supplier) {
        Supplier<?> fun = (Supplier<?>) val;
        return tryCast(fun.get(), expected);
    }
    if (Text.class.isAssignableFrom(expected)) {
        if (val instanceof Text) {
            return TypeUtils.tryOptional(() -> expected.cast(val));
        } else {
            if (val instanceof ItemStack) {
                return TypeUtils.tryOptional(() -> expected.cast(TextUtils.ofItem((ItemStack) val)));
            }
            if (val instanceof Instant) {
                return TypeUtils.tryOptional(() -> expected.cast(TextSerializers.FORMATTING_CODE
                        .deserialize(PlaceholderAPIPlugin.getInstance().formatter()
                                .format(LocalDateTime.ofInstant((Instant) val, ZoneId.systemDefault())))));
            }
            if (val instanceof Duration) {
                String dur = formatDuration((Duration) val);
                return TypeUtils
                        .tryOptional(() -> expected.cast(TextSerializers.FORMATTING_CODE.deserialize(dur)));
            }
            if (val instanceof LocalDateTime) {
                return TypeUtils.tryOptional(() -> expected.cast(TextSerializers.FORMATTING_CODE.deserialize(
                        PlaceholderAPIPlugin.getInstance().formatter().format((LocalDateTime) val))));
            }
            if (val instanceof CommandSource) {
                return TypeUtils.tryOptional(() -> expected.cast(TextSerializers.FORMATTING_CODE
                        .deserialize(String.valueOf(((CommandSource) val).getName()))));
            }
            if (val.getClass().isArray()) {
                List<Text> l2 = unboxPrimitiveArray(val).stream()
                        .map(o -> tryCast(o, (Class<? extends Text>) expected)).flatMap(unmapOptional())
                        .collect(Collectors.toList());
                return TypeUtils.tryOptional(() -> expected.cast(Text.joinWith(Text.of(", "), l2)));
            }
            if (val instanceof Iterable) {
                Iterable<?> l = (Iterable<?>) val;
                // should be safe cause we already checked assignability
                @SuppressWarnings("serial")
                final List<Text> l2 = new ArrayList<Object>() {
                    {
                        for (Object o : l) {
                            add(o);
                        }
                    }
                }.stream().map(o -> tryCast(o, (Class<? extends Text>) expected)).flatMap(unmapOptional())
                        .collect(Collectors.toList());
                return TypeUtils.tryOptional(() -> expected.cast(Text.joinWith(Text.of(", "), l2)));
            }
            return TypeUtils.tryOptional(
                    () -> expected.cast(TextSerializers.FORMATTING_CODE.deserialize(String.valueOf(val))));
        }
    }
    if (val instanceof String) {
        if (String.class.isAssignableFrom(expected)) {
            return tryOptional(() -> expected.cast(val));
        }
        if (expected.isArray() && String.class.isAssignableFrom(expected.getComponentType())) {
            String v = (String) val;
            if (v.isEmpty()) {
                return Optional.empty();
            }
            if (!v.contains("_")) {
                return tryOptional(() -> expected.cast(new String[] { v }));
            }
            String[] x = v.split("_");
            if (x.length == 0) {
                return Optional.empty();
            }
            boolean ne = false;
            for (String s : x) {
                ne = ne || !s.isEmpty();
            }
            if (!ne) {
                return Optional.empty();
            }
            return tryOptional(() -> expected.cast(x));
        }
        if (List.class.isAssignableFrom(expected)
                && String.class.isAssignableFrom(expected.getTypeParameters()[0].getGenericDeclaration())) {
            String v = (String) val;
            if (v.isEmpty()) {
                return Optional.empty();
            }
            if (!v.contains("_")) {
                return tryOptional(() -> expected.cast(Collections.singletonList(v)));
            }
            String[] x = v.split("_");
            if (x.length == 0) {
                return Optional.empty();
            }
            boolean ne = false;
            for (String s : x) {
                ne = ne || !s.isEmpty();
            }
            if (!ne) {
                return Optional.empty();
            }
            return tryOptional(() -> expected.cast(Arrays.asList(x)));
        }
        Optional<T> opt = tryOptional(() -> convertPrimitive((String) val, expected));
        if (opt.isPresent()) {
            return opt;
        }
        opt = deserializers.entrySet().stream()
                .filter(e -> e.getKey().isSubtypeOf(expected) || e.getKey().getRawType().equals(expected))
                .map(Map.Entry::getValue).map(f -> tryOptional(() -> f.apply((String) val)))
                .flatMap(unmapOptional()).findAny().flatMap(o -> tryOptional(() -> expected.cast(o)));
        if (opt.isPresent()) {
            return opt;
        }
        try {
            // should theoretically match any string -> object conversions, such as deser

            // for now im filtering against method names as well just to avoid issues where
            // expected result is not obtained due to weird methods, might change in future
            Method method = Arrays.stream(expected.getDeclaredMethods())
                    .filter(m -> Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers()))
                    .filter(m -> Arrays.stream(m.getParameterTypes()).anyMatch(c -> c.equals(String.class)))
                    .filter(m -> m.getReturnType().equals(expected) || m.getReturnType().equals(Optional.class))
                    .filter(m -> STRING_TO_VAL_PATTERN.matcher(m.getName()).find()).findAny().get(); // error if no
            Object valout = method.invoke(null, (String) val);
            if (valout == null) {
                return Optional.empty();
            }
            if (expected.isInstance(valout)) {
                // Register a new deserializer once we confirm it works. Should prevent
                // extremely long parsing from happening multiple times.
                final MethodHandle mh = MethodHandles.publicLookup().unreflect(method);
                PlaceholderServiceImpl.get().registerTypeDeserializer(TypeToken.of(expected), str -> {
                    try {
                        return expected.cast(mh.invokeExact((String) val));
                    } catch (Throwable e1) {
                        throw new RuntimeException(e1);
                    }
                });
                return tryOptional(() -> expected.cast(valout));
            }
            if (valout instanceof Optional) {
                Optional<?> valopt = (Optional<?>) valout;
                if (!valopt.isPresent()) {
                    return Optional.empty();
                }
                Object v = valopt.get();
                if (expected.isInstance(v)) {
                    // Register a new deserializer once we confirm it works. Should prevent
                    // extremely long parsing from happening multiple times.
                    final MethodHandle mh = MethodHandles.publicLookup().unreflect(method);
                    PlaceholderServiceImpl.get().registerTypeDeserializer(TypeToken.of(expected), str -> {
                        try {
                            Optional<?> optx = (Optional<?>) mh.invokeExact((String) val);
                            return expected.cast(optx.get());
                        } catch (Throwable e1) {
                            throw new RuntimeException(e1);
                        }
                    });
                    return tryOptional(() -> expected.cast(v));
                } else {
                    return Optional.empty();
                }
            }
            return Optional.empty();
        } catch (Exception e) {
            // fires if no method found, if invoke throws, if something else goes wrong
            return Optional.empty();
        }
    }
    return TypeUtils.tryOptional(() -> expected.cast(val));
}

From source file:com.almende.eve.protocol.jsonrpc.JSONRpc.java

/**
 * Invoke a method on an object.//from www . j  a  v  a  2s  . c om
 * 
 * @param destination
 *            the destination
 * @param request
 *            A request in JSON-RPC format
 * @param requestParams
 *            Optional request parameters
 * @param auth
 *            the auth
 * @return the jSON response
 */
public static JSONResponse invoke(final Object destination, final JSONRequest request,
        final RequestParams requestParams, final Authorizor auth) {
    final JSONResponse resp = new JSONResponse(request.getId(), null);
    try {
        final CallTuple tuple = NamespaceUtil.get(destination, request.getMethod());

        final Object realDest = tuple.getDestination();
        final AnnotatedMethod annotatedMethod = tuple.getMethod();
        if (!isAvailable(annotatedMethod, realDest, requestParams, auth)) {
            throw new JSONRPCException(JSONRPCException.CODE.METHOD_NOT_FOUND, "Method '" + request.getMethod()
                    + "' not found. The method does not exist or you are not authorized.");
        }

        final MethodHandle methodHandle = annotatedMethod.getMethodHandle();
        final Method method = annotatedMethod.getActualMethod();

        Object result;
        if (Defines.HASMETHODHANDLES) {
            final Object[] params = castParams(realDest, request.getParams(), annotatedMethod.getParams(),
                    requestParams);
            result = methodHandle.invokeExact(params);
        } else {
            final Object[] params = castParams(request.getParams(), annotatedMethod.getParams(), requestParams);
            result = method.invoke(realDest, params);
        }
        if (result == null) {
            result = JOM.createNullNode();
        }
        resp.setResult(result);
    } catch (final JSONRPCException err) {
        resp.setError(err);
    } catch (final Throwable err) {
        final Throwable cause = err.getCause();
        if (cause instanceof JSONRPCException) {
            resp.setError((JSONRPCException) cause);
        } else {
            if (err instanceof InvocationTargetException && cause != null) {
                LOG.log(Level.WARNING,
                        "Exception raised, returning its cause as JSONRPCException. Request:" + request, cause);

                final JSONRPCException jsonError = new JSONRPCException(JSONRPCException.CODE.INTERNAL_ERROR,
                        getMessage(cause), cause);
                jsonError.setData(cause);
                resp.setError(jsonError);
            } else {
                LOG.log(Level.WARNING, "Exception raised, returning it as JSONRPCException. Request:" + request,
                        err);

                final JSONRPCException jsonError = new JSONRPCException(JSONRPCException.CODE.INTERNAL_ERROR,
                        getMessage(err), err);
                jsonError.setData(err);
                resp.setError(jsonError);
            }
        }
    }
    if (resp.getId() == null || resp.getId().isNull()) {
        return null;
    } else {
        return resp;
    }
}

From source file:com.almende.eve.rpc.jsonrpc.JSONRPC.java

/**
 * Invoke a method on an object.//www. j  a  v a2 s.  c  o m
 * 
 * @param destination
 *            the destination
 * @param request
 *            A request in JSON-RPC format
 * @param requestParams
 *            Optional request parameters
 * @param auth
 *            the auth
 * @return the jSON response
 */
public static JSONResponse invoke(final Object destination, final JSONRequest request,
        final RequestParams requestParams, final JSONAuthorizor auth) {
    final JSONResponse resp = new JSONResponse(request.getId(), null);
    try {
        final CallTuple tuple = NamespaceUtil.get(destination, request.getMethod());

        final Object realDest = tuple.getDestination();
        final AnnotatedMethod annotatedMethod = tuple.getMethod();
        if (!isAvailable(annotatedMethod, realDest, requestParams, auth)) {
            throw new JSONRPCException(JSONRPCException.CODE.METHOD_NOT_FOUND, "Method '" + request.getMethod()
                    + "' not found. The method does not exist or you are not authorized.");
        }

        final MethodHandle methodHandle = annotatedMethod.getMethodHandle();
        final Method method = annotatedMethod.getActualMethod();

        Object result;
        if (USEMETHODHANDLE) {
            final Object[] params = castParams(realDest, request.getParams(), annotatedMethod.getParams(),
                    requestParams);
            result = methodHandle.invokeExact(params);
        } else {
            final Object[] params = castParams(request.getParams(), annotatedMethod.getParams(), requestParams);
            result = method.invoke(realDest, params);
        }
        if (result == null) {
            result = JOM.createNullNode();
        }
        resp.setResult(result);
    } catch (final JSONRPCException err) {
        resp.setError(err);
    } catch (final Throwable err) {
        final Throwable cause = err.getCause();
        if (cause instanceof JSONRPCException) {
            resp.setError((JSONRPCException) cause);
        } else {
            if (err instanceof InvocationTargetException && cause != null) {
                LOG.log(Level.WARNING,
                        "Exception raised, returning its cause as JSONRPCException. Request:" + request, cause);

                final JSONRPCException jsonError = new JSONRPCException(JSONRPCException.CODE.INTERNAL_ERROR,
                        getMessage(cause), cause);
                jsonError.setData(cause);
                resp.setError(jsonError);
            } else {
                LOG.log(Level.WARNING, "Exception raised, returning it as JSONRPCException. Request:" + request,
                        err);

                final JSONRPCException jsonError = new JSONRPCException(JSONRPCException.CODE.INTERNAL_ERROR,
                        getMessage(err), err);
                jsonError.setData(err);
                resp.setError(jsonError);
            }
        }
    }
    return resp;
}