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                byteStream.flush();
064            }
065            catch(IOException exc)
066            {
067                log.error("Exception while reading from stream", exc);
068            }
069            return byteStream.toByteArray();
070        }
071        
072        /**
073         * Returns the contents of the reader as a string.
074         * @param reader the <code>Reader</code>
075         * @return the reader content as <code>String</code>
076         */
077        public static String getReaderAsString(Reader reader)
078        {
079            return getReaderAsString(reader, -1);
080        }
081        
082        /**
083         * Returns the contents of the reader as a string.
084         * @param reader the <code>Reader</code>
085         * @param length the number of chars to copy, if length < 0,
086         *        the number is unlimited
087         * @return the reader content as <code>String</code>
088         */
089        public static String getReaderAsString(Reader reader, int length)
090        {
091            if(length == 0) return "";
092            boolean checkLength = true;
093            if(length < 0)
094            {
095                length = Integer.MAX_VALUE;
096                checkLength = false;
097            }
098            StringBuffer buffer = new StringBuffer();
099            try
100            {
101                int nextValue = reader.read();
102                if(checkLength) length--;
103                while(-1 != nextValue && length >= 0)
104                {
105                    buffer.append((char)nextValue);
106                    nextValue = reader.read();
107                    if(checkLength) length--;
108                }
109            }
110            catch(IOException exc)
111            {
112                log.error("Exception while reading from reader", exc);
113            }
114            return buffer.toString();
115        }
116        
117        /**
118         * Returns a copy of the specified stream. If the specified stream supports
119         * marking, it will be reset after the copy.
120         * @param sourceStream the stream to copy
121         * @return a copy of the stream
122         */
123        public static InputStream copyStream(InputStream sourceStream)
124        {
125            try
126            {
127                if(sourceStream.markSupported()) sourceStream.mark(sourceStream.available());
128                byte[] sourceData = getStreamAsByteArray(sourceStream);
129                if(sourceStream.markSupported()) sourceStream.reset();
130                return new ByteArrayInputStream(sourceData);
131            }
132            catch(IOException exc)
133            {
134                log.error("Exception while copying stream", exc);
135                return null;
136            }
137        }
138      
139        /**
140         * Returns a copy of the specified reader. If the specified reader supports
141         * marking, it will be reset after the copy.
142         * @param sourceReader the stream to reader
143         * @return a copy of the reader
144         */
145        public static Reader copyReader(Reader sourceReader)
146        {
147            try
148            {
149                if(sourceReader.markSupported()) sourceReader.mark(Integer.MAX_VALUE);
150                String sourceData = getReaderAsString(sourceReader);
151                if(sourceReader.markSupported()) sourceReader.reset();
152                return new StringReader(sourceData);
153            }
154            catch(IOException exc)
155            {
156                log.error("Exception while copying reader", exc);
157                return null;
158            }
159        }
160        
161        /**
162         * Compares the content of the streams. If the streams support
163         * marking, they will be reset after the comparison.
164         * @param sourceStream the source stream
165         * @param targetStream the target stream
166         * @return <code>true</code>, if the streams are identical, <code>false</code> otherwise
167         */
168        public static boolean compareStreams(InputStream sourceStream, InputStream targetStream)
169        {
170            try
171            {
172                if(sourceStream.markSupported()) sourceStream.mark(sourceStream.available());
173                if(targetStream.markSupported()) targetStream.mark(targetStream.available());
174                byte[] sourceArray = getStreamAsByteArray(sourceStream);
175                byte[] targetArray = getStreamAsByteArray(targetStream);
176                if(sourceStream.markSupported()) sourceStream.reset();
177                if(targetStream.markSupported()) targetStream.reset();
178                return Arrays.equals(sourceArray, targetArray);
179            }
180            catch(IOException exc)
181            {
182                log.error("Exception while comparing streams", exc);
183                return false;
184            }
185        }
186        
187        /**
188         * Compares the content of the readers. If the readers support
189         * marking, they will be reset after the comparison.
190         * @param sourceReader the source stream
191         * @param targetReader the target stream
192         * @return <code>true</code>, if the streams are identical, <code>false</code> otherwise
193         */
194        public static boolean compareReaders(Reader sourceReader, Reader targetReader)
195        {
196            try
197            {
198                if(sourceReader.markSupported()) sourceReader.mark(Integer.MAX_VALUE);
199                if(targetReader.markSupported()) targetReader.mark(Integer.MAX_VALUE);
200                String sourceString = getReaderAsString(sourceReader);
201                String targetString = getReaderAsString(targetReader);
202                if(sourceReader.markSupported()) sourceReader.reset();
203                if(targetReader.markSupported()) targetReader.reset();
204                return sourceString.equals(targetString);
205            }
206            catch(IOException exc)
207            {
208                log.error("Exception while comparing readers", exc);
209                return false;
210            }
211        }
212        
213        /**
214         * Reads the lines from the specified reader and adds them to a <code>List</code>.
215         * @param reader the reader
216         * @return the <code>List</code> with the lines
217         */
218        public static List getLinesFromReader(Reader reader)
219        {
220            List resultList = new ArrayList();
221            try
222            {
223                BufferedReader bufferedReader = new BufferedReader(reader);
224                String line = bufferedReader.readLine();
225                while(line != null)
226                {
227                    resultList.add(line);
228                    line = bufferedReader.readLine();
229                }
230            } 
231            catch(IOException exc)
232            {
233                throw new NestedApplicationException(exc);
234            }
235            return resultList;
236        }
237    }