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.transport.http.issues;
8   
9   import org.mule.RequestContext;
10  import org.mule.api.DefaultMuleException;
11  import org.mule.api.MuleEventContext;
12  import org.mule.api.lifecycle.Callable;
13  import org.mule.config.i18n.MessageFactory;
14  import org.mule.tck.functional.EventCallback;
15  import org.mule.tck.functional.FunctionalTestNotification;
16  import org.mule.util.StringMessageUtils;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  
21  /**
22   * <code>FunctionalTestComponent</code> is a service that can be used by
23   * functional tests. This service accepts an EventCallback that can be used to
24   * assert the state of the current event.
25   * <p/>
26   * Also, this service fires {@link org.mule.tck.functional.FunctionalTestNotification} via Mule for every message received.
27   * Tests can register with Mule to receive these events by implementing
28   * {@link org.mule.tck.functional.FunctionalTestNotificationListener}.
29   *
30   * @see org.mule.tck.functional.EventCallback
31   * @see org.mule.tck.functional.FunctionalTestNotification
32   * @see org.mule.tck.functional.FunctionalTestNotificationListener
33   */
34  
35  public class NoTransformFunctionalTestComponent implements Callable
36  {
37      protected transient Log logger = LogFactory.getLog(getClass());
38  
39      public static final int STREAM_SAMPLE_SIZE = 4;
40      public static final int STREAM_BUFFER_SIZE = 4096;
41      private EventCallback eventCallback;
42      private Object returnMessage = null;
43      private boolean appendComponentName = false;
44      private boolean throwException = false;
45  
46      /**
47       * {@inheritDoc}
48       */
49      public Object onCall(MuleEventContext context) throws Exception
50      {
51          String contents = context.getMessageAsString();
52          String msg = StringMessageUtils.getBoilerPlate("Message Received in service: "
53                  + context.getFlowConstruct().getName() + ". Content is: "
54                  + StringMessageUtils.truncate(contents, 100, true), '*', 80);
55  
56          logger.info(msg);
57  
58          if (eventCallback != null)
59          {
60              eventCallback.eventReceived(context, this);
61          }
62  
63          Object replyMessage;
64          if (returnMessage != null)
65          {
66              replyMessage = returnMessage;
67          }
68          else
69          {
70              replyMessage = received(contents) + (appendComponentName ? " " + context.getFlowConstruct().getName() : "");
71          }
72  
73          context.getMuleContext().fireNotification(
74                  new FunctionalTestNotification(context, replyMessage, FunctionalTestNotification.EVENT_RECEIVED));
75  
76          if (throwException)
77          {
78              throw new DefaultMuleException(MessageFactory.createStaticMessage("Functional Test Service Exception"));
79          }
80  
81          return replyMessage;
82      }
83  
84      /**
85       * Append " Received" to contents.  Exposed as static method so tests can call to
86       * construct string for comparison.
87       *
88       * @param contents
89       * @return Extended message
90       */
91      public static String received(String contents)
92      {
93          return contents + " Received";
94      }
95  
96      /**
97       * @param data the event data received
98       * @return the processed message
99       * @throws Exception
100      *
101      * @deprecated Not sure why we have this duplicate method here. Need to investigate...
102      */
103     public Object onReceive(Object data) throws Exception
104     {
105         MuleEventContext context = RequestContext.getEventContext();
106 
107         String contents = data.toString();
108         String msg = StringMessageUtils.getBoilerPlate("Message Received in service: "
109                 + context.getFlowConstruct().getName() + ". Content is: "
110                 + StringMessageUtils.truncate(contents, 100, true), '*', 80);
111 
112         logger.info(msg);
113 
114         if (eventCallback != null)
115         {
116             eventCallback.eventReceived(context, this);
117         }
118 
119         Object replyMessage;
120         if (returnMessage != null)
121         {
122             replyMessage = returnMessage;
123         }
124         else
125         {
126             replyMessage = contents + " Received";
127         }
128 
129         context.getMuleContext().fireNotification(
130                 new FunctionalTestNotification(context, replyMessage, FunctionalTestNotification.EVENT_RECEIVED));
131 
132         if (throwException)
133         {
134             if(returnMessage!=null && returnMessage instanceof Exception)
135             {
136                 throw (Exception)returnMessage;
137             }
138             else
139             {
140                 throw new DefaultMuleException(MessageFactory.createStaticMessage("Functional Test Service Exception"));
141             }
142         }
143 
144         return replyMessage;
145     }
146 
147     /**
148      * An event callback is called when a message is received by the service.
149      * An MuleEvent callback isn't strictly required but it is usfal for performing assertions
150      * on the current message being received.
151      * Note that the FunctionalTestComponent should be made a singleton
152      * when using MuleEvent callbacks
153      * <p/>
154      * Another option is to register a {@link org.mule.tck.functional.FunctionalTestNotificationListener} with Mule and this
155      * will deleiver a {@link org.mule.tck.functional.FunctionalTestNotification} for every message received by this service
156      *
157      * @return the callback to call when a message is received
158      * @see org.mule.tck.functional.FunctionalTestNotification
159      * @see org.mule.tck.functional.FunctionalTestNotificationListener
160      */
161     public EventCallback getEventCallback()
162     {
163         return eventCallback;
164     }
165 
166     /**
167      * An event callback is called when a message is received by the service.
168      * An MuleEvent callback isn't strictly required but it is usfal for performing assertions
169      * on the current message being received.
170      * Note that the FunctionalTestComponent should be made a singleton
171      * when using MuleEvent callbacks
172      * <p/>
173      * Another option is to register a {@link org.mule.tck.functional.FunctionalTestNotificationListener} with Mule and this
174      * will deleiver a {@link org.mule.tck.functional.FunctionalTestNotification} for every message received by this service
175      *
176      * @param eventCallback the callback to call when a message is received
177      * @see org.mule.tck.functional.FunctionalTestNotification
178      * @see org.mule.tck.functional.FunctionalTestNotificationListener
179      */
180     public void setEventCallback(EventCallback eventCallback)
181     {
182         this.eventCallback = eventCallback;
183     }
184 
185     /**
186      * Often you will may want to return a fixed message payload to simulate and external system call.
187      * This can be done using the 'returnMessage' property. Note that you can return complex objects by
188      * using the <container-property> element in the Xml configuration.
189      *
190      * @return the message payload to always return from this service instance
191      */
192     public Object getReturnMessage()
193     {
194         return returnMessage;
195     }
196 
197     /**
198      * Often you will may want to return a fixed message payload to simulate and external system call.
199      * This can be done using the 'returnMessage' property. Note that you can return complex objects by
200      * using the <container-property> element in the Xml configuration.
201      *
202      * @param returnMessage the message payload to always return from this service instance
203      */
204     public void setReturnMessage(Object returnMessage)
205     {
206         this.returnMessage = returnMessage;
207     }
208 
209     /**
210      * Sometimes you will want the service to always throw an exception, if this is the case you can
211      * set the 'throwException' property to true.
212      *
213      * @return throwException true if an exception should always be thrown from this instance.
214      *         If the {@link #returnMessage} property is set and is of type
215      *         java.lang.Exception, that exception will be thrown.
216      */
217     public boolean isThrowException()
218     {
219         return throwException;
220     }
221 
222     /**
223      * Sometimes you will want the service to always throw an exception, if this is the case you can
224      * set the 'throwException' property to true.
225      *
226      * @param throwException true if an exception should always be thrown from this instance.
227      *                       If the {@link #returnMessage} property is set and is of type
228      *                       java.lang.Exception, that exception will be thrown.
229      */
230     public void setThrowException(boolean throwException)
231     {
232         this.throwException = throwException;
233     }
234 
235     /**
236      * This will cause the service to append the compoent name to the end of the message
237      * returned from this service. This only works when processing String messages.
238      * This feature is useful when processing multiple messages using a pool of FunctionalTestComponents
239      * to determine who processed the resulting message
240      *
241      * @return true if the service name will be appended to the return message
242      */
243     public boolean isAppendComponentName()
244     {
245         return appendComponentName;
246     }
247 
248     /**
249      * This will cause the service to append the compoent name to the end of the message
250      * returned from this service. This only works when processing String messages.
251      * This feature is useful when processing multiple messages using a pool of FunctionalTestComponents
252      * to determine who processed the resulting message
253      *
254      * @param appendComponentName true if the service name will be appended to the return message
255      */
256     public void setAppendComponentName(boolean appendComponentName)
257     {
258         this.appendComponentName = appendComponentName;
259     }
260 
261 }