View Javadoc

1   /*
2    * $Id: AbstractEntryPointResolver.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  package org.mule.model.resolvers;
11  
12  import org.mule.VoidResult;
13  import org.mule.api.MuleEventContext;
14  import org.mule.api.model.EntryPointResolver;
15  import org.mule.api.model.InvocationResult;
16  import org.mule.api.transformer.TransformerException;
17  import org.mule.transport.NullPayload;
18  import org.mule.util.ClassUtils;
19  import org.mule.util.StringMessageUtils;
20  
21  import java.lang.reflect.InvocationTargetException;
22  import java.lang.reflect.Method;
23  
24  import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  /**
30   * A Base class for {@link org.mule.api.model.EntryPointResolver}. It provides parameters for
31   * detemining if the payload of the message should be transformed first and whether void methods are
32   * acceptible. It also provides a method cashe for those resolvers that use reflection to discover methods
33   * on the service.
34   */
35  public abstract class AbstractEntryPointResolver implements EntryPointResolver
36  {
37      /** logger used by this class */
38      protected transient final Log logger = LogFactory.getLog(getClass());
39  
40      private boolean acceptVoidMethods = false;
41  
42      private boolean synchronizeCall = false;
43  
44      // @GuardedBy(itself)
45      protected final ConcurrentHashMap methodCache = new ConcurrentHashMap(4);
46  
47      public boolean isAcceptVoidMethods()
48      {
49          return acceptVoidMethods;
50      }
51  
52      public void setAcceptVoidMethods(boolean acceptVoidMethods)
53      {
54          this.acceptVoidMethods = acceptVoidMethods;
55      }
56  
57      protected Method getMethodByName(String methodName, MuleEventContext context)
58      {
59          return (Method) methodCache.get(methodName);
60      }
61  
62      protected Method addMethodByName(Method method, MuleEventContext context)
63      {
64          Method previousMethod = (Method) methodCache.putIfAbsent(method.getName(), method);
65          return (previousMethod != null ? previousMethod : method);
66      }
67  
68      protected Method addMethodByArguments(Object component, Method method, Object[] payload)
69      {
70          Method previousMethod = (Method) methodCache.putIfAbsent(getCacheKeyForPayload(component, payload), method);
71          return (previousMethod != null ? previousMethod : method);
72      }
73  
74  
75      protected Method getMethodByArguments(Object component, Object[] payload)
76      {
77          Method method = (Method) methodCache.get(getCacheKeyForPayload(component, payload));
78          return method;
79      }
80  
81      protected String getCacheKeyForPayload(Object component, Object[] payload)
82      {
83          StringBuffer key = new StringBuffer(48);
84          for (int i = 0; i < payload.length; i++)
85          {
86              Object o = payload[i];
87              if (o != null)
88              {
89                  key.append(o.getClass().getName());
90              }
91              else
92              {
93                  key.append("null");
94              }
95          }
96          key.append(".").append(ClassUtils.getClassName(component.getClass()));
97          return key.toString();
98      }
99  
100 
101     protected Object[] getPayloadFromMessage(MuleEventContext context) throws TransformerException
102     {
103         Object temp = context.getMessage().getPayload();
104         if (temp instanceof Object[])
105         {
106             return (Object[]) temp;
107         }
108         else if (temp instanceof NullPayload)
109         {
110             return ClassUtils.NO_ARGS;
111         }
112         else
113         {
114             return new Object[]{temp};
115         }
116     }
117 
118     protected InvocationResult invokeMethod(Object component, Method method, Object[] arguments)
119             throws InvocationTargetException, IllegalAccessException
120     {
121         String methodCall = null;
122 
123         if (logger.isDebugEnabled())
124         {
125             methodCall = component.getClass().getName() + "." + method.getName() + "("
126                     + StringMessageUtils.toString(ClassUtils.getClassTypes(arguments)) + ")";
127             logger.debug("Invoking " + methodCall);
128         }
129 
130         Object result;
131 
132         if(isSynchronizeCall())
133         {
134             synchronized (component)
135             {
136                 result = method.invoke(component, arguments);
137             }
138         }
139         else
140         {
141             result = method.invoke(component, arguments);
142         }
143 
144         if (method.getReturnType().equals(Void.TYPE))
145         {
146             result = VoidResult.getInstance();
147         }
148 
149         if (logger.isDebugEnabled())
150         {
151             logger.debug("Result of call " + methodCall + " is " + (result == null ? "null" : "not null"));
152         }
153 
154         return new InvocationResult(this, result, method);
155     }
156 
157     public boolean isSynchronizeCall()
158     {
159         return synchronizeCall;
160     }
161 
162     public void setSynchronizeCall(boolean synchronizeCall)
163     {
164         this.synchronizeCall = synchronizeCall;
165     }
166 
167     @Override
168     public String toString()
169     {
170         final StringBuffer sb = new StringBuffer();
171         sb.append("AbstractEntryPointResolver");
172         sb.append(", acceptVoidMethods=").append(acceptVoidMethods);
173         sb.append('}');
174         return sb.toString();
175     }
176 }