View Javadoc

1   /*
2    * $Id: SystemStreamConnector.java 7963 2007-08-21 08:53:15Z 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.stream;
12  
13  import org.mule.config.i18n.MessageFactory;
14  import org.mule.umo.UMOComponent;
15  import org.mule.umo.UMOException;
16  import org.mule.umo.UMOMessage;
17  import org.mule.umo.endpoint.UMOEndpoint;
18  import org.mule.umo.endpoint.UMOImmutableEndpoint;
19  import org.mule.umo.lifecycle.InitialisationException;
20  import org.mule.umo.provider.UMOConnector;
21  import org.mule.umo.provider.UMOMessageReceiver;
22  import org.mule.util.StringUtils;
23  
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  
27  /**
28   * <code>SystemStreamConnector</code> connects to the System streams in and out by
29   * default and add some basic fuctionality for writing out prompt messages.
30   */
31  public class SystemStreamConnector extends StreamConnector
32  {
33  
34      private String promptMessage;
35      private String promptMessageCode = null;
36      private String resourceBundle = null;
37      private String outputMessage;
38      private String outputMessageCode = null;
39      private long messageDelayTime = 3000;
40      private boolean firstTime = true;
41  
42      public SystemStreamConnector()
43      {
44          super();
45          inputStream = System.in;
46          outputStream = System.out;
47      }
48  
49  
50      protected void doInitialise() throws InitialisationException
51      {
52          // template method, nothing to do
53      }
54  
55      protected void doDispose()
56      {
57          // Override as a no-op.
58          // The reason is System.in/out shouldn't be closed.
59          // It is valid for them to remain open (consider, e.g. tail -F).
60          // Trying to close System.in will result in I/O block, and
61          // available() will always return 0 bytes for System.in.
62  
63          // There is a scheme to get a ref to System.in via NIO,
64          // e.g. :
65          // FileInputStream fis = new FileInputStream(FileDescriptor.in);
66          // InputStream is = Channels.newInputStream(fis.getChannel);
67          //
68          // It is then possible to register a watchdog thread for the caller
69          // which will interrupt this (now wrapped with NIO) read() call.
70  
71          // Well, it isn't absolutely required for the reasons stated above,
72          // just following the KISS principle.
73      }
74  
75      protected void doConnect() throws Exception
76      {
77          // template method
78      }
79  
80      protected void doDisconnect() throws Exception
81      {
82          // template method
83      }
84  
85      public InputStream getInputStream()
86      {
87          return inputStream;
88      }
89  
90      public void doStart()
91      {
92          firstTime = false;
93      }
94  
95      public OutputStream getOutputStream()
96      {
97          return outputStream;
98      }
99  
100     /**
101      * @return Returns the promptMessage.
102      */
103     public String getPromptMessage()
104     {
105         if (StringUtils.isNotBlank(resourceBundle) && StringUtils.isNotBlank(promptMessageCode))
106         {
107             return SystemStreamMessageFactory.getString(resourceBundle, promptMessageCode);
108         }
109 
110         return promptMessage;
111     }
112 
113     /**
114      * @param promptMessage The promptMessage to set.
115      */
116     public void setPromptMessage(String promptMessage)
117     {
118         this.promptMessage = promptMessage;
119     }
120 
121     /**
122      * @return Returns the promptMessageCode.
123      */
124     public String getPromptMessageCode()
125     {
126         return promptMessageCode;
127     }
128 
129     /**
130      * @param promptMessageCode The promptMessageCode to set.
131      */
132     public void setPromptMessageCode(String promptMessageCode)
133     {
134         this.promptMessageCode = promptMessageCode;
135     }
136 
137     /**
138      * @return Returns the resourceBundle.
139      */
140     public String getResourceBundle()
141     {
142         return resourceBundle;
143     }
144 
145     /**
146      * @param resourceBundle The resourceBundle to read the message from. This property is 
147      * only needed in conjunction with promptMessageCode or outputMessageCode.
148      */
149     public void setResourceBundle(String resourceBundle)
150     {
151         this.resourceBundle = resourceBundle;
152     }
153 
154     /**
155      * @return Returns the outputMessage.
156      */
157     public String getOutputMessage()
158     {
159         if (StringUtils.isNotBlank(resourceBundle) && StringUtils.isNotBlank(outputMessageCode))
160         {
161             return SystemStreamMessageFactory.getString(resourceBundle, outputMessageCode);
162         }
163 
164         return outputMessage;
165     }
166 
167     /**
168      * @param outputMessage The outputMessage to set.
169      */
170     public void setOutputMessage(String outputMessage)
171     {
172         this.outputMessage = outputMessage;
173     }
174 
175     /**
176      * @return Returns the outputMessageCode.
177      */
178     public String getOutputMessageCode()
179     {
180         return outputMessageCode;
181     }
182 
183     /**
184      * @param outputMessageCode The outputMessageCode to set.
185      */
186     public void setOutputMessageCode(String outputMessageCode)
187     {
188         this.outputMessageCode = outputMessageCode;
189     }
190 
191     public UMOConnector getConnector()
192     {
193         return this;
194     }
195 
196     public UMOMessageReceiver registerListener(UMOComponent component, UMOEndpoint endpoint) throws Exception
197     {
198         if (receivers.size() > 0)
199         {
200             throw new UnsupportedOperationException(
201                 "You can only register one listener per system stream connector");
202         }
203         UMOMessageReceiver receiver = super.registerListener(component, endpoint);
204         return receiver;
205     }
206 
207     public long getMessageDelayTime()
208     {
209         if (firstTime)
210         {
211             return messageDelayTime + 4000;
212         }
213         else
214         {
215             return messageDelayTime;
216         }
217     }
218 
219     public void setMessageDelayTime(long messageDelayTime)
220     {
221         this.messageDelayTime = messageDelayTime;
222     }
223 
224 
225     public OutputStream getOutputStream(UMOImmutableEndpoint endpoint, UMOMessage message) throws UMOException
226     {
227         OutputStream out;
228         String streamName = endpoint.getEndpointURI().getAddress();
229 
230         if (STREAM_SYSTEM_OUT.equalsIgnoreCase(streamName))
231         {
232             out = System.out;
233         }
234         else if (STREAM_SYSTEM_ERR.equalsIgnoreCase(streamName))
235         {
236             out = System.err;
237         }
238         else
239         {
240             out = getOutputStream();
241         }
242         return out;
243     }
244     
245     /**
246      * {@link SystemStreamConnector} needs a way to access other modules' messages. The default
247      * way to access messages is by using {@link MessageFactory} which itself is not meant to be used 
248      * directly. In order not to soften this requiement this private subclass offers access to
249      * {@link MessageFactory}'s methods.
250      */
251     private static class SystemStreamMessageFactory extends MessageFactory
252     {
253         protected static String getString(String bundlePath, String code)
254         {
255             return MessageFactory.getString(bundlePath, Integer.parseInt(code));
256         }
257     }
258 }