PostingReader.java
/*
* Copyright (C) 2016-2025 The CTAN Team and individual authors
*
* This file is distributed under the 3-clause BSD license.
* See file LICENSE for details.
*/
package org.ctan.site.services.postings;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
/**
* This class provides a reader for mails from gzipped mail archive files.
*
* @author <a href="gene@ctan.org">Gerd Neugebauer</a>
*/
public class PostingReader implements AutoCloseable {
/**
* The field <code>reader</code> contains the reader for the data source.
*/
private BufferedReader reader;
/**
* The field <code>line</code> contains the pushback buffer for read lines.
*/
private String line = null;
/**
* This is the constructor for <code>PostingReader</code>.
*
* @param r the reader
*/
public PostingReader(Reader r) {
reader = new BufferedReader(r, 1024);
}
/**
* This method closes this reader and the attached input sources.
*
* @throws IOException in case of an I/O error during closing
*/
@Override
public void close() throws IOException {
if (reader != null) {
reader.close();
}
reader = null;
}
/**
* This method reads a mail from this reader and returns it.
*
* @return the mail read or {@code null} at EOF
*
* @throws IOException in case of an I/O error
*/
public Posting read() throws IOException {
if (line == null) {
line = reader.readLine();
}
if (line == null || !line.startsWith("From ")) {
return null;
}
var m = new Posting(line.substring(5));
var key = "";
for (line = reader.readLine(); line != null
&& !line.isEmpty(); line = reader.readLine()) {
if (line.startsWith(" ") || line.startsWith("\t")) {
m.put(key, m.get(key) + line);
}
var i = line.indexOf(':');
if (i >= 0) {
key = line.substring(0, i);
m.put(key, line.substring(i + 2));
} else {
break;
}
}
var buffer = new StringBuilder();
var nl = false;
for (line = reader.readLine(); line != null; line = reader.readLine()) {
if (line.isEmpty()) {
if (nl) {
buffer.append('\n');
} else {
nl = true;
}
} else {
if (nl) {
if (line.startsWith("From ")) {
break;
}
buffer.append('\n');
nl = false;
}
buffer.append(line);
buffer.append('\n');
}
}
m.setBody(buffer.toString());
return m;
}
}