001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.component.stream;
018
019 import java.io.BufferedReader;
020 import java.io.File;
021 import java.io.FileInputStream;
022 import java.io.IOException;
023 import java.io.InputStream;
024 import java.io.InputStreamReader;
025 import java.net.URL;
026 import java.net.URLConnection;
027 import java.nio.charset.Charset;
028 import java.util.Arrays;
029 import java.util.List;
030 import java.util.concurrent.ExecutorService;
031
032 import org.apache.camel.Exchange;
033 import org.apache.camel.Message;
034 import org.apache.camel.Processor;
035 import org.apache.camel.impl.DefaultConsumer;
036 import org.apache.camel.impl.DefaultMessage;
037 import org.apache.camel.util.ObjectHelper;
038 import org.apache.camel.util.concurrent.ExecutorServiceHelper;
039 import org.apache.commons.logging.Log;
040 import org.apache.commons.logging.LogFactory;
041
042 /**
043 * Consumer that can read from streams
044 */
045 public class StreamConsumer extends DefaultConsumer implements Runnable {
046
047 private static final transient Log LOG = LogFactory.getLog(StreamConsumer.class);
048 private static final String TYPES = "in,file,url";
049 private static final String INVALID_URI = "Invalid uri, valid form: 'stream:{" + TYPES + "}'";
050 private static final List<String> TYPES_LIST = Arrays.asList(TYPES.split(","));
051 private ExecutorService executor;
052 private InputStream inputStream = System.in;
053 private StreamEndpoint endpoint;
054 private String uri;
055 private boolean initialPromptDone;
056
057 public StreamConsumer(StreamEndpoint endpoint, Processor processor, String uri) throws Exception {
058 super(endpoint, processor);
059 this.endpoint = endpoint;
060 this.uri = uri;
061 validateUri(uri);
062 }
063
064 @Override
065 protected void doStart() throws Exception {
066 super.doStart();
067
068 if ("in".equals(uri)) {
069 inputStream = System.in;
070 } else if ("file".equals(uri)) {
071 inputStream = resolveStreamFromFile();
072 } else if ("url".equals(uri)) {
073 inputStream = resolveStreamFromUrl();
074 }
075
076 executor = ExecutorServiceHelper.newSingleThreadExecutor(endpoint.getEndpointUri(), true);
077 executor.execute(this);
078 }
079
080 @Override
081 public void doStop() throws Exception {
082 // important: do not close the stream as it will close the standard
083 // system.in etc.
084 if (executor != null) {
085 executor.shutdownNow();
086 executor = null;
087 }
088 super.doStop();
089 }
090
091 public void run() {
092 try {
093 readFromStream();
094 } catch (Exception e) {
095 getExceptionHandler().handleException(e);
096 }
097 }
098
099 private void readFromStream() throws Exception {
100 Charset charset = endpoint.getCharset();
101 BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, charset));
102 String line;
103
104 if (endpoint.isScanStream()) {
105 // repeat scanning from stream
106 while (isRunAllowed()) {
107 line = br.readLine();
108 if (LOG.isTraceEnabled()) {
109 LOG.trace("Read line: " + line);
110 }
111 boolean eos = line == null;
112 if (!eos && isRunAllowed()) {
113 processLine(line);
114 }
115 try {
116 Thread.sleep(endpoint.getScanStreamDelay());
117 } catch (InterruptedException e) {
118 Thread.currentThread().interrupt();
119 break;
120 }
121 }
122 } else {
123 // regular read stream once until end of stream
124 boolean eos = false;
125 while (!eos && isRunAllowed()) {
126 if (endpoint.getPromptMessage() != null) {
127 doPromptMessage();
128 }
129
130 line = br.readLine();
131 if (LOG.isTraceEnabled()) {
132 LOG.trace("Read line: " + line);
133 }
134 eos = line == null;
135 if (!eos && isRunAllowed()) {
136 processLine(line);
137 }
138 }
139 }
140 // important: do not close the reader as it will close the standard system.in etc.
141 }
142
143 /**
144 * Strategy method for processing the line
145 */
146 protected void processLine(Object line) throws Exception {
147 Exchange exchange = endpoint.createExchange();
148
149 Message msg = new DefaultMessage();
150 msg.setBody(line);
151 exchange.setIn(msg);
152
153 getProcessor().process(exchange);
154 }
155
156 /**
157 * Strategy method for prompting the prompt message
158 */
159 protected void doPromptMessage() {
160 long delay = 0;
161
162 if (!initialPromptDone && endpoint.getInitialPromptDelay() > 0) {
163 initialPromptDone = true;
164 delay = endpoint.getInitialPromptDelay();
165 } else if (endpoint.getPromptDelay() > 0) {
166 delay = endpoint.getPromptDelay();
167 }
168
169 if (delay > 0) {
170 try {
171 Thread.sleep(delay);
172 } catch (InterruptedException e) {
173 Thread.currentThread().interrupt();
174 }
175 }
176
177 System.out.print(endpoint.getPromptMessage());
178 }
179
180 private InputStream resolveStreamFromUrl() throws IOException {
181 String u = endpoint.getUrl();
182 ObjectHelper.notEmpty(u, "url");
183 if (LOG.isDebugEnabled()) {
184 LOG.debug("About to read from url: " + u);
185 }
186
187 URL url = new URL(u);
188 URLConnection c = url.openConnection();
189 return c.getInputStream();
190 }
191
192 private InputStream resolveStreamFromFile() throws IOException {
193 String fileName = endpoint.getFileName();
194 ObjectHelper.notEmpty(fileName, "fileName");
195
196 FileInputStream fileStream;
197
198 File file = new File(fileName);
199
200 if (LOG.isDebugEnabled()) {
201 LOG.debug("File to be scanned : " + file.getName() + ", path : " + file.getAbsolutePath());
202 }
203
204 if (file.canRead()) {
205 fileStream = new FileInputStream(file);
206 } else {
207 throw new IllegalArgumentException(INVALID_URI);
208 }
209
210 return fileStream;
211 }
212
213 private void validateUri(String uri) throws IllegalArgumentException {
214 String[] s = uri.split(":");
215 if (s.length < 2) {
216 throw new IllegalArgumentException(INVALID_URI);
217 }
218 String[] t = s[1].split("\\?");
219
220 if (t.length < 1) {
221 throw new IllegalArgumentException(INVALID_URI);
222 }
223
224 this.uri = t[0].trim();
225 if (this.uri.startsWith("//")) {
226 this.uri = this.uri.substring(2);
227 }
228
229 if (!TYPES_LIST.contains(this.uri)) {
230 throw new IllegalArgumentException(INVALID_URI);
231 }
232 }
233
234 }