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 020package org.apache.james.mime4j.io; 021 022import org.apache.james.mime4j.util.ByteArrayBuffer; 023 024import java.io.IOException; 025import 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 */ 032public 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}