Home | History | Annotate | Download | only in mime4j
      1 /****************************************************************
      2  * Licensed to the Apache Software Foundation (ASF) under one   *
      3  * or more contributor license agreements.  See the NOTICE file *
      4  * distributed with this work for additional information        *
      5  * regarding copyright ownership.  The ASF licenses this file   *
      6  * to you under the Apache License, Version 2.0 (the            *
      7  * "License"); you may not use this file except in compliance   *
      8  * with the License.  You may obtain a copy of the License at   *
      9  *                                                              *
     10  *   http://www.apache.org/licenses/LICENSE-2.0                 *
     11  *                                                              *
     12  * Unless required by applicable law or agreed to in writing,   *
     13  * software distributed under the License is distributed on an  *
     14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
     15  * KIND, either express or implied.  See the License for the    *
     16  * specific language governing permissions and limitations      *
     17  * under the License.                                           *
     18  ****************************************************************/
     19 
     20 package org.apache.james.mime4j;
     21 
     22 import java.io.IOException;
     23 import java.io.InputStream;
     24 import java.io.PushbackInputStream;
     25 
     26 /**
     27  * InputStream which converts <code>\r</code>
     28  * bytes not followed by <code>\n</code> and <code>\n</code> not
     29  * preceded by <code>\r</code> to <code>\r\n</code>.
     30  *
     31  *
     32  * @version $Id: EOLConvertingInputStream.java,v 1.4 2004/11/29 13:15:42 ntherning Exp $
     33  */
     34 public class EOLConvertingInputStream extends InputStream {
     35     /** Converts single '\r' to '\r\n' */
     36     public static final int CONVERT_CR   = 1;
     37     /** Converts single '\n' to '\r\n' */
     38     public static final int CONVERT_LF   = 2;
     39     /** Converts single '\r' and '\n' to '\r\n' */
     40     public static final int CONVERT_BOTH = 3;
     41 
     42     private PushbackInputStream in = null;
     43     private int previous = 0;
     44     private int flags = CONVERT_BOTH;
     45 
     46     /**
     47      * Creates a new <code>EOLConvertingInputStream</code>
     48      * instance converting bytes in the given <code>InputStream</code>.
     49      * The flag <code>CONVERT_BOTH</code> is the default.
     50      *
     51      * @param in the <code>InputStream</code> to read from.
     52      */
     53     public EOLConvertingInputStream(InputStream in) {
     54         this(in, CONVERT_BOTH);
     55     }
     56     /**
     57      * Creates a new <code>EOLConvertingInputStream</code>
     58      * instance converting bytes in the given <code>InputStream</code>.
     59      *
     60      * @param in the <code>InputStream</code> to read from.
     61      * @param flags one of <code>CONVERT_CR</code>, <code>CONVERT_LF</code> or
     62      *        <code>CONVERT_BOTH</code>.
     63      */
     64     public EOLConvertingInputStream(InputStream in, int flags) {
     65         super();
     66 
     67         this.in = new PushbackInputStream(in, 2);
     68         this.flags = flags;
     69     }
     70 
     71     /**
     72      * Closes the underlying stream.
     73      *
     74      * @throws IOException on I/O errors.
     75      */
     76     public void close() throws IOException {
     77         in.close();
     78     }
     79 
     80     /**
     81      * @see java.io.InputStream#read()
     82      */
     83     public int read() throws IOException {
     84         int b = in.read();
     85 
     86         if (b == -1) {
     87             return -1;
     88         }
     89 
     90         if ((flags & CONVERT_CR) != 0 && b == '\r') {
     91             int c = in.read();
     92             if (c != -1) {
     93                 in.unread(c);
     94             }
     95             if (c != '\n') {
     96                 in.unread('\n');
     97             }
     98         } else if ((flags & CONVERT_LF) != 0 && b == '\n' && previous != '\r') {
     99             b = '\r';
    100             in.unread('\n');
    101         }
    102 
    103         previous = b;
    104 
    105         return b;
    106     }
    107 
    108 }
    109