View Javadoc

1   /*
2    * $Id: DeferredOutputStream.java 10565 2008-01-28 14:30:45Z holger $
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  package org.mule.impl.model.streaming;
11  
12  import org.mule.config.i18n.CoreMessages;
13  import org.mule.providers.streaming.StreamMessageAdapter;
14  import org.mule.umo.MessagingException;
15  import org.mule.umo.UMODescriptor;
16  import org.mule.umo.UMOEventContext;
17  import org.mule.umo.UMOException;
18  import org.mule.umo.endpoint.UMOEndpoint;
19  import org.mule.umo.endpoint.UMOEndpointURI;
20  import org.mule.umo.routing.UMOOutboundRouter;
21  import org.mule.umo.routing.UMOOutboundRouterCollection;
22  
23  import java.io.BufferedOutputStream;
24  import java.io.IOException;
25  import java.io.OutputStream;
26  import java.util.Iterator;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  /**
32   * This outputStream allows a stream to be choosen after this has been created.  It is used by
33   * Mule when using streaming to pass to the Streaming component. The actual output stream is
34   * choosen at the point where the first byte is written. At this point an outbound router can be
35   * chosen and values set on the event context can affect which stream is choosen.
36   */
37  public class DeferredOutputStream extends OutputStream
38  {
39      
40      protected final Log logger = LogFactory.getLog(DeferredOutputStream.class);
41      private UMOEventContext event;
42      private OutputStream out = null;
43      private int buffer = 0;
44  
45  
46      public DeferredOutputStream(UMOEventContext event)
47      {
48          this.event = event;
49      }
50  
51  
52      public DeferredOutputStream(UMOEventContext event, int buffer)
53      {
54          this.event = event;
55          this.buffer = buffer;
56      }
57  
58      public void write(int b) throws IOException
59      {
60          if (out == null)
61          {
62              out = getOutputStream();
63          }
64          out.write(b);
65      }
66  
67      // @Override
68      public void write(byte b[]) throws IOException
69      {
70          if (out == null)
71          {
72              out = getOutputStream();
73          }
74          out.write(b);
75      }
76  
77      // @Override
78      public void write(byte b[], int off, int len) throws IOException 
79      {
80           if (out == null) 
81           {
82               out = getOutputStream();
83           }
84           out.write(b, off, len);
85       }
86  
87      // @Override    
88      public void flush() throws IOException
89      {
90          //out could be null if the stream hasn't been written to yet
91          if (out != null)
92          {
93              logger.debug("flushing deferred output stream");
94              out.flush();
95          }
96          else
97          {
98              logger.debug("deferred output stream unflushed");
99          }
100     }
101 
102     // @Override
103     public void close() throws IOException
104     {
105         //out could be null if the stream hasn't been written to yet
106         if (out != null)
107         {
108             out.close();
109         }
110     }
111 
112     protected OutputStream getOutputStream() throws IOException
113     {
114         StreamMessageAdapter adapter = (StreamMessageAdapter) event.getMessage().getAdapter();
115         OutputStream temp = getOutputStreamFromRouter();
116         if (temp == null)
117         {
118             temp = adapter.getOutputStream();
119         }
120         if (temp == null)
121         {
122             throw new IOException("No output stream was found for the current event: " + event);
123         }
124         else if (getBuffer() > 0)
125         {
126             return new BufferedOutputStream(temp, getBuffer());
127         }
128         else
129         {
130             return temp;
131         }
132     }
133 
134 
135     public int getBuffer()
136     {
137         return buffer;
138     }
139 
140     public void setBuffer(int buffer)
141     {
142         if (out != null)
143         {
144             throw new IllegalStateException("The stream buffer cannot be set after the stream has been written to");
145         }
146         this.buffer = buffer;
147     }
148 
149     protected OutputStream getOutputStreamFromRouter() throws IOException
150     {
151         UMODescriptor descriptor = event.getComponentDescriptor();
152         UMOEndpointURI endpoint = event.getEndpointURI();
153 
154         UMOOutboundRouterCollection messageRouter = descriptor.getOutboundRouter();
155         if (messageRouter.hasEndpoints())
156         {
157             for (Iterator iterator = messageRouter.getRouters().iterator(); iterator.hasNext();)
158             {
159                 UMOOutboundRouter router = (UMOOutboundRouter) iterator.next();
160                 boolean match = false;
161                 try
162                 {
163                     match = router.isMatch(event.getMessage());
164                 }
165                 catch (MessagingException e)
166                 {
167                     throw (IOException) new IOException(e.toString()).initCause(e);
168                 }
169                 if (match)
170                 {
171                     if (router.getEndpoints().size() != 1)
172                     {
173                         throw new IOException(
174                             CoreMessages.streamingComponentMustHaveOneEndpoint(descriptor.getName()).toString());
175                     }
176                     else
177                     {
178                         UMOEndpoint ep = (UMOEndpoint) router.getEndpoints().get(0);
179                         try
180                         {
181                             return ep.getConnector().getOutputStream(ep, event.getMessage());
182                         }
183                         catch (UMOException e)
184                         {
185                             throw (IOException) new IOException(
186                                 CoreMessages.streamingFailedForEndpoint(endpoint.toString()).toString()).initCause(e);
187                         }
188                     }
189                 }
190             }
191             //If we got to here there are no matching outbound Routers
192             throw new IOException(
193                 CoreMessages.streamingComponentMustHaveOneEndpoint(descriptor.getName()).toString());
194         }
195         if (logger.isDebugEnabled())
196         {
197             logger.debug("there are no outbound endpoints configured on this component, the otput stream provided from the message adapter will be used");
198         }
199 
200         //Use the response output stream on the StreamingMessage adapter
201         return null;
202     }
203 }