View Javadoc

1   /*
2    * $Id: OutboundRouterCollection.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.routing.outbound;
12  
13  import org.mule.management.stats.RouterStatistics;
14  import org.mule.routing.AbstractRouterCollection;
15  import org.mule.transaction.TransactionCallback;
16  import org.mule.transaction.TransactionTemplate;
17  import org.mule.umo.MessagingException;
18  import org.mule.umo.UMOMessage;
19  import org.mule.umo.UMOSession;
20  import org.mule.umo.endpoint.UMOEndpoint;
21  import org.mule.umo.routing.RoutingException;
22  import org.mule.umo.routing.UMOOutboundRouter;
23  import org.mule.umo.routing.UMOOutboundRouterCollection;
24  
25  import java.util.ArrayList;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  /**
30   * <code>OutboundRouterCollection</code> is a container of routers. An
31   * OutboundRouterCollection must have atleast one router. By default the first matching
32   * router is used to route an event though it is possible to match on all routers
33   * meaning that the message will get sent over all matching routers.
34   */
35  
36  public class OutboundRouterCollection extends AbstractRouterCollection implements UMOOutboundRouterCollection
37  {
38  
39      public OutboundRouterCollection()
40      {
41          super(RouterStatistics.TYPE_OUTBOUND);
42      }
43  
44      public UMOMessage route(final UMOMessage message, final UMOSession session, final boolean synchronous)
45          throws MessagingException
46      {
47  
48          UMOMessage result;
49          boolean matchfound = false;
50  
51          for (Iterator iterator = getRouters().iterator(); iterator.hasNext();)
52          {
53              UMOOutboundRouter umoOutboundRouter = (UMOOutboundRouter) iterator.next();
54              if (umoOutboundRouter.isMatch(message))
55              {
56                  matchfound = true;
57                  // Manage outbound only transactions here
58                  final UMOOutboundRouter router = umoOutboundRouter;
59                  TransactionTemplate tt = new TransactionTemplate(umoOutboundRouter.getTransactionConfig(),
60                      session.getComponent().getDescriptor().getExceptionListener());
61  
62                  TransactionCallback cb = new TransactionCallback()
63                  {
64                      public Object doInTransaction() throws Exception
65                      {
66                          return router.route(message, session, synchronous);
67                      }
68                  };
69                  try
70                  {
71                      result = (UMOMessage) tt.execute(cb);
72                  }
73                  catch (Exception e)
74                  {
75                      throw new RoutingException(message, null, e);
76                  }
77  
78                  if (!isMatchAll())
79                  {
80                      return result;
81                  }
82              }
83          }
84  
85          if (!matchfound && getCatchAllStrategy() != null)
86          {
87              if (logger.isDebugEnabled())
88              {
89                  logger.debug("Message did not match any routers on: "
90                               + session.getComponent().getDescriptor().getName()
91                               + " invoking catch all strategy");
92              }
93              return catchAll(message, session, synchronous);
94          }
95          else if (!matchfound)
96          {
97              logger.warn("Message did not match any routers on: "
98                          + session.getComponent().getDescriptor().getName()
99                          + " and there is no catch all strategy configured on this router.  Disposing message.");
100         }
101         return message;
102     }
103 
104     /**
105      * A helper method for finding out which endpoints a message would be routed to
106      * without actually routing the the message
107      * 
108      * @param message the message to retrieve endpoints for
109      * @return an array of UMOEndpoint objects or an empty array
110      * @throws RoutingException
111      */
112     public UMOEndpoint[] getEndpointsForMessage(UMOMessage message) throws MessagingException
113     {
114         List endpoints = new ArrayList();
115         for (Iterator iterator = getRouters().iterator(); iterator.hasNext();)
116         {
117             UMOOutboundRouter umoOutboundRouter = (UMOOutboundRouter) iterator.next();
118             if (umoOutboundRouter.isMatch(message))
119             {
120                 endpoints.addAll(umoOutboundRouter.getEndpoints());
121                 if (!isMatchAll())
122                 {
123                     break;
124                 }
125             }
126         }
127 
128         UMOEndpoint[] result = new UMOEndpoint[endpoints.size()];
129         return (UMOEndpoint[]) endpoints.toArray(result);
130     }
131 
132     protected UMOMessage catchAll(UMOMessage message, UMOSession session, boolean synchronous)
133         throws RoutingException
134     {
135         if (getStatistics().isEnabled())
136         {
137             getStatistics().incrementCaughtMessage();
138         }
139 
140         return getCatchAllStrategy().catchMessage(message, session, synchronous);
141     }
142 
143     public boolean hasEndpoints()
144     {
145         for (Iterator iterator = routers.iterator(); iterator.hasNext();)
146         {
147             UMOOutboundRouter router = (UMOOutboundRouter) iterator.next();
148             if (router.getEndpoints().size() > 0 || router.isDynamicEndpoints())
149             {
150                 return true;
151             }
152         }
153         return false;
154     }
155 
156 }