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.converter.stream;
018    
019    import java.io.IOException;
020    import java.io.InputStream;
021    import java.io.Reader;
022    import java.io.StringReader;
023    
024    import javax.xml.transform.TransformerException;
025    import javax.xml.transform.sax.SAXSource;
026    import javax.xml.transform.stream.StreamSource;
027    
028    import org.apache.camel.Converter;
029    import org.apache.camel.Exchange;
030    import org.apache.camel.StreamCache;
031    import org.apache.camel.converter.jaxp.BytesSource;
032    import org.apache.camel.converter.jaxp.StringSource;
033    import org.apache.camel.util.IOHelper;
034    import org.apache.commons.logging.Log;
035    import org.apache.commons.logging.LogFactory;
036    
037    /**
038     * A set of {@link Converter} methods for wrapping stream-based messages in a {@link StreamCache}
039     * implementation to ensure message re-readability (eg multicasting, retrying)
040     */
041    @Converter
042    public class StreamCacheConverter {
043        private static final transient Log LOG = LogFactory.getLog(StreamCacheConverter.class);
044    
045        @Converter
046        public StreamCache convertToStreamCache(StreamSource source, Exchange exchange) throws IOException {
047            return new StreamSourceCache(source, exchange);
048        }
049        
050        @Converter
051        public StreamCache convertToStreamCache(StringSource source) {
052            //no need to do stream caching for a StringSource
053            return null;
054        }
055        
056        @Converter
057        public StreamCache convertToStreamCache(BytesSource source) {
058            //no need to do stream caching for a BytesSource
059            return null;
060        }
061        
062        @Converter
063        public StreamCache convertToStreamCache(SAXSource source, Exchange exchange) throws TransformerException {
064            String data = exchange.getContext().getTypeConverter().convertTo(String.class, source);
065            return new SourceCache(data);
066        }
067    
068        @Converter
069        public StreamCache convertToStreamCache(InputStream stream, Exchange exchange) throws IOException {
070            // set up CachedOutputStream with the properties
071            CachedOutputStream cos = new CachedOutputStream(exchange.getContext().getProperties());
072            IOHelper.copyAndCloseInput(stream, cos);       
073            return cos.getStreamCache();
074        }
075    
076        @Converter
077        public StreamCache convertToStreamCache(Reader reader, Exchange exchange) throws IOException {
078            String data = exchange.getContext().getTypeConverter().convertTo(String.class, reader);
079            return new ReaderCache(data);
080        }
081    
082        /*
083         * {@link StreamCache} implementation for {@link Source}s
084         */
085        private class SourceCache extends StringSource implements StreamCache {
086    
087            private static final long serialVersionUID = 4147248494104812945L;
088    
089            public SourceCache() {
090            }
091    
092            public SourceCache(String text) {
093                super(text);
094            }
095    
096            public void reset() {
097                // do nothing here
098            }
099    
100        }
101        
102        /*
103         * {@link StreamCache} implementation for Cache the StreamSource {@link StreamSource}s
104         */
105        private class StreamSourceCache extends StreamSource implements StreamCache {
106            StreamCache streamCache;
107            ReaderCache readCache;
108            
109            public StreamSourceCache(StreamSource source, Exchange exchange) throws IOException {
110                if (source.getInputStream() != null) {
111                    // set up CachedOutputStream with the properties
112                    CachedOutputStream cos = new CachedOutputStream(exchange.getContext().getProperties());
113                    IOHelper.copyAndCloseInput(source.getInputStream(), cos);
114                    streamCache = cos.getStreamCache();
115                    setInputStream((InputStream)streamCache);
116                    setSystemId(source.getSystemId());
117                }
118                if (source.getReader() != null) {
119                    String data = exchange.getContext().getTypeConverter().convertTo(String.class, source.getReader());
120                    readCache = new ReaderCache(data);
121                    setReader(readCache);
122                }
123            }
124    
125            public void reset() {
126                if (streamCache != null) {
127                    streamCache.reset();
128                }
129                if (readCache != null) {
130                    readCache.reset();
131                }            
132            }
133            
134        }
135          
136        private class ReaderCache extends StringReader implements StreamCache {
137    
138            public ReaderCache(String s) {
139                super(s);
140            }
141    
142            public void reset() {
143                try {
144                    super.reset();
145                } catch (IOException e) {
146                    LOG.warn("Cannot reset cache", e);
147                }
148            }
149    
150            public void close() {
151                // Do not release the string for caching
152            }
153    
154        }
155        
156        
157    
158    
159    }