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