package com.renaghan.notes2cloud;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.Calendar;
import java.util.Collection;
import java.util.LinkedHashSet;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
/**
* export messages from lotus notes
*
* @author prenagha
*/
public class NotesMailExport {
private static final Logger LOG = Logger.getLogger(NotesMailExport.class);
private final Utils utils = Notes2Cloud.getUtils();
private final static int READ_SIZE = 500;
private final Collection<NotesMailMeta> messages = new LinkedHashSet<NotesMailMeta>(2000);
public NotesMailExport() {
}
public void go() {
loadList();
exportList();
}
private void exportList() {
Calendar breather = Calendar.getInstance();
breather.add(Calendar.MINUTE, -30);
int total = messages.size();
int item = 0;
for (NotesMailMeta msg : messages) {
item++;
// we don't archive calendar to email
if (!msg.isExport()) {
//LOG.debug("Skip: " + msg);
continue;
}
// give a few hours to clear new stuff from inbox
if (msg.getDate().after(breather))
continue;
// export directory is based on year of message
String year = String.valueOf(msg.getDate().get(Calendar.YEAR));
File outputDir = new File(utils.getProperty("export.outputDir") + "/" + year + "/cur");
if (!outputDir.exists())
throw new RuntimeException("Output dir does not exist " + outputDir + " " + msg);
if (!outputDir.canRead() || !outputDir.canWrite())
throw new RuntimeException("Output dir not accessible " + outputDir + " " + msg);
// if we already have exported this message then skip
File msgFile = new File(outputDir, msg.getIMAPFileName());
if (msgFile.exists())
continue;
if (contains(outputDir, msg.getFileName()))
continue;
exportMessage(item, total, msg, outputDir, msgFile);
}
}
private boolean contains (File dir, final String startsWith) {
if (dir == null || startsWith == null || startsWith.length() < 10)
return false;
File[] files = dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.startsWith(startsWith);
}
});
return files != null && files.length > 0;
}
private void exportMessage(int item, int total, NotesMailMeta msg, File outputDir, File msgFile) {
LOG.info(item + "/" + total + " Export " + msg);
String msgUrl = utils.getProperty("notes.url")
+ utils.getProperty("export.msgUrl")
+ msg.getId()
+ utils.getProperty("export.msgFields");
try {
HttpGet contents = new HttpGet(msgUrl);
HttpResponse response = utils.getHttpClient().execute(contents);
if (response.getStatusLine().getStatusCode() == 200) {
//export worked
File tmp = new File(outputDir, ".msg.tmp");
if (tmp.exists())
tmp.delete();
InputStream is = response.getEntity().getContent();
FileOutputStream os = new FileOutputStream(msgFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buffer = new byte[8192];
int len;
while ((len = is.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
is.close();
bos.close();
tmp.renameTo(msgFile);
msgFile.setLastModified(msg.getDate().getTimeInMillis());
} else {
//export failed
throw new RuntimeException("Notes export mail failed " + response.getStatusLine().getStatusCode() + " " + msg);
}
LOG.info("Fix mail export " + msgFile.getCanonicalPath());
try {
Runtime.getRuntime().exec("/usr/bin/perl /Users/prenagha/Dev/notes2cloud/fix-mail-export.pl " + msgFile.getCanonicalPath());
} catch (Exception e) {
LOG.error("Error running perl fixDate script on " + msgFile.getName());
}
} catch (Exception e) {
throw new RuntimeException("Error in mail export " + msgUrl + " -- " + msg, e);
}
}
private void loadList() {
int total = 0;
int start = 1;
while (true) {
LOG.info("List reading from " + start);
int read = listStarting(start);
total = total + read;
LOG.info("List read count " + read);
if (read < READ_SIZE)
break;
start = total;
}
LOG.info("Total read " + total);
}
private int listStarting(int start) {
String listUrl = utils.getProperty("notes.url")
+ utils.getProperty("export.listUrl")
+ "&Start=" + start
+ "&Count=" + READ_SIZE
+ utils.getProperty("export.listFields");
try {
HttpGet list = new HttpGet(listUrl);
HttpResponse response = utils.getHttpClient().execute(list);
String output = response.getEntity() == null ? "" : EntityUtils.toString(response.getEntity());
if ("true".equals(Notes2Cloud.getUtils().getProperty("debug"))) {
HttpEntity entity = response.getEntity();
if (entity != null) {
FileWriter fw = new FileWriter("notes-export-list-response.xml");
fw.write(output);
fw.close();
}
}
if (response.getStatusLine().getStatusCode() == 200) {
//list worked
} else {
//list failed
throw new RuntimeException("Notes export mail list failed " + response.getStatusLine().getStatusCode());
}
Reader r = new StringReader(output);
Collection<NotesMailMeta> ms = new NotesListResponseParser().convertXML(r);
r.close();
if (ms != null && !ms.isEmpty())
messages.addAll(ms);
return ms == null ? 0 : ms.size();
} catch (Exception e) {
throw new RuntimeException("Error in mail export list " + listUrl, e);
}
}
public static void main(String[] args) {
try {
LOG.info("Start");
NotesMailExport exp = new NotesMailExport();
new NotesLogin().login();
exp.loadList();
exp.exportList();
exp.utils.close();
LOG.info("End");
} catch (Throwable t) {
LOG.error("Error in mail export", t);
}
}
}