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