View Javadoc

1   /*
2    * $Id: SxcFilteringOutboundRouter.java 12364 2008-07-16 16:30:30Z 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.module.sxc;
12  
13  import org.mule.RequestContext;
14  import org.mule.api.MuleMessage;
15  import org.mule.api.routing.RoutingException;
16  import org.mule.api.routing.filter.Filter;
17  import org.mule.api.transformer.TransformerException;
18  import org.mule.module.xml.stax.ReversibleXMLStreamReader;
19  import org.mule.module.xml.transformer.XmlToXMLStreamReader;
20  import org.mule.routing.filters.logic.AndFilter;
21  import org.mule.routing.filters.logic.NotFilter;
22  import org.mule.routing.filters.logic.OrFilter;
23  import org.mule.routing.outbound.FilteringOutboundRouter;
24  
25  import com.envoisolutions.sxc.xpath.XPathBuilder;
26  import com.envoisolutions.sxc.xpath.XPathEvaluator;
27  
28  import java.util.Iterator;
29  import java.util.Map;
30  
31  /**
32   * <code>FilteringRouter</code> is a router that accepts events based on a filter
33   * set.
34   */
35  
36  public class SxcFilteringOutboundRouter extends FilteringOutboundRouter
37  {
38      private final static ThreadLocal<MuleMessage> messages = new ThreadLocal<MuleMessage>();
39      private final static XmlToXMLStreamReader transformer = new XmlToXMLStreamReader();
40  
41      static
42      {
43          transformer.setReversible(true);
44      }
45  
46      private Map<String, String> namespaces;
47      private XPathEvaluator evaluator;
48  
49      private XPathBuilder builder;
50  
51      @Override
52      public void setFilter(Filter filter)
53      {
54          super.setFilter(filter);
55      }
56  
57      protected void addEventHandlers(XPathBuilder builder, Filter filter)
58      {
59          if (filter instanceof SxcFilter)
60          {
61              SxcFilter sxcFilter = ((SxcFilter) filter);
62              sxcFilter.addEventHandler(this, builder);
63          }
64          else if (filter instanceof AndFilter)
65          {
66              AndFilter f = (AndFilter) filter;
67  
68              for (Iterator<?> itr = f.getFilters().iterator(); itr.hasNext();)
69              {
70                  addEventHandlers(builder, (Filter) itr.next());
71              }
72          }
73          else if (filter instanceof OrFilter)
74          {
75              OrFilter f = (OrFilter) filter;
76  
77              for (Iterator<?> itr = f.getFilters().iterator(); itr.hasNext();)
78              {
79                  addEventHandlers(builder, (Filter) itr.next());
80              }
81          }
82          else if (filter instanceof NotFilter)
83          {
84              NotFilter f = (NotFilter) filter;
85  
86              addEventHandlers(builder, f.getFilter());
87          }
88          else
89          {
90              logger.warn("Filter type " + filter.getClass().toString()
91                             + " is not recognized by the SXC router. If it contains child "
92                             + "SXC filters it will not work correctly.");
93          }
94      }
95  
96      protected void initialize() throws Exception
97      {
98          if (evaluator == null)
99          {
100             doInitialize();
101         }
102     }
103 
104     private synchronized void doInitialize()
105     {
106         if (evaluator == null)
107         {
108             builder = new XPathBuilder();
109 
110             addEventHandlers(builder, getFilter());
111 
112             evaluator = builder.compile();
113         }
114     }
115 
116     @Override
117     public boolean isMatch(MuleMessage message) throws RoutingException
118     {
119 
120         ReversibleXMLStreamReader reader = null;
121         try
122         {
123             initialize();
124             messages.set(message);
125 
126             reader = getXMLStreamReader(message);
127             reader.setTracking(true);
128             evaluator.evaluate(reader);
129         }
130         catch (StopProcessingException e)
131         {
132             // stop processing
133         }
134         catch (Exception e)
135         {
136             throw new RoutingException(message, RequestContext.getEvent().getEndpoint(), e);
137         }
138         finally
139         {
140             messages.set(null);
141 
142             if (reader != null)
143             {
144                 reader.setTracking(false);
145                 reader.reset();
146             }
147         }
148 
149         try
150         {
151             return testMatch(message);
152         }
153         catch (UndefinedMatchException m)
154         {
155             return false;
156         }
157     }
158 
159     public boolean testMatch(MuleMessage message) throws RoutingException
160     {
161         return super.isMatch(message);
162     }
163 
164     /**
165      * Gets an XMLStreamReader for this message.
166      * 
167      * @param message
168      * @return
169      * @throws TransformerException
170      */
171     protected ReversibleXMLStreamReader getXMLStreamReader(MuleMessage message) throws TransformerException
172     {
173          ReversibleXMLStreamReader r = (ReversibleXMLStreamReader) transformer.transform(message);
174          
175          if (r != message.getPayload())
176          {
177              message.setPayload(r);
178          }
179          return r;
180     }
181 
182     public Map<String, String> getNamespaces()
183     {
184         return namespaces;
185     }
186 
187     public void setNamespaces(Map<String, String> namespaces)
188     {
189         this.namespaces = namespaces;
190     }
191 
192     public static MuleMessage getCurrentMessage()
193     {
194         return messages.get();
195     }
196 }