All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sdklite.rpc.RpcServiceProxy Maven / Gradle / Ivy

package com.sdklite.rpc;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import com.sdklite.rpc.annotation.DnsResolution;
import com.sdklite.rpc.annotation.Interception;
import com.sdklite.rpc.annotation.Timeout;

final class RpcServiceProxy implements InvocationHandler {

    private static final Set OBJECT_METHODS = Collections.unmodifiableSet(new HashSet(Arrays.asList(Object.class.getMethods())));

    final RpcServiceFactory factory;

    final Class service;

    final String baseUrl;

    final Set methods;

    public RpcServiceProxy(final RpcServiceFactory factory, final Class service, final String baseUrl) {
        this.factory = factory;
        this.service = service;
        this.baseUrl = baseUrl;
        this.methods = Collections.unmodifiableSet(new HashSet(Arrays.asList(service.getMethods())));
    }

    @Override
    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
        final String name = method.getName();
        final Class[] parameterTypes = method.getParameterTypes(); 

        if (this.methods.contains(method)) {
            return execute(method, args);
        }

        if (OBJECT_METHODS.contains(method)) {
            if ("equals".equals(name) && Arrays.equals(new Class[] { Object.class }, parameterTypes)) {
                return this.equals(args[0]);
            }

            if ("hashCode".equals(name) && parameterTypes.length == 0) {
                return this.hashCode();
            }

            if ("toString".equals(name) && parameterTypes.length == 0) {
                return this.toString();
            }
        }

        throw new NoSuchMethodException(method.toString());
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private Object execute(final Method method, final Object... args) throws RpcException {
        try {
            final RpcClient.Builder clientBuilder = getRpcClient(method, args).newBuilder();

            // Set RPC timeout
            final Timeout timeout = method.isAnnotationPresent(Timeout.class)
                    ? method.getAnnotation(Timeout.class)
                    : this.service.getAnnotation(Timeout.class);
            if (null != timeout) {
                clientBuilder.setConnectTimeout(timeout.connectTimeout());
                clientBuilder.setReadTimeout(timeout.readTimeout());
                clientBuilder.setWriteTimeout(timeout.writeTimeout());
            }

            // Set RPC DNS resolver
            final DnsResolution dns = method.isAnnotationPresent(DnsResolution.class)
                    ? method.getAnnotation(DnsResolution.class)
                    : this.service.getAnnotation(DnsResolution.class);
            if (null != dns) {
                clientBuilder.setDnsResolver(dns.value().newInstance());
            }

            // Set RPC interceptors
            final Interception interception = method.isAnnotationPresent(Interception.class)
                    ? method.getAnnotation(Interception.class)
                    : this.service.getAnnotation(Interception.class);
            if (null != interception) {
                for (final Class clazz : interception.value()) {
                    if (null != clazz) {
                        clientBuilder.addInterceptor(clazz.newInstance());
                    }
                }
            }

            final RpcClient client = clientBuilder.build();
            final RpcRequest request = client.newRequestBuilder()
                    .setUrl(this.baseUrl)
                    .setService(this.service, method, args)
                    .build();
            final Rpc rpc = client.newRpc(request);
            final Object result;

            if (args.length > 0 && args[args.length - 1] instanceof RpcService.Callback) {
                final RpcService.Callback callback = (RpcService.Callback) args[args.length - 1];

                result = rpc.enqueue(new Rpc.Callback() {
                    @Override
                    public void onSuccess(final RpcResponse response) {
                        try {
                            callback.onSuccess(response.getContent());
                        } catch (final IOException e) {
                            callback.onFailure(new RpcException(e));
                        }
                    }

                    @Override
                    public void onFailure(final RpcRequest request, final RpcException e) {
                        callback.onFailure(e);
                    }
                });
            } else {
                result = rpc.execute().getContent();
            }

            final Class retType = method.getReturnType();
            if (void.class.equals(retType) || Void.class.equals(retType)) {
                return null;
            }

            return result;
        } catch (final RpcException e) {
            throw e;
        } catch (final Throwable e) {
            throw new RpcException(e);
        }
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private RpcClient getRpcClient(final Method method, final Object... args) throws Throwable {
        final URI uri = new URI(this.baseUrl);
        final RpcClient client = this.factory.getRpcClient(uri.getScheme());
        if (!method.isAnnotationPresent(Interception.class)) {
            return client;
        }

        final Interception interception = method.getAnnotation(Interception.class);
        final Class[] classesOfInterceptor = interception.value();
        final RpcClient.Builder builder = client.newBuilder();

        for (final Class clazz : classesOfInterceptor) {
            builder.addInterceptor(clazz.newInstance());
        }

        return builder.build();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy