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.stdio;
8   
9   import org.mule.api.MuleMessage;
10  import org.mule.api.construct.FlowConstruct;
11  import org.mule.api.endpoint.InboundEndpoint;
12  import org.mule.api.lifecycle.CreateException;
13  import org.mule.api.transport.Connector;
14  import org.mule.transport.AbstractPollingMessageReceiver;
15  
16  import java.io.InputStream;
17  import java.io.PrintStream;
18  import java.io.PushbackInputStream;
19  
20  import org.apache.commons.lang.BooleanUtils;
21  import org.apache.commons.lang.SystemUtils;
22  
23  /**
24   * <code>StdioMessageReceiver</code> is a listener for events from Mule components
25   * which then simply passes the events on to the target components.
26   */
27  public class StdioMessageReceiver extends AbstractPollingMessageReceiver
28  {
29      public static final int DEFAULT_BUFFER_SIZE = 4096;
30  
31      private int bufferSize = DEFAULT_BUFFER_SIZE;
32      private InputStream inputStream;
33      private StdioConnector connector;
34  
35      private boolean sendStream;
36  
37      public StdioMessageReceiver(Connector connector,
38                                  FlowConstruct flowConstruct,
39                                  InboundEndpoint endpoint,
40                                  long checkFrequency) throws CreateException
41      {
42          super(connector, flowConstruct, endpoint);
43          this.setFrequency(checkFrequency);
44  
45          this.connector = (StdioConnector) connector;
46          String streamName = endpoint.getEndpointURI().getAddress();
47          if (StdioConnector.STREAM_SYSTEM_IN.equalsIgnoreCase(streamName))
48          {
49              inputStream = System.in;
50          }
51          else
52          {
53              inputStream = this.connector.getInputStream();
54          }
55  
56          // apply connector-specific properties
57          if (connector instanceof PromptStdioConnector)
58          {
59              PromptStdioConnector ssc = (PromptStdioConnector) connector;
60  
61              String promptMessage = (String) endpoint.getProperties().get("promptMessage");
62              if (promptMessage != null)
63              {
64                  ssc.setPromptMessage(promptMessage);
65              }
66          }
67          
68          this.sendStream = BooleanUtils.toBoolean((String) endpoint.getProperties().get("sendStream"));
69      }
70  
71      @Override
72      protected void doDispose()
73      {
74          // template method
75      }
76  
77      @Override
78      public void doConnect() throws Exception
79      {
80          if (connector instanceof PromptStdioConnector)
81          {
82              PromptStdioConnector ssc = (PromptStdioConnector) connector;
83              DelayedMessageWriter writer = new DelayedMessageWriter(ssc);
84              writer.start();
85          }
86      }
87  
88      @Override
89      public void doDisconnect() throws Exception
90      {
91          // noop
92      }
93  
94      @Override
95      public void poll()
96      {
97          String encoding = endpoint.getEncoding();
98          try
99          {
100             if (sendStream)
101             {
102                 PushbackInputStream in = new PushbackInputStream(inputStream);
103 
104                 //Block until we have some data
105                 int i = in.read();
106                 //Roll back our read
107                 in.unread(i);
108                 MuleMessage message = createMuleMessage(in, encoding);
109                 routeMessage(message);
110             }
111             else
112             {
113                 byte[] inputBuffer = new byte[bufferSize];
114                 int len = inputStream.read(inputBuffer);
115 
116                 if (len == -1)
117                 {
118                     return;
119                 }
120 
121                 StringBuffer fullBuffer = new StringBuffer(bufferSize);
122                 while (len > 0)
123                 {
124                     fullBuffer.append(new String(inputBuffer, 0, len));
125                     len = 0; // mark as read
126                     if (inputStream.available() > 0)
127                     {
128                         len = inputStream.read(inputBuffer);
129                     }
130                 }
131 
132                 // Each line is a separate message
133                 String[] lines = fullBuffer.toString().split(SystemUtils.LINE_SEPARATOR);
134                 for (int i = 0; i < lines.length; ++i)
135                 {                
136                     MuleMessage message = createMuleMessage(lines[i], encoding);
137                     routeMessage(message);
138                 }
139             }
140 
141             doConnect();
142         }
143         catch (Exception e)
144         {
145             getConnector().getMuleContext().getExceptionListener().handleException(e);
146         }
147     }
148 
149     public InputStream getInputStream()
150     {
151         return inputStream;
152     }
153 
154     public void setInputStream(InputStream inputStream)
155     {
156         this.inputStream = inputStream;
157     }
158 
159     public int getBufferSize()
160     {
161         return bufferSize;
162     }
163 
164     public void setBufferSize(int bufferSize)
165     {
166         this.bufferSize = bufferSize;
167     }
168 
169     private class DelayedMessageWriter extends Thread
170     {
171         private long delay = 0;
172         private PromptStdioConnector ssc;
173 
174         public DelayedMessageWriter(PromptStdioConnector ssc)
175         {
176             this.delay = ssc.getMessageDelayTime();
177             this.ssc = ssc;
178         }
179 
180         @Override
181         public void run()
182         {
183             if (delay > 0)
184             {
185                 try
186                 {
187                     // Allow all other console message to be printed out first
188                     sleep(delay);
189                 }
190                 catch (InterruptedException e1)
191                 {
192                     // ignore
193                 }
194             }
195             ((PrintStream) ssc.getOutputStream()).println();
196             ((PrintStream) ssc.getOutputStream()).print(ssc.getPromptMessage());
197         }
198     }
199 }