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.BufferedWriter;
020 import java.io.File;
021 import java.io.FileOutputStream;
022 import java.io.IOException;
023 import java.io.OutputStream;
024 import java.io.OutputStreamWriter;
025 import java.io.Writer;
026 import java.net.URL;
027 import java.net.URLConnection;
028 import java.nio.charset.Charset;
029 import java.util.Arrays;
030 import java.util.List;
031
032 import org.apache.camel.CamelExchangeException;
033 import org.apache.camel.Exchange;
034 import org.apache.camel.impl.DefaultProducer;
035 import org.apache.camel.util.ObjectHelper;
036 import org.apache.commons.logging.Log;
037 import org.apache.commons.logging.LogFactory;
038
039 /**
040 * Producer that can write to streams
041 */
042 public class StreamProducer extends DefaultProducer {
043
044 private static final transient Log LOG = LogFactory.getLog(StreamProducer.class);
045 private static final String TYPES = "out,err,file,header,url";
046 private static final String INVALID_URI = "Invalid uri, valid form: 'stream:{" + TYPES + "}'";
047 private static final List<String> TYPES_LIST = Arrays.asList(TYPES.split(","));
048 private OutputStream outputStream = System.out;
049 private StreamEndpoint endpoint;
050 private String uri;
051
052 public StreamProducer(StreamEndpoint endpoint, String uri) throws Exception {
053 super(endpoint);
054 this.endpoint = endpoint;
055 validateUri(uri);
056 }
057
058 @Override
059 public void doStop() throws Exception {
060 // important: do not close the stream as it will close the standard system.out etc.
061 super.doStop();
062 }
063
064 public void process(Exchange exchange) throws Exception {
065 delay(endpoint.getDelay());
066
067 if ("out".equals(uri)) {
068 outputStream = System.out;
069 } else if ("err".equals(uri)) {
070 outputStream = System.err;
071 } else if ("file".equals(uri)) {
072 outputStream = resolveStreamFromFile();
073 } else if ("header".equals(uri)) {
074 outputStream = resolveStreamFromHeader(exchange.getIn().getHeader("stream"), exchange);
075 } else if ("url".equals(uri)) {
076 outputStream = resolveStreamFromUrl();
077 }
078
079 writeToStream(exchange);
080 }
081
082 private OutputStream resolveStreamFromUrl() throws IOException {
083 String u = endpoint.getUrl();
084 ObjectHelper.notEmpty(u, "url");
085 if (LOG.isDebugEnabled()) {
086 LOG.debug("About to write to url: " + u);
087 }
088
089 URL url = new URL(u);
090 URLConnection c = url.openConnection();
091 return c.getOutputStream();
092 }
093
094 private OutputStream resolveStreamFromFile() throws IOException {
095 String fileName = endpoint.getFileName();
096 ObjectHelper.notEmpty(fileName, "fileName");
097 if (LOG.isDebugEnabled()) {
098 LOG.debug("About to write to file: " + fileName);
099 }
100 File f = new File(fileName);
101 // will create a new file if missing or append to existing
102 f.createNewFile();
103 return new FileOutputStream(f);
104 }
105
106 private OutputStream resolveStreamFromHeader(Object o, Exchange exchange) throws CamelExchangeException {
107 return exchange.getContext().getTypeConverter().convertTo(OutputStream.class, o);
108 }
109
110 private void delay(long ms) throws InterruptedException {
111 if (ms == 0) {
112 return;
113 }
114 if (LOG.isTraceEnabled()) {
115 LOG.trace("Delaying " + ms + " millis");
116 }
117 Thread.sleep(ms);
118 }
119
120 private void writeToStream(Exchange exchange) throws IOException, CamelExchangeException {
121 Object body = exchange.getIn().getBody();
122
123 // if not a string then try as byte array first
124 if (!(body instanceof String)) {
125 byte[] bytes = exchange.getIn().getBody(byte[].class);
126 if (bytes != null) {
127 if (LOG.isDebugEnabled()) {
128 LOG.debug("Writing as byte[]: " + bytes + " to " + outputStream);
129 }
130 outputStream.write(bytes);
131 return;
132 }
133 }
134
135 // okay now fallback to mandatory converterable to string
136 String s = exchange.getIn().getMandatoryBody(String.class);
137 Charset charset = endpoint.getCharset();
138 Writer writer = new OutputStreamWriter(outputStream, charset);
139 BufferedWriter bw = new BufferedWriter(writer);
140 if (LOG.isDebugEnabled()) {
141 LOG.debug("Writing as text: " + body + " to " + outputStream + " using encoding:" + charset);
142 }
143 bw.write(s);
144 bw.write("\n");
145 bw.flush();
146 // important: do not close the writer as it will close the standard system.out etc.
147 }
148
149 private void validateUri(String uri) throws Exception {
150 String[] s = uri.split(":");
151 if (s.length < 2) {
152 throw new IllegalArgumentException(INVALID_URI);
153 }
154 String[] t = s[1].split("\\?");
155
156 if (t.length < 1) {
157 throw new IllegalArgumentException(INVALID_URI);
158 }
159 this.uri = t[0].trim();
160 if (this.uri.startsWith("//")) {
161 this.uri = this.uri.substring(2);
162 }
163
164 if (!TYPES_LIST.contains(this.uri)) {
165 throw new IllegalArgumentException(INVALID_URI);
166 }
167 }
168
169 }
170