/* * Copyright 2014 Red Hat, Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package io.vertx.serviceproxy; import io.vertx.core.Vertx; import io.vertx.core.eventbus.DeliveryOptions; import io.vertx.core.eventbus.MessageConsumer; import io.vertx.core.json.JsonObject; import java.lang.reflect.Constructor; import java.util.Objects; /** * @author <a href="http://tfox.org">Tim Fox</a> */ public class ProxyHelper { public static <T> T createProxy(Class<T> clazz, Vertx vertx, String address) { return createProxy(clazz, vertx, address, null); } public static <T> T createProxy(Class<T> clazz, Vertx vertx, String address, DeliveryOptions options) { String proxyClassName = clazz.getName() + "VertxEBProxy"; Class<?> proxyClass = loadClass(proxyClassName, clazz); Constructor constructor; Object instance; if (options == null) { constructor = getConstructor(proxyClass, Vertx.class, String.class); instance = createInstance(constructor, vertx, address); } else { constructor = getConstructor(proxyClass, Vertx.class, String.class, DeliveryOptions.class); instance = createInstance(constructor, vertx, address, options); } return (T) instance; } public static final long DEFAULT_CONNECTION_TIMEOUT = 5 * 60; // 5 minutes /** * Registers a service on the event bus. * * @param clazz the service class (interface) * @param vertx the vert.x instance * @param service the service object * @param address the address on which the service is published * @param <T> the type of the service interface * @return the consumer used to unregister the service */ public static <T> MessageConsumer<JsonObject> registerService(Class<T> clazz, Vertx vertx, T service, String address) { // No timeout - used for top level services return registerService(clazz, vertx, service, address, DEFAULT_CONNECTION_TIMEOUT); } public static <T> MessageConsumer<JsonObject> registerService(Class<T> clazz, Vertx vertx, T service, String address, long timeoutSeconds) { // No timeout - used for top level services return registerService(clazz, vertx, service, address, true, timeoutSeconds); } public static <T> MessageConsumer<JsonObject> registerService(Class<T> clazz, Vertx vertx, T service, String address, boolean topLevel, long timeoutSeconds) { String handlerClassName = clazz.getName() + "VertxProxyHandler"; Class<?> handlerClass = loadClass(handlerClassName, clazz); Constructor constructor = getConstructor(handlerClass, Vertx.class, clazz, boolean.class, long.class); Object instance = createInstance(constructor, vertx, service, topLevel, timeoutSeconds); ProxyHandler handler = (ProxyHandler) instance; return handler.registerHandler(address); } /** * Unregisters a published service. * * @param consumer the consumer returned by {@link #registerService(Class, Vertx, Object, String)}. */ public static void unregisterService(MessageConsumer<JsonObject> consumer) { Objects.requireNonNull(consumer); if (consumer instanceof ProxyHandler) { ((ProxyHandler) consumer).close(); } else { // Fall back to plain unregister. consumer.unregister(); } } private static Class<?> loadClass(String name, Class origin) { try { return origin.getClassLoader().loadClass(name); } catch (ClassNotFoundException e) { throw new IllegalStateException("Cannot find proxyClass: " + name, e); } } private static Constructor getConstructor(Class<?> clazz, Class<?>... types) { try { return clazz.getDeclaredConstructor(types); } catch (NoSuchMethodException e) { throw new IllegalStateException("Cannot find constructor on: " + clazz.getName(), e); } } private static Object createInstance(Constructor constructor, Object... args) { try { return constructor.newInstance(args); } catch (Exception e) { throw new IllegalStateException("Failed to call constructor on", e); } } }