Coverage Report - org.mule.module.xml.filters.JXPathFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
JXPathFilter
0%
0/114
0%
0/62
0
 
 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.module.xml.filters;
 8  
 
 9  
 import static org.mule.util.ClassUtils.equal;
 10  
 import static org.mule.util.ClassUtils.hash;
 11  
 
 12  
 import org.mule.api.MuleContext;
 13  
 import org.mule.api.MuleMessage;
 14  
 import org.mule.api.context.MuleContextAware;
 15  
 import org.mule.api.expression.ExpressionRuntimeException;
 16  
 import org.mule.api.lifecycle.Initialisable;
 17  
 import org.mule.api.lifecycle.InitialisationException;
 18  
 import org.mule.api.registry.RegistrationException;
 19  
 import org.mule.api.routing.filter.Filter;
 20  
 import org.mule.config.i18n.CoreMessages;
 21  
 import org.mule.module.xml.util.NamespaceManager;
 22  
 import org.mule.module.xml.util.XMLUtils;
 23  
 
 24  
 import java.util.HashMap;
 25  
 import java.util.Iterator;
 26  
 import java.util.Map;
 27  
 
 28  
 import org.apache.commons.jxpath.AbstractFactory;
 29  
 import org.apache.commons.jxpath.JXPathContext;
 30  
 import org.apache.commons.logging.Log;
 31  
 import org.apache.commons.logging.LogFactory;
 32  
 import org.dom4j.Document;
 33  
 import org.dom4j.DocumentHelper;
 34  
 import org.dom4j.XPath;
 35  
 
 36  
 /**
 37  
  * <code>JXPathFilter</code> evaluates an XPath expression against a W3C Document,
 38  
  * XML string, or Java bean and returns true if the result is as expected.
 39  
  */
 40  
 public class JXPathFilter implements Filter, MuleContextAware, Initialisable
 41  
 {
 42  
 
 43  0
     protected transient Log logger = LogFactory.getLog(getClass());
 44  
 
 45  
     private String pattern;
 46  
     private String expectedValue;
 47  0
     private Map namespaces = null;
 48  0
     private Map contextProperties = null;
 49  
     private AbstractFactory factory;
 50  0
     private boolean lenient = true;
 51  
 
 52  
     private MuleContext muleContext;
 53  
     private NamespaceManager namespaceManager;
 54  
 
 55  
     public JXPathFilter()
 56  
     {
 57  0
         super();
 58  0
     }
 59  
 
 60  
     public void setMuleContext(MuleContext context)
 61  
     {
 62  0
         this.muleContext = context;
 63  0
     }
 64  
 
 65  
     public void initialise() throws InitialisationException
 66  
     {
 67  
         try
 68  
         {
 69  0
             namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
 70  
         }
 71  0
         catch (RegistrationException e)
 72  
         {
 73  0
             throw new ExpressionRuntimeException(CoreMessages.failedToLoad("NamespaceManager"), e);
 74  0
         }
 75  
 
 76  0
         if (namespaceManager != null)
 77  
         {
 78  0
             if (namespaces == null)
 79  
             {
 80  0
                 namespaces = new HashMap(namespaceManager.getNamespaces());
 81  
             }
 82  
             else
 83  
             {
 84  0
                 namespaces.putAll(namespaceManager.getNamespaces());
 85  
             }
 86  
         }
 87  0
     }
 88  
 
 89  
     public JXPathFilter(String pattern)
 90  0
     {
 91  0
         this.pattern = pattern;
 92  0
     }
 93  
 
 94  
     public JXPathFilter(String pattern, String expectedValue)
 95  0
     {
 96  0
         this.pattern = pattern;
 97  0
         this.expectedValue = expectedValue;
 98  0
     }
 99  
 
 100  
     public boolean accept(MuleMessage obj)
 101  
     {
 102  0
         if (obj.getPayload() instanceof byte[])
 103  
         {
 104  
             try
 105  
             {
 106  0
                 return accept(obj.getPayloadAsString());
 107  
             }
 108  0
             catch (Exception e)
 109  
             {
 110  0
                 logger.warn("JxPath filter rejected message because it could not convert from byte[] to String: " + e.getMessage(), e);
 111  0
                 return false;
 112  
             }
 113  
         }
 114  0
         return accept(obj.getPayload());
 115  
     }
 116  
 
 117  
     private boolean accept(Object obj)
 118  
     {
 119  0
         if (obj == null)
 120  
         {
 121  0
             logger.warn("Applying JXPathFilter to null object.");
 122  0
             return false;
 123  
         }
 124  0
         if (pattern == null)
 125  
         {
 126  0
             logger.warn("Expression for JXPathFilter is not set.");
 127  0
             return false;
 128  
         }
 129  0
         if (expectedValue == null)
 130  
         {
 131  
             // Handle the special case where the expected value really is null.
 132  0
             if (pattern.endsWith("= null") || pattern.endsWith("=null"))
 133  
             {
 134  0
                 expectedValue = "null";
 135  0
                 pattern = pattern.substring(0, pattern.lastIndexOf("="));
 136  
             }
 137  
             else
 138  
             {
 139  0
                 if (logger.isInfoEnabled())
 140  
                 {
 141  0
                     logger.info("Expected value for JXPathFilter is not set, using 'true' by default");
 142  
                 }
 143  0
                 expectedValue = Boolean.TRUE.toString();
 144  
             }
 145  
         }
 146  
 
 147  0
         Object xpathResult = null;
 148  0
         boolean accept = false;
 149  
 
 150  
         Document dom4jDoc;
 151  
         try
 152  
         {
 153  0
             dom4jDoc = XMLUtils.toDocument(obj, muleContext);
 154  
         }
 155  0
         catch (Exception e)
 156  
         {
 157  0
             logger.warn("JxPath filter rejected message because of an error while parsing XML: " + e.getMessage(), e);
 158  0
             return false;
 159  0
         }
 160  
 
 161  
         // Payload is XML
 162  0
         if (dom4jDoc != null)
 163  
         {
 164  0
             if (namespaces == null)
 165  
             {
 166  
                 // no namespace defined, let's perform a direct evaluation
 167  0
                 xpathResult = dom4jDoc.valueOf(pattern);
 168  
             }
 169  
             else
 170  
             {
 171  
                 // create an xpath expression with namespaces and evaluate it
 172  0
                 XPath xpath = DocumentHelper.createXPath(pattern);
 173  0
                 xpath.setNamespaceURIs(namespaces);
 174  0
                 xpathResult = xpath.valueOf(dom4jDoc);
 175  0
             }
 176  
         }
 177  
         // Payload is a Java object
 178  
         else
 179  
         {
 180  0
             if (logger.isDebugEnabled())
 181  
             {
 182  0
                 logger.debug("Passing object of type " + obj.getClass().getName() + " to JXPathContext");
 183  
             }
 184  0
             JXPathContext context = JXPathContext.newContext(obj);
 185  0
             initialise(context);
 186  0
             xpathResult = context.getValue(pattern);
 187  
         }
 188  
 
 189  0
         if (logger.isDebugEnabled())
 190  
         {
 191  0
             logger.debug("JXPathFilter Expression result = '" + xpathResult + "' -  Expected value = '"
 192  
                     + expectedValue + "'");
 193  
         }
 194  
         // Compare the XPath result with the expected result.
 195  0
         if (xpathResult != null)
 196  
         {
 197  0
             accept = xpathResult.toString().equals(expectedValue);
 198  
         }
 199  
         else
 200  
         {
 201  
             // A null result was actually expected.
 202  0
             if (expectedValue.equals("null"))
 203  
             {
 204  0
                 accept = true;
 205  
             }
 206  
             // A null result was not expected, something probably went wrong.
 207  
             else
 208  
             {
 209  0
                 logger.warn("JXPathFilter expression evaluates to null: " + pattern);
 210  
             }
 211  
         }
 212  
 
 213  0
         if (logger.isDebugEnabled())
 214  
         {
 215  0
             logger.debug("JXPathFilter accept object  : " + accept);
 216  
         }
 217  
 
 218  0
         return accept;
 219  
     }
 220  
 
 221  
     /**
 222  
      * Initializes the JXPathContext based on any relevant properties set for the
 223  
      * filter.
 224  
      *
 225  
      * @param context the JXPathContext to initialize
 226  
      */
 227  
     protected void initialise(JXPathContext context)
 228  
     {
 229  
         Map.Entry entry;
 230  0
         if (namespaces != null)
 231  
         {
 232  0
             if (logger.isDebugEnabled())
 233  
             {
 234  0
                 logger.debug("Initializing JXPathContext with namespaces: " + namespaces);
 235  
             }
 236  
 
 237  0
             for (Iterator iterator = namespaces.entrySet().iterator(); iterator.hasNext();)
 238  
             {
 239  0
                 entry = (Map.Entry) iterator.next();
 240  0
                 context.registerNamespace(entry.getKey().toString(), entry.getValue().toString());
 241  
             }
 242  
         }
 243  
 
 244  0
         if (contextProperties != null)
 245  
         {
 246  0
             if (logger.isDebugEnabled())
 247  
             {
 248  0
                 logger.debug("Initializing JXPathContext with properties: " + contextProperties);
 249  
             }
 250  
 
 251  0
             for (Iterator iterator = contextProperties.entrySet().iterator(); iterator.hasNext();)
 252  
             {
 253  0
                 entry = (Map.Entry) iterator.next();
 254  0
                 context.setValue(entry.getKey().toString(), entry.getValue());
 255  
             }
 256  
         }
 257  
 
 258  0
         if (factory != null)
 259  
         {
 260  0
             context.setFactory(factory);
 261  
         }
 262  
 
 263  0
         context.setLenient(lenient);
 264  0
     }
 265  
 
 266  
     /**
 267  
      * @return XPath expression
 268  
      */
 269  
     public String getPattern()
 270  
     {
 271  0
         return pattern;
 272  
     }
 273  
 
 274  
     /**
 275  
      * @param pattern The XPath expression
 276  
      */
 277  
     public void setPattern(String pattern)
 278  
     {
 279  0
         this.pattern = pattern;
 280  0
     }
 281  
 
 282  
     /**
 283  
      * @return The expected result value of the XPath expression
 284  
      */
 285  
     public String getExpectedValue()
 286  
     {
 287  0
         return expectedValue;
 288  
     }
 289  
 
 290  
     /**
 291  
      * Sets the expected result value of the XPath expression
 292  
      */
 293  
     public void setExpectedValue(String expectedValue)
 294  
     {
 295  0
         this.expectedValue = expectedValue;
 296  0
     }
 297  
 
 298  
     /**
 299  
      * @return The expected result value of the XPath expression
 300  
      * @deprecated Use <code>getExpectedValue()</code>.
 301  
      */
 302  
     public String getValue()
 303  
     {
 304  0
         return getExpectedValue();
 305  
     }
 306  
 
 307  
     /**
 308  
      * Sets the expected result value of the XPath expression
 309  
      *
 310  
      * @deprecated Use <code>setExpectedValue(String expectedValue)</code>.
 311  
      */
 312  
     public void setValue(String value)
 313  
     {
 314  0
         setExpectedValue(value);
 315  0
     }
 316  
 
 317  
     public Map getNamespaces()
 318  
     {
 319  0
         return namespaces;
 320  
     }
 321  
 
 322  
     public void setNamespaces(Map namespaces)
 323  
     {
 324  0
         this.namespaces = namespaces;
 325  0
     }
 326  
 
 327  
     public Map getContextProperties()
 328  
     {
 329  0
         return contextProperties;
 330  
     }
 331  
 
 332  
     public void setContextProperties(Map contextProperties)
 333  
     {
 334  0
         this.contextProperties = contextProperties;
 335  0
     }
 336  
 
 337  
     public AbstractFactory getFactory()
 338  
     {
 339  0
         return factory;
 340  
     }
 341  
 
 342  
     public void setFactory(AbstractFactory factory)
 343  
     {
 344  0
         this.factory = factory;
 345  0
     }
 346  
 
 347  
     public boolean isLenient()
 348  
     {
 349  0
         return lenient;
 350  
     }
 351  
 
 352  
     public void setLenient(boolean lenient)
 353  
     {
 354  0
         this.lenient = lenient;
 355  0
     }
 356  
     
 357  
     public boolean equals(Object obj)
 358  
     {
 359  0
         if (this == obj) return true;
 360  0
         if (obj == null || getClass() != obj.getClass()) return false;
 361  
 
 362  0
         final JXPathFilter other = (JXPathFilter) obj;
 363  0
         return equal(expectedValue, other.expectedValue)
 364  
             && equal(contextProperties, other.contextProperties)
 365  
             && equal(namespaces, other.namespaces)
 366  
             && equal(pattern, other.pattern)
 367  
             && lenient == other.lenient;
 368  
     }
 369  
 
 370  
     public int hashCode()
 371  
     {
 372  0
         return hash(new Object[]{this.getClass(), expectedValue, contextProperties, namespaces, pattern, lenient});
 373  
     }
 374  
 }