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.james.mime4j.io;
021    
022    import org.apache.james.mime4j.util.ByteArrayBuffer;
023    
024    import java.io.IOException;
025    import java.io.InputStream;
026    
027    /**
028     * <code>InputStream</code> used by the MIME parser to detect whether the
029     * underlying data stream was used (read from) and whether the end of the 
030     * stream was reached.
031     */
032    public class LineReaderInputStreamAdaptor extends LineReaderInputStream {
033    
034        private final LineReaderInputStream bis;
035        private final int maxLineLen;
036        
037        private boolean used = false;
038        private boolean eof = false;
039    
040        public LineReaderInputStreamAdaptor(
041                final InputStream is,
042                int maxLineLen) {
043            super(is);
044            if (is instanceof LineReaderInputStream) {
045                this.bis = (LineReaderInputStream) is;
046            } else {
047                this.bis = null;
048            }
049            this.maxLineLen = maxLineLen;
050        }
051    
052        public LineReaderInputStreamAdaptor(
053                final InputStream is) {
054            this(is, -1);
055        }
056        
057        @Override
058        public int read() throws IOException {
059            int i = in.read();
060            this.eof = i == -1;
061            this.used = true;
062            return i;
063        }
064    
065        @Override
066        public int read(byte[] b, int off, int len) throws IOException {
067            int i = in.read(b, off, len);
068            this.eof = i == -1;
069            this.used = true;
070            return i;
071        }
072        
073        @Override
074        public int readLine(final ByteArrayBuffer dst) throws IOException {
075            int i;
076            if (this.bis != null) {
077                 i = this.bis.readLine(dst);
078            } else {
079                 i = doReadLine(dst);
080            }
081            this.eof = i == -1;
082            this.used = true;
083            return i;
084        }
085    
086        private int doReadLine(final ByteArrayBuffer dst) throws IOException {
087            int total = 0;
088            int ch;
089            while ((ch = in.read()) != -1) {
090                dst.append(ch);
091                total++;
092                if (this.maxLineLen > 0 && dst.length() >= this.maxLineLen) {
093                    throw new MaxLineLimitException("Maximum line length limit exceeded");
094                }
095                if (ch == '\n') {
096                    break;
097                }
098            }
099            if (total == 0 && ch == -1) {
100                return -1;
101            } else {
102                return total;
103            }
104        }
105        
106        public boolean eof() {
107            return this.eof;
108        }
109    
110        public boolean isUsed() {
111            return this.used;
112        }
113        
114        @Override
115        public String toString() {
116            return "[LineReaderInputStreamAdaptor: " + bis + "]";
117        }
118    }