View Javadoc
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.expression;
8   
9   import org.apache.commons.jxpath.Container;
10  import org.mule.api.MuleContext;
11  import org.mule.api.MuleMessage;
12  import org.mule.api.context.MuleContextAware;
13  import org.mule.api.expression.ExpressionEvaluator;
14  import org.mule.api.expression.ExpressionRuntimeException;
15  import org.mule.api.registry.RegistrationException;
16  import org.mule.config.i18n.CoreMessages;
17  import org.mule.module.xml.i18n.XmlMessages;
18  import org.mule.module.xml.util.NamespaceManager;
19  import org.mule.module.xml.util.XMLUtils;
20  
21  import java.util.Iterator;
22  import java.util.Map;
23  
24  import org.apache.commons.jxpath.JXPathContext;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.w3c.dom.Document;
28  
29  /**
30   * Will extract properties based on Xpath expressions. Will work on Xml/Dom and beans
31   *
32   * @deprecated Developers should use xpath, bean or groovy instead of this expression evaluator since there are some
33   * quirks with JXPath and the performance is not good.
34   */
35  public class JXPathExpressionEvaluator implements ExpressionEvaluator, MuleContextAware
36  {
37      public static final String NAME = "jxpath";
38      /**
39       * logger used by this class
40       */
41      protected transient Log logger = LogFactory.getLog(getClass());
42      protected transient MuleContext muleContext;
43      private NamespaceManager namespaceManager;
44  
45      public void setMuleContext(MuleContext context)
46      {
47          muleContext = context;
48      }
49  
50      public Object evaluate(String expression, MuleMessage message)
51      {
52          Document document;
53          try
54          {
55              document = XMLUtils.toW3cDocument(message.getPayload());
56          }
57          catch (Exception e)
58          {
59              logger.error(e);
60              return null;
61          }
62  
63          JXPathContext context;
64  
65          if (document != null)
66          {
67              context = createContextForXml(document);
68          }
69          else
70          {
71              context = createContextForBean(message.getPayload());
72          }
73  
74          return getExpressionValue(context, expression);
75      }
76  
77      private JXPathContext createContextForXml(final Document document)
78      {
79          Container container = new Container()
80          {
81  
82              public Object getValue()
83              {
84                  return document;
85              }
86  
87              public void setValue(Object value)
88              {
89                  throw new UnsupportedOperationException();
90              }
91          };
92  
93          return JXPathContext.newContext(container);
94      }
95  
96      private JXPathContext createContextForBean(Object payload)
97      {
98          return JXPathContext.newContext(payload);
99      }
100 
101     private Object getExpressionValue(JXPathContext context, String expression)
102     {
103         NamespaceManager theNamespaceManager = getNamespaceManager();
104         if (theNamespaceManager != null)
105         {
106             addNamespacesToContext(theNamespaceManager, context);
107         }
108 
109         Object result = null;
110 
111         try
112         {
113             result = context.getValue(expression);
114         }
115         catch (Exception e)
116         {
117             if (logger.isDebugEnabled())
118             {
119                 logger.debug("failed to process JXPath expression: " + expression, e);
120             }
121         }
122 
123         return result;
124     }
125 
126     protected void addNamespacesToContext(NamespaceManager manager, JXPathContext context)
127     {
128         for (Iterator iterator = manager.getNamespaces().entrySet().iterator(); iterator.hasNext();)
129         {
130             Map.Entry entry = (Map.Entry) iterator.next();
131             try
132             {
133                 context.registerNamespace(entry.getKey().toString(), entry.getValue().toString());
134             }
135             catch (Exception e)
136             {
137                 throw new ExpressionRuntimeException(XmlMessages.failedToRegisterNamespace(entry.getKey().toString(), entry.getValue().toString()));
138             }
139         }
140     }
141 
142     /**
143      * {@inheritDoc}
144      */
145     public String getName()
146     {
147         return NAME;
148     }
149 
150     /**
151      * {@inheritDoc}
152      */
153     public void setName(String name)
154     {
155         throw new UnsupportedOperationException("setName");
156     }
157 
158     /**
159      *
160      * @return the nsmespace manager from the registry
161      */
162     protected synchronized NamespaceManager getNamespaceManager()
163     {
164         if (namespaceManager == null)
165         {
166 
167             try
168             {
169                 // We defer looking this up until registry is completely built
170                 if (muleContext != null)
171                 {
172                     namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
173                 }
174             }
175             catch (RegistrationException e)
176             {
177                 throw new ExpressionRuntimeException(CoreMessages.failedToLoad("NamespaceManager"), e);
178             }
179         }
180         return namespaceManager;
181     }
182 }