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.expression.transformers;
8   
9   import org.mule.api.MuleContext;
10  import org.mule.api.MuleMessage;
11  import org.mule.api.context.MuleContextAware;
12  import org.mule.api.expression.ExpressionRuntimeException;
13  import org.mule.api.transformer.Transformer;
14  import org.mule.api.transformer.TransformerException;
15  import org.mule.config.i18n.CoreMessages;
16  import org.mule.expression.ExpressionConfig;
17  import org.mule.transformer.types.DataTypeFactory;
18  
19  /**
20   * TODO
21   */
22  public class ExpressionArgument implements MuleContextAware
23  {
24      private ExpressionConfig expressionConfig = new ExpressionConfig();
25      private String name;
26      private boolean optional;
27      private Class<?> returnClass;
28      protected ClassLoader expressionEvaluationClassLoader = ExpressionArgument.class.getClassLoader();
29      private MuleContext muleContext;
30  
31      public ExpressionArgument()
32      {
33          super();
34      }
35  
36      public ExpressionArgument(String name, ExpressionConfig expressionConfig, boolean optional)
37      {
38          this(name, expressionConfig, optional, null);
39      }
40  
41      public ExpressionArgument(String name, ExpressionConfig expressionConfig, boolean optional, 
42          Class<?> returnClass)
43      {
44          this.expressionConfig = expressionConfig;
45          this.name = name;
46          this.optional = optional;
47          this.returnClass = returnClass;
48      }
49  
50      public void setMuleContext(MuleContext context)
51      {
52          this.muleContext = context;
53      }
54  
55      public String getName()
56      {
57          return name;
58      }
59  
60      public void setName(String name)
61      {
62          this.name = name;
63      }
64  
65      public ExpressionConfig getExpressionConfig()
66      {
67          return expressionConfig;
68      }
69  
70      public void setExpressionConfig(ExpressionConfig expressionConfig)
71      {
72          this.expressionConfig = expressionConfig;
73      }
74  
75      public boolean isOptional()
76      {
77          return optional;
78      }
79  
80      public void setOptional(boolean optional)
81      {
82          this.optional = optional;
83      }
84  
85      protected String getFullExpression()
86      {
87          return expressionConfig.getFullExpression(muleContext.getExpressionManager());
88      }
89  
90      protected void validate()
91      {
92          expressionConfig.validate(muleContext.getExpressionManager());
93      }
94  
95      /**
96       * Evaluates this Expression against the passed in Message.  If a returnClass is set on this Expression Argument it
97       * will be checked to ensure the Argument returns the correct class type.
98       * @param message the message to execute the expression on
99       * @return the result of the expression
100      * @throws ExpressionRuntimeException if the wrong return type is returned from the expression.
101      */
102     public Object evaluate(MuleMessage message) throws ExpressionRuntimeException
103     {
104         Object result = null;
105 
106         // MULE-4797 Because there is no way to specify the class-loader that script
107         // engines use and because scripts when used for expressions are compiled in
108         // runtime rather than at initialization the only way to ensure the correct
109         // class-loader to used is to switch it out here. We may want to consider
110         // passing the class-loader to the ExpressionManager and only doing this for
111         // certain ExpressionEvaluators further in.
112         ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
113         try
114         {
115             Thread.currentThread().setContextClassLoader(expressionEvaluationClassLoader);
116             result = muleContext.getExpressionManager().evaluate(getExpression(), getEvaluator(), message,
117                 !isOptional());
118         }
119         finally
120         {
121             // Restore original context class-loader
122             Thread.currentThread().setContextClassLoader(originalContextClassLoader);
123         }
124 
125         if (getReturnClass() != null && result != null)
126         {
127             if (!getReturnClass().isInstance(result))
128             {
129                 //If the return type does not match, lets attempt to transform it before throwing an error
130                 try
131                 {
132                     Transformer t = muleContext.getRegistry().lookupTransformer(
133                         DataTypeFactory.createFromObject(result), DataTypeFactory.create(getReturnClass()));
134                     result = t.transform(result);
135                 }
136                 catch (TransformerException e)
137                 {
138                     throw new ExpressionRuntimeException(CoreMessages.transformUnexpectedType(result.getClass(),
139                     getReturnClass()), e);
140                 }
141 
142             }
143 //            if(result instanceof Collection && ((Collection)result).size()==0 && !isOptional())
144 //            {
145 //                throw new ExpressionRuntimeException(CoreMessages.expressionEvaluatorReturnedNull(this.getEvaluator(), this.getExpression()));
146 //            }
147         }
148         return result;
149     }
150 
151     public String getExpression()
152     {
153         return expressionConfig.getExpression();
154     }
155 
156     public void setExpression(String expression)
157     {
158         expressionConfig.setExpression(expression);
159     }
160 
161     public String getEvaluator()
162     {
163         return expressionConfig.getEvaluator();
164     }
165     
166     public void setEvaluator(String evaluator)
167     {
168         expressionConfig.setEvaluator(evaluator);
169     }
170 
171     public void setCustomEvaluator(String evaluator)
172     {
173         expressionConfig.setCustomEvaluator(evaluator);
174     }
175 
176     public String getCustomEvaluator()
177     {
178         return expressionConfig.getCustomEvaluator();
179     }
180 
181     public Class<?> getReturnClass()
182     {
183         return returnClass;
184     }
185 
186     public void setReturnDataType(Class<?> returnClass)
187     {
188         this.returnClass = returnClass;
189     }
190     
191     public void setExpressionEvaluationClassLoader(ClassLoader expressionEvaluationClassLoader)
192     {
193         this.expressionEvaluationClassLoader = expressionEvaluationClassLoader;
194     }
195 
196 }