View Javadoc

1   /*
2    * $Id: VMMessageDispatcher.java 7976 2007-08-21 14:26:13Z dirk.olmes $
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.providers.vm;
12  
13  import org.mule.MuleManager;
14  import org.mule.config.i18n.CoreMessages;
15  import org.mule.impl.MuleMessage;
16  import org.mule.providers.AbstractMessageDispatcher;
17  import org.mule.providers.vm.i18n.VMMessages;
18  import org.mule.transformers.simple.ObjectToByteArray;
19  import org.mule.umo.UMOEvent;
20  import org.mule.umo.UMOMessage;
21  import org.mule.umo.endpoint.UMOEndpointURI;
22  import org.mule.umo.endpoint.UMOImmutableEndpoint;
23  import org.mule.umo.provider.DispatchException;
24  import org.mule.umo.provider.NoReceiverForEndpointException;
25  import org.mule.umo.provider.UMOStreamMessageAdapter;
26  import org.mule.util.queue.Queue;
27  import org.mule.util.queue.QueueSession;
28  
29  import java.io.ByteArrayInputStream;
30  import java.io.InputStream;
31  import java.io.PipedInputStream;
32  import java.io.PipedOutputStream;
33  
34  /**
35   * <code>VMMessageDispatcher</code> is used for providing in memory interaction
36   * between components.
37   */
38  public class VMMessageDispatcher extends AbstractMessageDispatcher
39  {
40      private final VMConnector connector;
41      private final ObjectToByteArray objectToByteArray;
42  
43      public VMMessageDispatcher(UMOImmutableEndpoint endpoint)
44      {
45          super(endpoint);
46          this.connector = (VMConnector)endpoint.getConnector();
47          objectToByteArray = new ObjectToByteArray();
48      }
49  
50      /**
51       * Make a specific request to the underlying transport
52       * 
53       * @param timeout the maximum time the operation should block before returning.
54       *            The call should return immediately if there is data available. If
55       *            no data becomes available before the timeout elapses, null will be
56       *            returned
57       * @return the result of the request wrapped in a UMOMessage object. Null will be
58       *         returned if no data was available
59       * @throws Exception if the call to the underlying protocol causes an exception
60       */
61      protected UMOMessage doReceive(long timeout) throws Exception
62      {
63          if (!connector.isQueueEvents())
64          {
65              throw new UnsupportedOperationException("Receive requested on VM Connector, but queueEvents is false");
66          }
67  
68          try
69          {
70              QueueSession queueSession = connector.getQueueSession();
71              Queue queue = queueSession.getQueue(endpoint.getEndpointURI().getAddress());
72  
73              if (queue == null)
74              {
75                  if (logger.isDebugEnabled())
76                  {
77                      logger.debug("No queue with name " + endpoint.getEndpointURI().getAddress());
78                  }
79                  return null;
80              }
81              else
82              {
83                  UMOEvent event = null;
84                  if (logger.isDebugEnabled())
85                  {
86                      logger.debug("Waiting for a message on " + endpoint.getEndpointURI().getAddress());
87                  }
88                  try
89                  {
90                      event = (UMOEvent)queue.poll(timeout);
91                  }
92                  catch (InterruptedException e)
93                  {
94                      logger.error("Failed to receive event from queue: " + endpoint.getEndpointURI());
95                  }
96                  if (event != null)
97                  {
98                      if (logger.isDebugEnabled())
99                      {
100                         logger.debug("Event received: " + event);
101                     }
102                     return event.getMessage();
103                 }
104                 else
105                 {
106                     if (logger.isDebugEnabled())
107                     {
108                         logger.debug("No event received after " + timeout + " ms");
109                     }
110                     return null;
111                 }
112             }
113         }
114         catch (Exception e)
115         {
116             throw e;
117         }
118     }
119 
120     protected void doDispatch(UMOEvent event) throws Exception
121     {
122         UMOEndpointURI endpointUri = event.getEndpoint().getEndpointURI();
123 
124         // because this is vm th emessage will not be serialized, even though it will
125         // be passed to a new thread.  so we need to generate a new copy of the message
126         // at this point
127         //event = event.newCopy();
128         // doesn't help needs to be later?
129 
130         if (endpointUri == null)
131         {
132             throw new DispatchException(
133                 CoreMessages.objectIsNull("Endpoint"), event.getMessage(), event.getEndpoint());
134         }
135         if (connector.isQueueEvents())
136         {
137             QueueSession session = connector.getQueueSession();
138             Queue queue = session.getQueue(endpointUri.getAddress());
139             queue.put(event);
140         }
141         else
142         {
143             VMMessageReceiver receiver = connector.getReceiver(event.getEndpoint().getEndpointURI());
144             if (receiver == null)
145             {
146                 logger.warn("No receiver for endpointUri: " + event.getEndpoint().getEndpointURI());
147                 return;
148             }
149 
150             if (event.isStreaming())
151             {
152                 PipedInputStream in = new PipedInputStream();
153                 PipedOutputStream out = new PipedOutputStream(in);
154                 UMOStreamMessageAdapter sma = connector.getStreamMessageAdapter(in, out);
155                 sma.write(event);
156             }
157             receiver.onEvent(event);
158         }
159         if (logger.isDebugEnabled())
160         {
161             logger.debug("dispatched Event on endpointUri: " + endpointUri);
162         }
163     }
164 
165     protected UMOMessage doSend(UMOEvent event) throws Exception
166     {
167         UMOMessage retMessage;
168         UMOEndpointURI endpointUri = event.getEndpoint().getEndpointURI();
169         VMMessageReceiver receiver = connector.getReceiver(endpointUri);
170         if (receiver == null)
171         {
172             if (connector.isQueueEvents())
173             {
174                 if (logger.isDebugEnabled())
175                 {
176                     logger.debug("Writing to queue as there is no receiver on connector: "
177                                  + connector.getName() + ", for endpointUri: "
178                                  + event.getEndpoint().getEndpointURI());
179                 }
180                 doDispatch(event);
181                 return null;
182             }
183             else
184             {
185                 throw new NoReceiverForEndpointException(
186                     VMMessages.noReceiverForEndpoint(connector.getName(), 
187                         event.getEndpoint().getEndpointURI()));
188             }
189         }
190         if (event.isStreaming())
191         {
192             PipedInputStream in = new PipedInputStream();
193             PipedOutputStream out = new PipedOutputStream(in);
194             UMOStreamMessageAdapter sma = connector.getStreamMessageAdapter(in, out);
195             sma.write(event);
196         }
197 
198         retMessage = (UMOMessage)receiver.onCall(event);
199 
200         if (event.isStreaming() && retMessage != null)
201         {
202             InputStream in;
203             if (retMessage.getPayload() instanceof InputStream)
204             {
205                 in = (InputStream)retMessage.getPayload();
206             }
207             else
208             {
209                 in = new ByteArrayInputStream((byte[])objectToByteArray.transform(retMessage.getPayload()));
210             }
211             UMOStreamMessageAdapter sma = connector.getStreamMessageAdapter(in, null);
212             retMessage = new MuleMessage(sma, retMessage);
213         }
214 
215         if (logger.isDebugEnabled())
216         {
217             logger.debug("sent event on endpointUri: " + event.getEndpoint().getEndpointURI());
218         }
219 
220         return retMessage;
221     }
222 
223     protected void doDispose()
224     {
225         // template method
226     }
227 
228     protected void doConnect() throws Exception
229     {
230         if (connector.isQueueEvents())
231         {
232             // use the default queue profile to configure this queue.
233             // Todo We may want to allow users to specify this at the connector level
234             MuleManager.getConfiguration().getQueueProfile().configureQueue(
235                 endpoint.getEndpointURI().getAddress());
236         }
237     }
238 
239     protected void doDisconnect() throws Exception
240     {
241         // template method
242     }
243 
244 }