Coverage Report - org.mule.module.xml.expression.AbstractXPathExpressionEvaluator
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractXPathExpressionEvaluator
0%
0/55
0%
0/16
0
AbstractXPathExpressionEvaluator$1
0%
0/7
0%
0/2
0
 
 1  
 /*
 2  
  * $Id: AbstractXPathExpressionEvaluator.java 20321 2010-11-24 15:21:24Z dfeist $
 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  
 package org.mule.module.xml.expression;
 11  
 
 12  
 import org.mule.api.MuleContext;
 13  
 import org.mule.api.MuleMessage;
 14  
 import org.mule.api.MuleRuntimeException;
 15  
 import org.mule.api.context.MuleContextAware;
 16  
 import org.mule.api.context.notification.MuleContextNotificationListener;
 17  
 import org.mule.api.expression.ExpressionEvaluator;
 18  
 import org.mule.api.expression.ExpressionRuntimeException;
 19  
 import org.mule.api.lifecycle.Disposable;
 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.config.i18n.CoreMessages;
 24  
 import org.mule.context.notification.MuleContextNotification;
 25  
 import org.mule.module.xml.i18n.XmlMessages;
 26  
 import org.mule.module.xml.util.NamespaceManager;
 27  
 
 28  
 import java.util.ArrayList;
 29  
 import java.util.Iterator;
 30  
 import java.util.List;
 31  
 import java.util.Map;
 32  
 import java.util.WeakHashMap;
 33  
 
 34  
 import org.dom4j.Document;
 35  
 import org.jaxen.JaxenException;
 36  
 import org.jaxen.XPath;
 37  
 import org.mule.transformer.types.DataTypeFactory;
 38  
 
 39  
 /**
 40  
  * Provides a base class for XPath property extractors. The XPath engine used is jaxen (http://jaxen.org) which supports
 41  
  * XPath queries on other object models such as JavaBeans as well as Xml
 42  
  */
 43  0
 public abstract class AbstractXPathExpressionEvaluator implements ExpressionEvaluator, Initialisable, Disposable, MuleContextAware
 44  
 {
 45  0
     private Map<String, XPath> cache = new WeakHashMap<String, XPath>(8);
 46  
 
 47  
     private MuleContext muleContext;
 48  
     private NamespaceManager namespaceManager;
 49  
 
 50  
     public void setMuleContext(MuleContext context)
 51  
     {
 52  0
         this.muleContext = context;
 53  
 
 54  0
     }
 55  
 
 56  
     public void initialise() throws InitialisationException
 57  
     {
 58  
         try
 59  
         {
 60  
             /*
 61  
                 Workaround for standalone mode, when registry bootstrap order may be non-deterministic and lead
 62  
                 to failures on startup.
 63  
 
 64  
                 initialise() can't do any lookups as it will have spring create and init beans for things like
 65  
                 global endpoints, interfering with current lifecycle and leading to failure.
 66  
                 TODO AP/RM this will be solved by the @Inject annotation or phase, as discussed
 67  
              */
 68  0
             this.muleContext.registerListener(new MuleContextNotificationListener<MuleContextNotification>(){
 69  
 
 70  
                 public void onNotification(MuleContextNotification notification)
 71  
                 {
 72  
                     // CONTEXT_INITIALIZED fires too soon, before registry is inited, thus using this one
 73  0
                     if (MuleContextNotification.CONTEXT_STARTING == notification.getAction())
 74  
                     {
 75  
                         try
 76  
                         {
 77  0
                             namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
 78  
                         }
 79  0
                         catch (RegistrationException e)
 80  
                         {
 81  0
                             throw new RuntimeException(e);
 82  0
                         }
 83  
                     }
 84  0
                 }
 85  
             });
 86  
         }
 87  0
         catch (Throwable t)
 88  
         {
 89  0
             throw new InitialisationException(t, this);
 90  0
         }
 91  0
     }
 92  
 
 93  
     public void inject() throws Exception
 94  
     {
 95  
         try
 96  
         {
 97  0
             namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
 98  
         }
 99  0
         catch (RegistrationException e)
 100  
         {
 101  0
             throw new ExpressionRuntimeException(CoreMessages.failedToLoad("NamespaceManager"), e);
 102  0
         }
 103  0
     }
 104  
 
 105  
     /** {@inheritDoc} */
 106  
     public Object evaluate(String expression, MuleMessage message)
 107  
     {
 108  
         try
 109  
         {
 110  0
             Object payload = message.getPayload();
 111  
             //we need to convert to a Dom if its an XML string
 112  0
             if(payload instanceof String)
 113  
             {
 114  0
                 payload = message.getPayload(DataTypeFactory.create(Document.class));
 115  
             }
 116  
 
 117  0
             XPath xpath = getXPath(expression, payload);
 118  0
             if(namespaceManager!=null)
 119  
             {
 120  0
                 addNamespaces(namespaceManager, xpath);
 121  
             }
 122  
 
 123  0
             List<?> result = xpath.selectNodes(payload);
 124  0
             result = extractResultsFromNodes(result);
 125  0
             if(result.size()==1)
 126  
             {
 127  0
                 return result.get(0);
 128  
             }
 129  0
             else if(result.size()==0)
 130  
             {
 131  0
                 return null;
 132  
             }
 133  
             else
 134  
             {
 135  0
                 return result;
 136  
             }
 137  
         }
 138  0
         catch (Exception e)
 139  
         {
 140  0
             throw new MuleRuntimeException(XmlMessages.failedToProcessXPath(expression), e);
 141  
         }
 142  
     }
 143  
 
 144  
     protected void addNamespaces(NamespaceManager manager, XPath xpath)
 145  
     {
 146  0
         for (Iterator<?> iterator = manager.getNamespaces().entrySet().iterator(); iterator.hasNext();)
 147  
         {
 148  0
             Map.Entry<?, ?> entry = (Map.Entry<?, ?>)iterator.next();
 149  
             try
 150  
             {
 151  0
                 xpath.addNamespace(entry.getKey().toString(), entry.getValue().toString());
 152  
             }
 153  0
             catch (JaxenException e)
 154  
             {
 155  0
                 throw new ExpressionRuntimeException(XmlMessages.failedToRegisterNamespace(entry.getKey().toString(), entry.getValue().toString()));
 156  0
             }
 157  0
         }
 158  0
     }
 159  
 
 160  
     /** {@inheritDoc} */
 161  
     public final void setName(String name)
 162  
     {
 163  0
         throw new UnsupportedOperationException("setName");
 164  
     }
 165  
 
 166  
     protected XPath getXPath(String expression, Object object) throws JaxenException
 167  
     {
 168  0
         XPath xpath = cache.get(expression + getClass().getName());
 169  0
         if(xpath==null)
 170  
         {
 171  0
             xpath = createXPath(expression, object);
 172  0
             cache.put(expression + getClass().getName(), xpath);
 173  
         }
 174  0
         return xpath;
 175  
     }
 176  
 
 177  
     protected abstract XPath createXPath(String expression, Object object) throws JaxenException;
 178  
 
 179  
     protected List<?> extractResultsFromNodes(List<?> results)
 180  
     {
 181  0
         if (results == null)
 182  
         {
 183  0
             return null;
 184  
         }
 185  0
         List<Object> newResults = new ArrayList<Object>(results.size());
 186  0
         for (Object o : results)
 187  
         {
 188  0
             newResults.add(extractResultFromNode(o));
 189  
         }
 190  0
         return newResults;
 191  
     }
 192  
 
 193  
     /**
 194  
      * A lifecycle method where implementor should free up any resources. If an
 195  
      * exception is thrown it should just be logged and processing should continue.
 196  
      * This method should not throw Runtime exceptions.
 197  
      */
 198  
     public void dispose()
 199  
     {
 200  0
         cache.clear();
 201  0
     }
 202  
 
 203  
     public NamespaceManager getNamespaceManager()
 204  
     {
 205  0
         return namespaceManager;
 206  
     }
 207  
 
 208  
     public void setNamespaceManager(NamespaceManager namespaceManager)
 209  
     {
 210  0
         this.namespaceManager = namespaceManager;
 211  0
     }
 212  
 
 213  
     public MuleContext getMuleContext()
 214  
     {
 215  0
         return muleContext;
 216  
     }
 217  
 
 218  
     protected abstract Object extractResultFromNode(Object result);
 219  
 }