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