001    package com.mockrunner.util.common;
002    
003    import java.io.BufferedReader;
004    import java.io.ByteArrayInputStream;
005    import java.io.ByteArrayOutputStream;
006    import java.io.IOException;
007    import java.io.InputStream;
008    import java.io.Reader;
009    import java.io.StringReader;
010    import java.util.ArrayList;
011    import java.util.Arrays;
012    import java.util.List;
013    
014    import org.apache.commons.logging.Log;
015    import org.apache.commons.logging.LogFactory;
016    
017    import com.mockrunner.base.NestedApplicationException;
018    
019    /**
020     * Simple util class for manipulating streams
021     */
022    public class StreamUtil
023    {
024        private final static Log log = LogFactory.getLog(StreamUtil.class);
025        
026        /**
027         * Returns the contents of the input stream as byte array.
028         * @param stream the <code>InputStream</code>
029         * @return the stream content as byte array
030         */
031        public static byte[] getStreamAsByteArray(InputStream stream)
032        {
033            return getStreamAsByteArray(stream, -1);
034        }
035        
036        /**
037         * Returns the contents of the input stream as byte array.
038         * @param stream the <code>InputStream</code>
039         * @param length the number of bytes to copy, if length < 0,
040         *        the number is unlimited
041         * @return the stream content as byte array
042         */
043        public static byte[] getStreamAsByteArray(InputStream stream, int length)
044        {
045            if(length == 0) return new byte[0];
046            boolean checkLength = true;
047            if(length < 0)
048            {
049                length = Integer.MAX_VALUE;
050                checkLength = false;
051            }
052            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
053            try
054            {
055                int nextValue = stream.read();
056                if(checkLength) length--;
057                while(-1 != nextValue && length >= 0)
058                {
059                    byteStream.write(nextValue);
060                    nextValue = stream.read();
061                    if(checkLength) length--;
062                }
063            }
064            catch(IOException exc)
065            {
066                log.error("Exception while reading from stream", exc);
067            }
068            return byteStream.toByteArray();
069        }
070        
071        /**
072         * Returns the contents of the reader as a string.
073         * @param reader the <code>Reader</code>
074         * @return the reader content as <code>String</code>
075         */
076        public static String getReaderAsString(Reader reader)
077        {
078            return getReaderAsString(reader, -1);
079        }
080        
081        /**
082         * Returns the contents of the reader as a string.
083         * @param reader the <code>Reader</code>
084         * @param length the number of chars to copy, if length < 0,
085         *        the number is unlimited
086         * @return the reader content as <code>String</code>
087         */
088        public static String getReaderAsString(Reader reader, int length)
089        {
090            if(length == 0) return "";
091            boolean checkLength = true;
092            if(length < 0)
093            {
094                length = Integer.MAX_VALUE;
095                checkLength = false;
096            }
097            StringBuffer buffer = new StringBuffer();
098            try
099            {
100                int nextValue = reader.read();
101                if(checkLength) length--;
102                while(-1 != nextValue && length >= 0)
103                {
104                    buffer.append((char)nextValue);
105                    nextValue = reader.read();
106                    if(checkLength) length--;
107                }
108            }
109            catch(IOException exc)
110            {
111                log.error("Exception while reading from reader", exc);
112            }
113            return buffer.toString();
114        }
115        
116        /**
117         * Returns a copy of the specified stream. If the specified stream supports
118         * marking, it will be reseted after the copy.
119         * @param sourceStream the stream to copy
120         * @return a copy of the stream
121         */
122        public static InputStream copyStream(InputStream sourceStream)
123        {
124            try
125            {
126                if(sourceStream.markSupported()) sourceStream.mark(sourceStream.available());
127                byte[] sourceData = getStreamAsByteArray(sourceStream);
128                if(sourceStream.markSupported()) sourceStream.reset();
129                return new ByteArrayInputStream(sourceData);
130            }
131            catch(IOException exc)
132            {
133                log.error("Exception while copying stream", exc);
134                return null;
135            }
136        }
137      
138        /**
139         * Returns a copy of the specified reader. If the specified reader supports
140         * marking, it will be reseted after the copy.
141         * @param sourceReader the stream to reader
142         * @return a copy of the reader
143         */
144        public static Reader copyReader(Reader sourceReader)
145        {
146            try
147            {
148                if(sourceReader.markSupported()) sourceReader.mark(Integer.MAX_VALUE);
149                String sourceData = getReaderAsString(sourceReader);
150                if(sourceReader.markSupported()) sourceReader.reset();
151                return new StringReader(sourceData);
152            }
153            catch(IOException exc)
154            {
155                log.error("Exception while copying reader", exc);
156                return null;
157            }
158        }
159        
160        /**
161         * Compares the content of the streams. If the streams support
162         * marking, they will be reseted after the comparison.
163         * @param sourceStream the source stream
164         * @param targetStream the target stream
165         * @return <code>true</code>, if the streams are identical, <code>false</code> otherwise
166         */
167        public static boolean compareStreams(InputStream sourceStream, InputStream targetStream)
168        {
169            try
170            {
171                if(sourceStream.markSupported()) sourceStream.mark(sourceStream.available());
172                if(targetStream.markSupported()) targetStream.mark(targetStream.available());
173                byte[] sourceArray = getStreamAsByteArray(sourceStream);
174                byte[] targetArray = getStreamAsByteArray(targetStream);
175                if(sourceStream.markSupported()) sourceStream.reset();
176                if(targetStream.markSupported()) targetStream.reset();
177                return Arrays.equals(sourceArray, targetArray);
178            }
179            catch(IOException exc)
180            {
181                log.error("Exception while comparing streams", exc);
182                return false;
183            }
184        }
185        
186        /**
187         * Compares the content of the readers. If the readers support
188         * marking, they will be reseted after the comparison.
189         * @param sourceReader the source stream
190         * @param targetReader the target stream
191         * @return <code>true</code>, if the streams are identical, <code>false</code> otherwise
192         */
193        public static boolean compareReaders(Reader sourceReader, Reader targetReader)
194        {
195            try
196            {
197                if(sourceReader.markSupported()) sourceReader.mark(Integer.MAX_VALUE);
198                if(targetReader.markSupported()) targetReader.mark(Integer.MAX_VALUE);
199                String sourceString = getReaderAsString(sourceReader);
200                String targetString = getReaderAsString(targetReader);
201                if(sourceReader.markSupported()) sourceReader.reset();
202                if(targetReader.markSupported()) targetReader.reset();
203                return sourceString.equals(targetString);
204            }
205            catch(IOException exc)
206            {
207                log.error("Exception while comparing readers", exc);
208                return false;
209            }
210        }
211        
212        /**
213         * Reads the lines from the specified reader and adds them to a <code>List</code>.
214         * @param reader the reader
215         * @return the <code>List</code> with the lines
216         */
217        public static List getLinesFromReader(Reader reader)
218        {
219            List resultList = new ArrayList();
220            try
221            {
222                BufferedReader bufferedReader = new BufferedReader(reader);
223                String line = bufferedReader.readLine();
224                while(line != null)
225                {
226                    resultList.add(line);
227                    line = bufferedReader.readLine();
228                }
229            } 
230            catch(IOException exc)
231            {
232                throw new NestedApplicationException(exc);
233            }
234            return resultList;
235        }
236    }