1 /*
2 * Copyright (C) The Apache Software Foundation. All rights reserved.
3 *
4 * This software is published under the terms of the Apache Software License
5 * version 1.1, a copy of which has been included with this distribution in
6 * the LICENSE file.
7 */
8 package org.apache.james.util;
9
10 import java.io.IOException;
11 import java.io.InputStream;
12
13 /***
14 * An InputStream class that terminates the stream when it encounters a
15 * particular byte sequence.
16 *
17 * @version 1.0.0, 24/04/1999
18 * @author Federico Barbieri <scoobie@pop.systemy.it>
19 */
20 public class CharTerminatedInputStream
21 extends InputStream {
22
23 /***
24 * The wrapped input stream
25 */
26 private InputStream in;
27
28 /***
29 * The terminating character array
30 */
31 private int match[];
32
33 /***
34 * An array containing the last N characters read from the stream, where
35 * N is the length of the terminating character array
36 */
37 private int buffer[];
38
39 /***
40 * The number of bytes that have been read that have not been placed
41 * in the internal buffer.
42 */
43 private int pos = 0;
44
45 /***
46 * Whether the terminating sequence has been read from the stream
47 */
48 private boolean endFound = false;
49
50 /***
51 * A constructor for this object that takes a stream to be wrapped
52 * and a terminating character sequence.
53 *
54 * @param in the <code>InputStream</code> to be wrapped
55 * @param terminator the array of characters that will terminate the stream.
56 *
57 * @throws IllegalArgumentException if the terminator array is null or empty
58 */
59 public CharTerminatedInputStream(InputStream in, char[] terminator) {
60 if (terminator == null) {
61 throw new IllegalArgumentException("The terminating character array cannot be null.");
62 }
63 if (terminator.length == 0) {
64 throw new IllegalArgumentException("The terminating character array cannot be of zero length.");
65 }
66 match = new int[terminator.length];
67 buffer = new int[terminator.length];
68 for (int i = 0; i < terminator.length; i++) {
69 match[i] = (int)terminator[i];
70 buffer[i] = (int)terminator[i];
71 }
72 this.in = in;
73 }
74
75 /***
76 * Read a byte off this stream.
77 *
78 * @return the byte read off the stream
79 * @throws IOException if an IOException is encountered while reading off the stream
80 */
81 public int read() throws IOException {
82 if (endFound) {
83 //We've found the match to the terminator
84 return -1;
85 }
86 if (pos == 0) {
87 //We have no data... read in a record
88 int b = in.read();
89 if (b == -1) {
90 //End of stream reached
91 endFound = true;
92 return -1;
93 }
94 if (b != match[0]) {
95 //this char is not the first char of the match
96 return b;
97 }
98 //this is a match...put this in the first byte of the buffer,
99 // and fall through to matching logic
100 buffer[0] = b;
101 pos++;
102 } else {
103 if (buffer[0] != match[0]) {
104 //Maybe from a previous scan, there is existing data,
105 // and the first available char does not match the
106 // beginning of the terminating string.
107 return topChar();
108 }
109 //we have a match... fall through to matching logic.
110 }
111 //MATCHING LOGIC
112
113 //The first character is a match... scan for complete match,
114 // reading extra chars as needed, until complete match is found
115 for (int i = 0; i < match.length; i++) {
116 if (i >= pos) {
117 int b = in.read();
118 if (b == -1) {
119 //end of stream found, so match cannot be fulfilled.
120 // note we don't set endFound, because otherwise
121 // remaining part of buffer won't be returned.
122 return topChar();
123 }
124 //put the read char in the buffer
125 buffer[pos] = b;
126 pos++;
127 }
128 if (buffer[i] != match[i]) {
129 //we did not find a match... return the top char
130 return topChar();
131 }
132 }
133 //A complete match was made...
134 endFound = true;
135 return -1;
136 }
137
138 /***
139 * Private helper method to update the internal buffer of last read characters
140 *
141 * @return the byte that was previously at the front of the internal buffer
142 */
143 private int topChar() {
144 int b = buffer[0];
145 if (pos > 1) {
146 //copy down the buffer to keep the fresh data at top
147 System.arraycopy(buffer, 1, buffer, 0, pos - 1);
148 }
149 pos--;
150 return b;
151 }
152 }
153
This page was automatically generated by Maven