/*
* Copyright 2010 Outerthought bvba
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lilyproject.tools.mboximport;
import java.io.IOException;
import java.io.InputStream;
/**
* An input stream that allows to read one mime message at a time from an mbox file.
*
* <p>Each new message starts on a line starting with "From<space>", this line itself
* is not part of the message.
*/
public class MboxInputStream extends InputStream {
private InputStream delegate;
private byte[] buffer;
private int currentLineLength;
private int currentLinePos;
private boolean atFromLine;
private boolean eof;
public MboxInputStream(InputStream delegate, int maxLineLength) throws IOException {
this.delegate = delegate;
buffer = new byte[maxLineLength];
readLine();
currentLinePos = -1;
}
public boolean nextMessage() throws IOException {
if (eof) {
return false;
}
if (!atFromLine) {
while (!atFromLine && !eof) {
System.err.println("Not yet at next message, skipping line: " + new String(buffer, 0, currentLineLength));
readLine();
}
}
if (eof) {
return false;
}
readLine();
return true;
}
@Override
public int read() throws IOException {
if (atFromLine || eof) {
return -1;
}
currentLinePos++;
if (currentLinePos >= currentLineLength) {
readLine();
currentLinePos = -1;
return '\n';
}
return buffer[currentLinePos];
}
@Override
public int read(byte b[], int off, int len) throws IOException {
if (atFromLine || eof) {
return -1;
}
currentLinePos++;
if (currentLinePos >= currentLineLength) {
readLine();
currentLinePos = -1;
b[off] = '\n';
return 1;
}
int amount = Math.min(currentLineLength - currentLinePos, len);
System.arraycopy(buffer, currentLinePos, b, off, amount);
currentLinePos += amount - 1;
return amount;
}
private void readLine() throws IOException {
int pos = 0;
int next = delegate.read();
if (next == -1) {
eof = true;
return;
}
while (next != -1 && next != '\n') {
buffer[pos] = (byte)next;
pos++;
next = delegate.read();
}
currentLineLength = pos;
atFromLine = currentLineLength >= 5 &&
buffer[0] == 'F' && buffer[1] == 'r' && buffer[2] == 'o' && buffer[3] == 'm' && buffer[4] == ' ';
}
}