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)
075 throws MaxLineLimitException, IOException {
076 int i;
077 if (this.bis != null) {
078 i = this.bis.readLine(dst);
079 } else {
080 i = doReadLine(dst);
081 }
082 this.eof = i == -1;
083 this.used = true;
084 return i;
085 }
086
087 private int doReadLine(final ByteArrayBuffer dst)
088 throws MaxLineLimitException, IOException {
089 int total = 0;
090 int ch;
091 while ((ch = in.read()) != -1) {
092 dst.append(ch);
093 total++;
094 if (this.maxLineLen > 0 && dst.length() >= this.maxLineLen) {
095 throw new MaxLineLimitException("Maximum line length limit exceeded");
096 }
097 if (ch == '\n') {
098 break;
099 }
100 }
101 if (total == 0 && ch == -1) {
102 return -1;
103 } else {
104 return total;
105 }
106 }
107
108 public boolean eof() {
109 return this.eof;
110 }
111
112 public boolean isUsed() {
113 return this.used;
114 }
115
116 @Override
117 public String toString() {
118 return "[LineReaderInputStreamAdaptor: " + bis + "]";
119 }
120
121 @Override
122 public boolean unread(ByteArrayBuffer buf) {
123 if (bis != null) {
124 return bis.unread(buf);
125 } else {
126 return false;
127 }
128 }
129
130 @Override
131 public long skip(long count) throws IOException {
132 if (count <= 0) {
133 return 0; // So specified by InputStream.skip(long).
134 }
135 final int bufferSize = count > 8192 ? 8192 : (int) count;
136 final byte[] buffer = new byte[bufferSize];
137 long result = 0;
138 while (count > 0) {
139 int res = read(buffer);
140 if (res == -1) {
141 break;
142 }
143 result += res;
144 count -= res;
145 }
146 return result;
147 }
148 }