Coverage Report - org.mule.module.xml.filters.XPathFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
XPathFilter
0%
0/93
0%
0/58
0
XPathFilter$1
0%
0/10
0%
0/6
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.config.i18n.MessageFactory;
 22  
 import org.mule.module.xml.util.NamespaceManager;
 23  
 import org.mule.util.ClassUtils;
 24  
 
 25  
 import java.text.MessageFormat;
 26  
 import java.util.Arrays;
 27  
 import java.util.Collections;
 28  
 import java.util.HashMap;
 29  
 import java.util.Iterator;
 30  
 import java.util.Map;
 31  
 
 32  
 import javax.xml.namespace.NamespaceContext;
 33  
 import javax.xml.xpath.XPath;
 34  
 import javax.xml.xpath.XPathConstants;
 35  
 import javax.xml.xpath.XPathFactory;
 36  
 
 37  
 import org.apache.commons.logging.Log;
 38  
 import org.apache.commons.logging.LogFactory;
 39  
 import org.w3c.dom.Node;
 40  
 
 41  
 /**
 42  
  */
 43  
 public class XPathFilter extends AbstractJaxpFilter 
 44  
     implements Filter, Initialisable, MuleContextAware
 45  
 {
 46  
 
 47  0
     protected transient Log logger = LogFactory.getLog(getClass());
 48  
 
 49  
     private String pattern;
 50  
     private String expectedValue;
 51  
     private XPath xpath;
 52  0
     private Map<String, String> prefixToNamespaceMap = null;
 53  
 
 54  
     private NamespaceManager namespaceManager;
 55  
 
 56  
     private MuleContext muleContext;
 57  
 
 58  
     public XPathFilter()
 59  0
     {
 60  0
     }
 61  
 
 62  
     public XPathFilter(String pattern)
 63  0
     {
 64  0
         this.pattern = pattern;
 65  0
     }
 66  
 
 67  
     public XPathFilter(String pattern, String expectedValue)
 68  0
     {
 69  0
         this.pattern = pattern;
 70  0
         this.expectedValue = expectedValue;
 71  0
     }
 72  
 
 73  
     public void setMuleContext(MuleContext context)
 74  
     {
 75  0
         this.muleContext = context;
 76  0
     }
 77  
 
 78  
     public void initialise() throws InitialisationException
 79  
     {
 80  0
         super.initialise();
 81  
         
 82  0
         if (getXpath() == null)
 83  
         {
 84  0
             setXpath(XPathFactory.newInstance().newXPath());
 85  
         }
 86  
 
 87  
 
 88  0
         if (pattern == null)
 89  
         {
 90  0
             throw new InitialisationException(
 91  
                 MessageFactory.createStaticMessage("A pattern must be supplied to the " +
 92  
                                                    ClassUtils.getSimpleName(getClass())),
 93  
                 this);
 94  
         }
 95  
 
 96  0
         if (muleContext != null)
 97  
         {
 98  
             try
 99  
             {
 100  0
                 namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
 101  
             }
 102  0
             catch (RegistrationException e)
 103  
             {
 104  0
                 throw new ExpressionRuntimeException(CoreMessages.failedToLoad("NamespaceManager"), e);
 105  0
             }
 106  
 
 107  0
             if (namespaceManager != null)
 108  
             {
 109  0
                 if (prefixToNamespaceMap == null)
 110  
                 {
 111  0
                     prefixToNamespaceMap = new HashMap(namespaceManager.getNamespaces());
 112  
                 }
 113  
                 else
 114  
                 {
 115  0
                     prefixToNamespaceMap.putAll(namespaceManager.getNamespaces());
 116  
                 }
 117  
             }
 118  
         }
 119  
         
 120  0
         final Map<String, String> prefixToNamespaceMap = this.prefixToNamespaceMap;
 121  0
         if (prefixToNamespaceMap != null)
 122  
         {
 123  0
             getXpath().setNamespaceContext(new NamespaceContext()
 124  0
             {
 125  
                 public String getNamespaceURI(String prefix)
 126  
                 {
 127  0
                     return prefixToNamespaceMap.get(prefix);
 128  
                 }
 129  
 
 130  
                 public String getPrefix(String namespaceURI)
 131  
                 {
 132  
 
 133  0
                     for (Map.Entry<String, String> entry : prefixToNamespaceMap.entrySet())
 134  
                     {
 135  0
                         if (namespaceURI.equals(entry.getValue()))
 136  
                         {
 137  0
                             return entry.getKey();
 138  
                         }
 139  
                     }
 140  
 
 141  0
                     return null;
 142  
                 }
 143  
 
 144  
                 public Iterator getPrefixes(String namespaceURI)
 145  
                 {
 146  0
                     String prefix = getPrefix(namespaceURI);
 147  0
                     if (prefix == null)
 148  
                     {
 149  0
                         return Collections.emptyList().iterator();
 150  
                     }
 151  
                     else
 152  
                     {
 153  0
                         return Arrays.asList(prefix).iterator();
 154  
                     }
 155  
                 }
 156  
             });
 157  
         }
 158  
 
 159  0
         if (logger.isInfoEnabled())
 160  
         {
 161  0
             logger.info("XPath implementation: " + getXpath());
 162  0
             logger.info("DocumentBuilderFactory implementation: " + getDocumentBuilderFactory());
 163  
         }
 164  0
     }
 165  
 
 166  
     public boolean accept(MuleMessage message)
 167  
     {
 168  0
         Object payload = message.getPayload();
 169  0
         if (payload == null)
 170  
         {
 171  0
             if (logger.isWarnEnabled())
 172  
             {
 173  0
                 logger.warn("Applying " + ClassUtils.getSimpleName(getClass()) + " to null object.");
 174  
             }
 175  0
             return false;
 176  
         }
 177  0
         if (pattern == null)
 178  
         {
 179  0
             if (logger.isWarnEnabled())
 180  
             {
 181  0
                 logger.warn("Expression for " + ClassUtils.getSimpleName(getClass()) + " is not set.");
 182  
             }
 183  0
             return false;
 184  
         }
 185  0
         if (expectedValue == null)
 186  
         {
 187  
             // Handle the special case where the expected value really is null.
 188  0
             if (pattern.endsWith("= null") || pattern.endsWith("=null"))
 189  
             {
 190  0
                 expectedValue = "null";
 191  0
                 pattern = pattern.substring(0, pattern.lastIndexOf("="));
 192  
             }
 193  
             else
 194  
             {
 195  0
                 if (logger.isInfoEnabled())
 196  
                 {
 197  0
                     logger.info("''expectedValue'' attribute for " + ClassUtils.getSimpleName(getClass()) +
 198  
                                 " is not set, using 'true' by default");
 199  
                 }
 200  0
                 expectedValue = Boolean.TRUE.toString();
 201  
             }
 202  
         }
 203  
 
 204  
         Node node;
 205  
         try
 206  
         {
 207  0
             node = toDOMNode(payload);
 208  
         }
 209  0
         catch (Exception e)
 210  
         {
 211  0
             if (logger.isWarnEnabled())
 212  
             {
 213  0
                 logger.warn(ClassUtils.getSimpleName(getClass()) + " filter rejected message because of an error while parsing XML: "
 214  
                             + e.getMessage(), e);
 215  
             }
 216  0
             return false;
 217  0
         }
 218  
 
 219  0
         message.setPayload(node);
 220  
 
 221  0
         return accept(node);
 222  
     }
 223  
 
 224  
     protected boolean accept(Node node)
 225  
     {
 226  
         Object xpathResult;
 227  0
         boolean accept = false;
 228  
 
 229  
         try
 230  
         {
 231  0
             xpathResult = getXpath().evaluate(pattern, node, XPathConstants.STRING);
 232  
         }
 233  0
         catch (Exception e)
 234  
         {
 235  0
             if (logger.isWarnEnabled())
 236  
             {
 237  0
                 logger.warn(
 238  
                         ClassUtils.getSimpleName(getClass()) + " filter rejected message because of an error while evaluating the expression: "
 239  
                         + e.getMessage(), e);
 240  
             }
 241  0
             return false;
 242  0
         }
 243  
 
 244  0
         if (logger.isDebugEnabled())
 245  
         {
 246  0
             logger.debug(MessageFormat.format("{0} Expression result = ''{1}'' -  Expected value = ''{2}''",
 247  
                                               ClassUtils.getSimpleName(getClass()), xpathResult, expectedValue));
 248  
         }
 249  
 
 250  
         // Compare the XPath result with the expected result.
 251  0
         if (xpathResult != null && !"".equals(xpathResult))
 252  
         {
 253  0
             accept = xpathResult.toString().equals(expectedValue);
 254  
         }
 255  
         else
 256  
         {
 257  
             // A null result was actually expected.
 258  0
             if ("null".equals(expectedValue))
 259  
             {
 260  0
                 accept = true;
 261  
             }
 262  
             // A null result was not expected, something probably went wrong.
 263  
             else
 264  
             {
 265  0
                 if (logger.isDebugEnabled())
 266  
                 {
 267  0
                     logger.debug(MessageFormat.format("{0} expression evaluates to null: {1}",
 268  
                                                       ClassUtils.getSimpleName(getClass()), pattern));
 269  
                 }
 270  
             }
 271  
         }
 272  
 
 273  0
         if (logger.isDebugEnabled())
 274  
         {
 275  0
             logger.debug(MessageFormat.format("{0} accept object  : {1}", ClassUtils.getSimpleName(getClass()), accept));
 276  
         }
 277  
 
 278  0
         return accept;
 279  
     }
 280  
 
 281  
     /**
 282  
      * @return XPath expression
 283  
      */
 284  
     public String getPattern()
 285  
     {
 286  0
         return pattern;
 287  
     }
 288  
 
 289  
     /**
 290  
      * @param pattern The XPath expression
 291  
      */
 292  
     public void setPattern(String pattern)
 293  
     {
 294  0
         this.pattern = pattern;
 295  0
     }
 296  
 
 297  
     /**
 298  
      * @return The expected result value of the XPath expression
 299  
      */
 300  
     public String getExpectedValue()
 301  
     {
 302  0
         return expectedValue;
 303  
     }
 304  
 
 305  
     /**
 306  
      * Sets the expected result value of the XPath expression
 307  
      * 
 308  
      * @param expectedValue The expected value.
 309  
      */
 310  
     public void setExpectedValue(String expectedValue)
 311  
     {
 312  0
         this.expectedValue = expectedValue;
 313  0
     }
 314  
 
 315  
     /**
 316  
      * The xpath object to use to evaluate the expression.
 317  
      * 
 318  
      * @return The xpath object to use to evaluate the expression.
 319  
      */
 320  
     public XPath getXpath()
 321  
     {
 322  0
         return xpath;
 323  
     }
 324  
 
 325  
     /**
 326  
      * The xpath object to use to evaluate the expression.
 327  
      * 
 328  
      * @param xpath The xpath object to use to evaluate the expression.
 329  
      */
 330  
     public void setXpath(XPath xpath)
 331  
     {
 332  0
         this.xpath = xpath;
 333  0
     }
 334  
 
 335  
 
 336  
     /**
 337  
      * The prefix-to-namespace map for the namespace context to be applied to the
 338  
      * XPath evaluation.
 339  
      * 
 340  
      * @return The prefix-to-namespace map for the namespace context to be applied to
 341  
      *         the XPath evaluation.
 342  
      */
 343  
     public Map<String, String> getNamespaces()
 344  
     {
 345  0
         return prefixToNamespaceMap;
 346  
     }
 347  
 
 348  
     /**
 349  
      * The prefix-to-namespace map for the namespace context to be applied to the
 350  
      * XPath evaluation.
 351  
      * 
 352  
      * @param prefixToNamespaceMap The prefix-to-namespace map for the namespace
 353  
      *            context to be applied to the XPath evaluation.
 354  
      */
 355  
     public void setNamespaces(Map<String, String> prefixToNamespaceMap)
 356  
     {
 357  0
         this.prefixToNamespaceMap = prefixToNamespaceMap;
 358  0
     }
 359  
     
 360  
     public boolean equals(Object obj)
 361  
     {
 362  0
         if (this == obj) return true;
 363  0
         if (obj == null || getClass() != obj.getClass()) return false;
 364  
 
 365  0
         final XPathFilter other = (XPathFilter) obj;
 366  0
         return equal(expectedValue, other.expectedValue)
 367  
             && equal(prefixToNamespaceMap, other.prefixToNamespaceMap)
 368  
             && equal(pattern, other.pattern);
 369  
     }
 370  
 
 371  
     public int hashCode()
 372  
     {
 373  0
         return hash(new Object[]{this.getClass(), expectedValue, prefixToNamespaceMap, pattern});
 374  
     }
 375  
 }