14ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/**************************************************************** 24ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Licensed to the Apache Software Foundation (ASF) under one * 34ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * or more contributor license agreements. See the NOTICE file * 44ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * distributed with this work for additional information * 54ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * regarding copyright ownership. The ASF licenses this file * 64ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * to you under the Apache License, Version 2.0 (the * 74ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * "License"); you may not use this file except in compliance * 84ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * with the License. You may obtain a copy of the License at * 94ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * * 104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 * 114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * * 124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Unless required by applicable law or agreed to in writing, * 134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * software distributed under the License is distributed on an * 144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * KIND, either express or implied. See the License for the * 164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * specific language governing permissions and limitations * 174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * under the License. * 184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira ****************************************************************/ 194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapackage org.apache.james.mime4j; 214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.IOException; 234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.InputStream; 244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.PushbackInputStream; 254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/** 274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * InputStream which converts <code>\r</code> 284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * bytes not followed by <code>\n</code> and <code>\n</code> not 294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * preceded by <code>\r</code> to <code>\r\n</code>. 304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * 314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * 324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @version $Id: EOLConvertingInputStream.java,v 1.4 2004/11/29 13:15:42 ntherning Exp $ 334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */ 344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapublic class EOLConvertingInputStream extends InputStream { 354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira /** Converts single '\r' to '\r\n' */ 364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira public static final int CONVERT_CR = 1; 374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira /** Converts single '\n' to '\r\n' */ 384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira public static final int CONVERT_LF = 2; 394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira /** Converts single '\r' and '\n' to '\r\n' */ 404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira public static final int CONVERT_BOTH = 3; 4196d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank 424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira private PushbackInputStream in = null; 434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira private int previous = 0; 444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira private int flags = CONVERT_BOTH; 4596d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank private int size = 0; 4696d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank private int pos = 0; 4796d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank private int nextTenPctPos; 4896d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank private int tenPctSize; 4996d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank private Callback callback; 5096d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank 5196d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank public interface Callback { 5296d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank public void report(int bytesRead); 5396d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank } 5496d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank 554ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira /** 564ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Creates a new <code>EOLConvertingInputStream</code> 574ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * instance converting bytes in the given <code>InputStream</code>. 584ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * The flag <code>CONVERT_BOTH</code> is the default. 594ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * 604ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @param in the <code>InputStream</code> to read from. 614ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */ 6296d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank public EOLConvertingInputStream(InputStream _in) { 6396d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank super(); 6496d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank in = new PushbackInputStream(_in, 2); 654ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } 6696d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank 674ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira /** 684ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Creates a new <code>EOLConvertingInputStream</code> 694ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * instance converting bytes in the given <code>InputStream</code>. 704ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * 7196d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank * @param _in the <code>InputStream</code> to read from. 7296d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank * @param _size the size of the input stream (need not be exact) 7396d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank * @param _callback a callback reporting when each 10% of stream's size is reached 744ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */ 7596d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank public EOLConvertingInputStream(InputStream _in, int _size, Callback _callback) { 7696d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank this(_in); 7796d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank size = _size; 7896d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank tenPctSize = size / 10; 7996d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank nextTenPctPos = tenPctSize; 8096d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank callback = _callback; 814ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } 824ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 834ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira /** 844ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Closes the underlying stream. 854ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * 864ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @throws IOException on I/O errors. 874ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */ 884ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira public void close() throws IOException { 894ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira in.close(); 904ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } 914ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 9296d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank private int readByte() throws IOException { 9396d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank int b = in.read(); 9496d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank if (b != -1) { 9596d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank if (callback != null && pos++ == nextTenPctPos) { 9696d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank nextTenPctPos += tenPctSize; 9796d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank if (callback != null) { 9896d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank callback.report(pos); 9996d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank } 10096d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank } 10196d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank } 10296d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank return b; 10396d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank } 10496d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank 10596d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank private void unreadByte(int c) throws IOException { 10696d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank in.unread(c); 10796d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank pos--; 10896d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank } 10996d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank 1104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira /** 1114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @see java.io.InputStream#read() 1124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */ 1134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira public int read() throws IOException { 11496d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank int b = readByte(); 1154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 1164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira if (b == -1) { 11796d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank pos = size; 1184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira return -1; 1194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } 1204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 1214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira if ((flags & CONVERT_CR) != 0 && b == '\r') { 12296d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank int c = readByte(); 1234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira if (c != -1) { 12496d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank unreadByte(c); 1254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } 1264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira if (c != '\n') { 12796d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank unreadByte('\n'); 1284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } 1294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } else if ((flags & CONVERT_LF) != 0 && b == '\n' && previous != '\r') { 1304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira b = '\r'; 13196d998a038c3df43f8f2e94c570e70d9d24fbfbcMarc Blank unreadByte('\n'); 1324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } 1334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 1344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira previous = b; 1354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 1364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira return b; 1374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira } 1384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira 1394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira} 140