View Javadoc

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