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