View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.util;
8   
9   import java.lang.reflect.InvocationHandler;
10  import java.lang.reflect.Method;
11  import java.lang.reflect.Proxy;
12  import java.util.ArrayList;
13  import java.util.Collection;
14  import java.util.Iterator;
15  import java.util.List;
16  
17  /**
18   * <code>Multicaster</code> is a utility that can call a given method on a
19   * collection of objects that implement one or more common interfaces. The create
20   * method returns a proxy that can be cast to any of the the interfaces passed and be
21   * used like a single object.
22   */
23  // @ThreadSafe
24  public final class Multicaster
25  {
26      /** Do not instanciate. */
27      private Multicaster ()
28      {
29          // no-op
30      }
31  
32      public static Object create(Class theInterface, Collection objects)
33      {
34          return create(new Class[]{theInterface}, objects);
35      }
36  
37      public static Object create(Class theInterface, Collection objects, InvokeListener listener)
38      {
39          return create(new Class[]{theInterface}, objects, listener);
40      }
41  
42      public static Object create(Class[] interfaces, Collection objects)
43      {
44          return create(interfaces, objects, null);
45      }
46  
47      public static Object create(Class[] interfaces, Collection objects, InvokeListener listener)
48      {
49          return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces,
50              new CastingHandler(objects, listener));
51      }
52  
53      private static class CastingHandler implements InvocationHandler
54      {
55          private final Collection objects;
56          private final InvokeListener listener;
57  
58          public CastingHandler(Collection objects)
59          {
60              this(objects, null);
61          }
62  
63          public CastingHandler(Collection objects, InvokeListener listener)
64          {
65              this.objects = objects;
66              this.listener = listener;
67          }
68  
69          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
70          {
71              List results = new ArrayList();
72              Object item = null;
73              Object result;
74  
75              for (Iterator iterator = objects.iterator(); iterator.hasNext();)
76              {
77                  try
78                  {
79                      item = iterator.next();
80                      result = method.invoke(item, args);
81                      if (listener != null)
82                      {
83                          listener.afterExecute(item, method, args);
84                      }
85                      if (result != null)
86                      {
87                          results.add(result);
88                      }
89                  }
90                  catch (Throwable t)
91                  {
92                      // TODO MULE-863: What should we do if null?
93                      if (listener != null)
94                      {
95                          t = listener.onException(item, method, args, t);
96                          if (t != null)
97                          {
98                              throw t;
99                          }
100                     }
101                 }
102             }
103             return results;
104         }
105     }
106 
107     public static interface InvokeListener
108     {
109         void afterExecute(Object object, Method method, Object[] args);
110 
111         Throwable onException(Object object, Method method, Object[] args, Throwable t);
112     }
113 
114 }