Coverage Report - org.mule.module.xml.filters.JaxenFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
JaxenFilter
0%
0/107
0%
0/58
0
 
 1  
 /*
 2  
  * $Id: JaxenFilter.java 19191 2010-08-25 21:05:23Z tcarlson $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.xml.filters;
 12  
 
 13  
 import static org.mule.util.ClassUtils.equal;
 14  
 import static org.mule.util.ClassUtils.hash;
 15  
 
 16  
 import org.mule.api.MuleContext;
 17  
 import org.mule.api.MuleMessage;
 18  
 import org.mule.api.context.MuleContextAware;
 19  
 import org.mule.api.expression.ExpressionRuntimeException;
 20  
 import org.mule.api.registry.RegistrationException;
 21  
 import org.mule.api.routing.filter.Filter;
 22  
 import org.mule.config.i18n.CoreMessages;
 23  
 import org.mule.module.xml.util.NamespaceManager;
 24  
 import org.mule.module.xml.util.XMLUtils;
 25  
 
 26  
 import java.io.InputStream;
 27  
 import java.util.HashMap;
 28  
 import java.util.Iterator;
 29  
 import java.util.Map;
 30  
 
 31  
 import javax.xml.transform.dom.DOMSource;
 32  
 
 33  
 import org.apache.commons.jxpath.AbstractFactory;
 34  
 import org.apache.commons.logging.Log;
 35  
 import org.apache.commons.logging.LogFactory;
 36  
 import org.dom4j.Document;
 37  
 import org.jaxen.BaseXPath;
 38  
 import org.jaxen.JaxenException;
 39  
 import org.jaxen.dom.DOMXPath;
 40  
 import org.jaxen.dom4j.Dom4jXPath;
 41  
 import org.jaxen.javabean.JavaBeanXPath;
 42  
 import org.mule.transformer.types.DataTypeFactory;
 43  
 
 44  
 /**
 45  
  * <code>JaxenFilter</code> evaluates an XPath expression against an XML document
 46  
  * using Jaxen.
 47  
  */
 48  
 public class JaxenFilter implements Filter, MuleContextAware
 49  
 {
 50  0
     protected transient Log logger = LogFactory.getLog(getClass());
 51  
 
 52  
     private String pattern;
 53  
     private String expectedValue;
 54  0
     private Map namespaces = null;
 55  0
     private Map contextProperties = null;
 56  
     private AbstractFactory factory;
 57  
 
 58  
     private MuleContext muleContext;
 59  
     private NamespaceManager namespaceManager;
 60  
 
 61  
     public JaxenFilter()
 62  
     {
 63  0
         super();
 64  0
     }
 65  
 
 66  
     public JaxenFilter(String pattern)
 67  0
     {
 68  0
         this.pattern = pattern;
 69  0
     }
 70  
 
 71  
     public JaxenFilter(String pattern, String expectedValue)
 72  0
     {
 73  0
         this.pattern = pattern;
 74  0
         this.expectedValue = expectedValue;
 75  0
     }
 76  
 
 77  
 
 78  
     public void setMuleContext(MuleContext context)
 79  
     {
 80  0
         this.muleContext = context;
 81  
         try
 82  
         {
 83  0
             namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
 84  
         }
 85  0
         catch (RegistrationException e)
 86  
         {
 87  0
             throw new ExpressionRuntimeException(CoreMessages.failedToLoad("NamespaceManager"), e);
 88  0
         }
 89  0
         if(namespaceManager!=null)
 90  
         {
 91  0
             if(namespaces == null)
 92  
             {
 93  0
                 namespaces = new HashMap(namespaceManager.getNamespaces());
 94  
             }
 95  
             else
 96  
             {
 97  0
                 namespaces.putAll(namespaceManager.getNamespaces());
 98  
             }
 99  
         }
 100  0
     }
 101  
 
 102  
     public boolean accept(MuleMessage obj)
 103  
     {
 104  0
         Object payload = obj.getPayload();
 105  
         
 106  
         try 
 107  
         {
 108  
             // Ensure that we have an object we can run an XPath on
 109  0
             if (payload instanceof DOMSource)
 110  
             {
 111  0
                 accept(((DOMSource) payload).getNode());
 112  
             }
 113  0
             else if (payload instanceof byte[] 
 114  
                      || payload instanceof InputStream 
 115  
                      || payload instanceof String)
 116  
             {
 117  
                 try
 118  
                 {
 119  0
                     return accept(obj.getPayload(DataTypeFactory.create(org.w3c.dom.Document.class)));
 120  
                 }
 121  0
                 catch (Exception e)
 122  
                 {
 123  0
                     logger.warn("JaxenPath filter rejected message because it could not convert from " 
 124  
                             + payload.getClass() 
 125  
                             + " to Source: "+ e.getMessage(), e);
 126  0
                     return false;
 127  
                 }
 128  
             }
 129  
         
 130  0
             return accept(payload);
 131  
         }
 132  0
         catch (JaxenException e) 
 133  
         {
 134  0
             logger.warn("JaxenPath filter rejected message because it could not build/evaluate the XPath expression.", e);
 135  0
             return false;
 136  
         }
 137  
     }
 138  
 
 139  
     private boolean accept(Object obj) throws JaxenException
 140  
     {
 141  0
         if (obj == null)
 142  
         {
 143  0
             logger.warn("Applying JaxenFilter to null object.");
 144  0
             return false;
 145  
         }
 146  0
         if (pattern == null)
 147  
         {
 148  0
             logger.warn("Expression for JaxenFilter is not set.");
 149  0
             return false;
 150  
         }
 151  0
         if (expectedValue == null)
 152  
         {
 153  
             // Handle the special case where the expected value really is null.
 154  0
             if (pattern.endsWith("= null") || pattern.endsWith("=null"))
 155  
             {
 156  0
                 expectedValue = "null";
 157  0
                 pattern = pattern.substring(0, pattern.lastIndexOf("="));
 158  
             }
 159  
             else
 160  
             {
 161  0
                 if (logger.isInfoEnabled())
 162  
                 {
 163  0
                     logger.info("Expected value for JaxenFilter is not set, using 'true' by default");
 164  
                 }
 165  0
                 expectedValue = Boolean.TRUE.toString();
 166  
             }
 167  
         }
 168  
 
 169  0
         Object xpathResult = null;
 170  0
         boolean accept = false;
 171  
 
 172  
         Document dom4jDoc;
 173  
         try
 174  
         {
 175  0
             dom4jDoc = XMLUtils.toDocument(obj, muleContext);
 176  
         }
 177  0
         catch (Exception e)
 178  
         {
 179  0
             throw new JaxenException(e);
 180  0
         }
 181  
         
 182  
         // Payload is a DOM Document
 183  0
         if (dom4jDoc != null)
 184  
         {
 185  0
             xpathResult = getDom4jXPath().stringValueOf(dom4jDoc);
 186  
         }
 187  
         // Payload is a W3C Document
 188  0
         else if (obj instanceof DOMSource)
 189  
         {
 190  0
             xpathResult = getDOMXPath().stringValueOf(obj);
 191  
         }
 192  
         // Payload is a W3C Document
 193  0
         else if (obj instanceof org.w3c.dom.Document)
 194  
         {
 195  0
             xpathResult = getDOMXPath().stringValueOf(obj);
 196  
         }
 197  
         // Payload is a Java object
 198  
         else
 199  
         {
 200  0
             if (logger.isDebugEnabled())
 201  
             {
 202  0
                 logger.debug("Passing object of type " + obj.getClass().getName() + " to JaxenContext");
 203  
             }
 204  0
             xpathResult = getJavaBeanXPath().stringValueOf(obj);
 205  
         }
 206  
 
 207  0
         if (logger.isDebugEnabled())
 208  
         {
 209  0
             logger.debug("JaxenFilter Expression result = '" + xpathResult + "' -  Expected value = '"
 210  
                     + expectedValue + "'");
 211  
         }
 212  
         // Compare the XPath result with the expected result.
 213  0
         if (xpathResult != null)
 214  
         {
 215  0
             accept = xpathResult.toString().equals(expectedValue);
 216  
         }
 217  
         else
 218  
         {
 219  
             // A null result was actually expected.
 220  0
             if (expectedValue.equals("null"))
 221  
             {
 222  0
                 accept = true;
 223  
             }
 224  
             // A null result was not expected, something probably went wrong.
 225  
             else
 226  
             {
 227  0
                 logger.warn("JaxenFilter expression evaluates to null: " + pattern);
 228  
             }
 229  
         }
 230  
 
 231  0
         if (logger.isDebugEnabled())
 232  
         {
 233  0
             logger.debug("JaxenFilter accept object  : " + accept);
 234  
         }
 235  
 
 236  0
         return accept;
 237  
     }
 238  
 
 239  
     protected DOMXPath getDOMXPath() throws JaxenException
 240  
     {
 241  0
         DOMXPath xpath = new DOMXPath(pattern);
 242  0
         setupNamespaces(xpath);
 243  0
         return xpath;
 244  
     }
 245  
 
 246  
     protected Dom4jXPath getDom4jXPath() throws JaxenException
 247  
     {
 248  0
         Dom4jXPath xpath = new Dom4jXPath(pattern);
 249  0
         setupNamespaces(xpath);
 250  0
         return xpath;
 251  
     }
 252  
     
 253  
     protected JavaBeanXPath getJavaBeanXPath() throws JaxenException
 254  
     {
 255  0
         JavaBeanXPath xpath = new JavaBeanXPath(pattern);
 256  0
         setupNamespaces(xpath);
 257  0
         return xpath;
 258  
     }
 259  
 
 260  
     private void setupNamespaces(BaseXPath xpath) throws JaxenException
 261  
     {
 262  0
         if (namespaces != null) 
 263  
         {
 264  0
             for (Iterator itr = namespaces.entrySet().iterator(); itr.hasNext();)
 265  
             {
 266  0
                 Map.Entry entry = (Map.Entry) itr.next();
 267  
                 
 268  0
                 xpath.addNamespace((String) entry.getKey(), (String) entry.getValue());
 269  0
             }
 270  
         }
 271  0
     }
 272  
 
 273  
     /** @return XPath expression */
 274  
     public String getPattern()
 275  
     {
 276  0
         return pattern;
 277  
     }
 278  
 
 279  
     /** @param pattern The XPath expression */
 280  
     public void setPattern(String pattern)
 281  
     {
 282  0
         this.pattern = pattern;
 283  0
     }
 284  
 
 285  
     /** @return The expected result value of the XPath expression */
 286  
     public String getExpectedValue()
 287  
     {
 288  0
         return expectedValue;
 289  
     }
 290  
 
 291  
     /** Sets the expected result value of the XPath expression */
 292  
     public void setExpectedValue(String expectedValue)
 293  
     {
 294  0
         this.expectedValue = expectedValue;
 295  0
     }
 296  
 
 297  
     public Map getNamespaces()
 298  
     {
 299  0
         return namespaces;
 300  
     }
 301  
 
 302  
     public void setNamespaces(Map namespaces)
 303  
     {
 304  0
         this.namespaces = namespaces;
 305  0
     }
 306  
 
 307  
     public Map getContextProperties()
 308  
     {
 309  0
         return contextProperties;
 310  
     }
 311  
 
 312  
     public void setContextProperties(Map contextProperties)
 313  
     {
 314  0
         this.contextProperties = contextProperties;
 315  0
     }
 316  
 
 317  
     public AbstractFactory getFactory()
 318  
     {
 319  0
         return factory;
 320  
     }
 321  
 
 322  
     public void setFactory(AbstractFactory factory)
 323  
     {
 324  0
         this.factory = factory;
 325  0
     }
 326  
     public boolean equals(Object obj)
 327  
     {
 328  0
         if (this == obj) return true;
 329  0
         if (obj == null || getClass() != obj.getClass()) return false;
 330  
 
 331  0
         final JaxenFilter other = (JaxenFilter) obj;
 332  0
         return equal(expectedValue, other.expectedValue)
 333  
             && equal(contextProperties, other.contextProperties)
 334  
             && equal(namespaces, other.namespaces)
 335  
             && equal(pattern, other.pattern);
 336  
     }
 337  
 
 338  
     public int hashCode()
 339  
     {
 340  0
         return hash(new Object[]{this.getClass(), expectedValue, contextProperties, namespaces, pattern});
 341  
     }
 342  
 }