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