001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *  http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.apache.geronimo.javamail.transport.nntp;
021    
022    import java.io.IOException;
023    import java.io.InputStream;
024    import java.io.UnsupportedEncodingException;
025    import java.util.List;
026    
027    /**
028     * @version $Rev: 437941 $ $Date: 2006-08-28 23:56:02 -0400 (Mon, 28 Aug 2006) $
029     */
030    public class StringListInputStream extends InputStream {
031        // the list of lines we're reading from
032        protected List lines;
033    
034        // the next line to process.
035        protected int nextLine = 0;
036    
037        // current buffer of bytes to read from
038        byte[] buffer;
039    
040        // current offset within the buffer;
041        int offset;
042    
043        // indicator that we've left off at a split between the CR and LF of a line
044        // break.
045        boolean atLineBreak = false;
046    
047        public StringListInputStream(List lines) throws IOException {
048            this.lines = lines;
049            nextLine = 0;
050            buffer = null;
051            offset = 0;
052            atLineBreak = false;
053    
054            // if we have at least one line in the list, get the bytes now.
055            if (lines.size() > 0) {
056                nextBuffer();
057            }
058        }
059    
060        /**
061         * Just override the single byte read version, which handles all of the
062         * lineend markers correctly.
063         * 
064         * @return The next byte from the stream or -1 if we've hit the EOF.
065         */
066        public int read() throws IOException {
067            // leave off at the split between a line?
068            if (atLineBreak) {
069                // flip this off and return the second line end character. Also step
070                // to the next line.
071                atLineBreak = false;
072                nextBuffer();
073                return '\n';
074            }
075            // gone past the end? Got an EOF
076            if (buffer == null) {
077                return -1;
078            }
079    
080            // reach the end of the line?
081            if (offset >= buffer.length) {
082                // we're now working on a virtual linebreak
083                atLineBreak = true;
084                return '\r';
085            }
086            // just return the next byte
087            return buffer[offset++];
088    
089        }
090    
091        /**
092         * Step to the next buffer of string data.
093         * 
094         * @exception IOException
095         */
096        protected void nextBuffer() throws IOException {
097            // give an eof check.
098            if (nextLine >= lines.size()) {
099                buffer = null;
100            } else {
101                try {
102                    String next = (String) lines.get(nextLine++);
103                    buffer = next.getBytes("US-ASCII");
104    
105                } catch (UnsupportedEncodingException e) {
106                    throw new IOException("Invalid string encoding");
107                }
108            }
109    
110            offset = 0;
111        }
112    }