001: //The contents of this file are subject to the Mozilla Public License Version 1.1
002: //(the "License"); you may not use this file except in compliance with the
003: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
004: //
005: //Software distributed under the License is distributed on an "AS IS" basis,
006: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
007: //for the specific language governing rights and
008: //limitations under the License.
009: //
010: //The Original Code is "The Columba Project"
011: //
012: //The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
013: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
014: //
015: //All Rights Reserved.
016:
017: package org.columba.mail.parser;
018:
019: import java.io.FilterInputStream;
020: import java.io.IOException;
021: import java.io.InputStream;
022:
023: import org.columba.core.base.Barrier;
024: import org.columba.core.base.Mutex;
025: import org.columba.ristretto.io.CharSequenceSource;
026: import org.columba.ristretto.message.Header;
027: import org.columba.ristretto.parser.HeaderParser;
028: import org.columba.ristretto.parser.ParserException;
029:
030: /**
031: * FilterInputStream that passively reads and parses
032: * a Header from the stream.
033: *
034: * @author Timo Stich <tstich@users.sourceforge.net>
035: */
036: public class PassiveHeaderParserInputStream extends FilterInputStream {
037:
038: private static final int READING = 0;
039: private static final int DONE = 1;
040: private static final String HEADER_END = "\r\n\r\n";
041:
042: private StringBuffer buffer;
043: private int mode;
044: private Header header;
045:
046: private Mutex mutex;
047: private Barrier barrier;
048:
049: /**
050: * Constructs the PassiveHeaderParserInputStream.
051: *
052: * @param arg0 the message stream
053: */
054: public PassiveHeaderParserInputStream(InputStream arg0) {
055: super (arg0);
056:
057: buffer = new StringBuffer();
058:
059: mutex = new Mutex();
060: barrier = new Barrier();
061: }
062:
063: public int read() throws IOException {
064: int character = super .read();
065:
066: if (mode == READING) {
067: if (character == -1) {
068: // The Stream finished before the header was completely
069: // read!
070:
071: // Create a emtpy header an back off
072: header = new Header();
073: barrier.open();
074: } else {
075: buffer.append((char) character);
076: checkHeaderReadComplete();
077: }
078: }
079:
080: return character;
081: }
082:
083: private void checkHeaderReadComplete() {
084: mutex.lock();
085: if (buffer.indexOf(HEADER_END) != -1) {
086: mode = DONE;
087: try {
088: // do the parsing
089: header = HeaderParser.parse(new CharSequenceSource(
090: buffer));
091: } catch (ParserException e) {
092: //TODO (@author tstich): do something
093: }
094: barrier.open();
095: buffer = null;
096: }
097: mutex.release();
098: }
099:
100: public int read(byte[] arg0, int arg1, int arg2) throws IOException {
101: int read = super .read(arg0, arg1, arg2);
102:
103: if (mode == READING) {
104: if (read == -1) {
105: // The Stream finished before the header was completely
106: // read!
107:
108: // Create a emtpy header an back off
109: header = new Header();
110: barrier.open();
111: } else {
112: buffer.append(new String(arg0, 0, read, "US-ASCII"));
113: checkHeaderReadComplete();
114: }
115: }
116:
117: return read;
118: }
119:
120: /**
121: * Checks if the Header is already available.
122: *
123: * @return true if the Header is parsed
124: */
125: public boolean isHeaderAvailable() {
126: return mode == DONE;
127: }
128:
129: /**
130: * This call blocks until the Header is parsed.
131: *
132: * @return Returns the header.
133: */
134: public Header getHeader() {
135: barrier.join();
136:
137: return header;
138: }
139: }
|