KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > util > CRLFTerminatedReader


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.util;
19
20 import java.io.InputStream JavaDoc;
21 import java.io.BufferedReader JavaDoc;
22 import java.io.UnsupportedEncodingException JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InputStreamReader JavaDoc;
25
26 /**
27  * A Reader for use with SMTP or other protocols in which lines
28  * must end with CRLF. Extends BufferedReader and overrides its
29  * readLine() method. The BufferedReader readLine() method cannot
30  * serve for SMTP because it ends lines with either CR or LF alone.
31  */

32 public class CRLFTerminatedReader extends BufferedReader JavaDoc {
33
34     public class TerminationException extends IOException JavaDoc {
35         private int where;
36         public TerminationException(int where) {
37             super();
38             this.where = where;
39         }
40
41         public TerminationException(String JavaDoc s, int where) {
42             super(s);
43             this.where = where;
44         }
45
46         public int position() {
47             return where;
48         }
49     }
50
51     /**
52      * Constructs this CRLFTerminatedReader.
53      * @param in an InputStream
54      * @param charsetName the String name of a supported charset.
55      * "ASCII" is common here.
56      * @throws UnsupportedEncodingException if the named charset
57      * is not supported
58      */

59     public CRLFTerminatedReader(InputStream JavaDoc in, String JavaDoc charsetName)
60             throws UnsupportedEncodingException JavaDoc {
61         super(new InputStreamReader JavaDoc(in, charsetName));
62     }
63
64     private StringBuffer JavaDoc lineBuffer = new StringBuffer JavaDoc();
65     private final int
66             EOF = -1,
67             CR = 13,
68             LF = 10;
69
70     private int tainted = -1;
71
72     /**
73      * Read a line of text which is terminated by CRLF. The concluding
74      * CRLF characters are not returned with the String, but if either CR
75      * or LF appears in the text in any other sequence it is returned
76      * in the String like any other character. Some characters at the
77      * end of the stream may be lost if they are in a "line" not
78      * terminated by CRLF.
79      *
80      * @return either a String containing the contents of a
81      * line which must end with CRLF, or null if the end of the
82      * stream has been reached, possibly discarding some characters
83      * in a line not terminated with CRLF.
84      * @throws IOException if an I/O error occurs.
85      */

86     public String JavaDoc readLine() throws IOException JavaDoc{
87
88         //start with the StringBuffer empty
89
lineBuffer.delete(0, lineBuffer.length());
90
91         /* This boolean tells which state we are in,
92          * depending upon whether or not we got a CR
93          * in the preceding read().
94          */

95         boolean cr_just_received = false;
96
97         while (true){
98             int inChar = read();
99
100             if (!cr_just_received){
101                 //the most common case, somewhere before the end of a line
102
switch (inChar){
103                     case CR : cr_just_received = true;
104                                 break;
105                     case EOF : return null; // premature EOF -- discards data(?)
106
case LF : //the normal ending of a line
107
if (tainted == -1) tainted = lineBuffer.length();
108                         // intentional fall-through
109
default : lineBuffer.append((char)inChar);
110                 }
111             }else{
112                 // CR has been received, we may be at end of line
113
switch (inChar){
114                     case LF : // LF without a preceding CR
115
if (tainted != -1) {
116                             int pos = tainted;
117                             tainted = -1;
118                             throw new TerminationException("\"bare\" CR or LF in data stream", pos);
119                         }
120                         return lineBuffer.toString();
121                     case EOF : return null; // premature EOF -- discards data(?)
122
case CR : //we got two (or more) CRs in a row
123
if (tainted == -1) tainted = lineBuffer.length();
124                         lineBuffer.append((char)CR);
125                         break;
126                     default : //we got some other character following a CR
127
if (tainted == -1) tainted = lineBuffer.length();
128                         lineBuffer.append((char)CR);
129                         lineBuffer.append((char)inChar);
130                         cr_just_received = false;
131                 }
132             }
133         }//while
134
}//method readLine()
135
}
136
Popular Tags