/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.util; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * <code>Multicaster</code> is a utility that can call a given method on a collection of objects that implement one or more common * interfaces. The create method returns a proxy that can be cast to any of the the interfaces passed and be used like a single * object. */ // @ThreadSafe public final class Multicaster { /** Do not instanciate. */ private Multicaster() { // no-op } public static Object create(Class<?> theInterface, Collection<?> objects) { return create(new Class[] {theInterface}, objects); } public static Object create(Class<?> theInterface, Collection<?> objects, InvokeListener listener) { return create(new Class[] {theInterface}, objects, listener); } public static Object create(Class<?>[] interfaces, Collection<?> objects) { return create(interfaces, objects, null); } public static Object create(Class<?>[] interfaces, Collection<?> objects, InvokeListener listener) { return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new CastingHandler(objects, listener)); } private static class CastingHandler implements InvocationHandler { private final Collection<?> objects; private final InvokeListener listener; public CastingHandler(Collection<?> objects) { this(objects, null); } public CastingHandler(Collection<?> objects, InvokeListener listener) { this.objects = objects; this.listener = listener; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { List<Object> results = new ArrayList<Object>(); Object item = null; Object result; for (Iterator<?> iterator = objects.iterator(); iterator.hasNext();) { try { item = iterator.next(); result = method.invoke(item, args); if (listener != null) { listener.afterExecute(item, method, args); } if (result != null) { results.add(result); } } catch (Throwable t) { // TODO MULE-863: What should we do if null? if (listener != null) { t = listener.onException(item, method, args, t); if (t != null) { throw t; } } } } return results; } } public static interface InvokeListener { void afterExecute(Object object, Method method, Object[] args); Throwable onException(Object object, Method method, Object[] args, Throwable t); } }