/**
* MailArchiver is an application that provides services for storing and managing e-mail messages through a Web Services SOAP interface.
* Copyright (C) 2012 Marcio Andre Scholl Levien and Fernando Alberto Reuter Wendt and Jose Ronaldo Nogueira Fonseca Junior
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
/******************************************************************************\
*
* This product was developed by
*
* SERVIÇO FEDERAL DE PROCESSAMENTO DE DADOS (SERPRO),
*
* a government company established under Brazilian law (5.615/70),
* at Department of Development of Porto Alegre.
*
\******************************************************************************/
package serpro.mailarchiver;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Map;
import java.util.TreeMap;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.net.SocketAppender;
import org.apache.log4j.rolling.RollingFileAppender;
import org.apache.log4j.rolling.TimeBasedRollingPolicy;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.web.context.request.RequestScope;
import org.springframework.web.context.request.SessionScope;
import com.google.common.base.Supplier;
import de.schlichtherle.truezip.file.TArchiveDetector;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.fs.archive.tar.TarBZip2Driver;
import de.schlichtherle.truezip.fs.archive.tar.TarDriver;
import de.schlichtherle.truezip.fs.archive.tar.TarGZipDriver;
import de.schlichtherle.truezip.fs.archive.zip.JarDriver;
import de.schlichtherle.truezip.fs.archive.zip.ZipDriver;
import de.schlichtherle.truezip.socket.sl.IOPoolLocator;
import serpro.mailarchiver.domain.metaarchive.*;
import serpro.mailarchiver.util.Environment;
import serpro.mailarchiver.util.Logger;
import serpro.mailarchiver.util.UserAppConfig;
import serpro.mailarchiver.util.jdo.MetadataDumper;
import serpro.mailarchiver.util.jdo.PersistenceManagerFactory;
public class Main {
private static final Logger log = Logger.getLocalLogger();
UserAppConfig userAppConfig;
public static void main(String[] args) {
try {
new Main().run();
}
catch(Exception ex) {
log.fatal(ex, "Falha catastrófica");
}
}
private void run() throws Exception {
setupLog();
logSystemProperties();
logSystemEnvironment();
logInternetAddresses();
logUserAppConfig();
TFile.setDefaultArchiveDetector(new TArchiveDetector(TArchiveDetector.NULL,
new Object[][] {
{ "zip", new ZipDriver(IOPoolLocator.SINGLETON)},
{ "jar", new JarDriver(IOPoolLocator.SINGLETON)},
{ "tar", new TarDriver(IOPoolLocator.SINGLETON) },
{ "tgz|tar.gz", new TarGZipDriver(IOPoolLocator.SINGLETON) },
{ "tbz|tb2|tar.bz2", new TarBZip2Driver(IOPoolLocator.SINGLETON) },
}));
final Path archiveDir = userAppConfig.SERVER.getArchiveDir();
if(Files.notExists(archiveDir)) {
Files.createDirectories(archiveDir);
}
final Path mailDir = archiveDir.resolve("mail");
if(Files.notExists(mailDir)) {
Files.createDirectories(mailDir);
}
final Path tempDir = archiveDir.resolve("temp");
if(Files.notExists(tempDir)) {
Files.createDirectories(tempDir);
}
else {
Files.walkFileTree(tempDir, new FileVisitor() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
log.error(exc, "temp delete failed: %s", file.toString());
return FileVisitResult.TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
if(dir != tempDir) {
Files.delete(dir);
}
return FileVisitResult.CONTINUE;
}
});
}
final Path indexDir = archiveDir.resolve("index");
if(Files.notExists(indexDir)) {
Files.createDirectories(indexDir);
}
final Path dbFile = archiveDir.resolve("metaarchive.h2.db");
if(Files.notExists(dbFile)) {
InputStream is = getClass().getResourceAsStream("/serpro/mailarchiver/resources/empty_metaarchive.h2.db");
Files.copy(is, dbFile);
}
ConfigurableApplicationContext context = getGlobalContext();
PersistenceManagerFactory pmf = context.getBean("pmf", PersistenceManagerFactory.class);
logJdoMetadata(pmf);
MailArchiver mailArchiver = context.getBean("mailArchiver", MailArchiver.class);
mailArchiver.init();
}
private ConfigurableApplicationContext getGlobalContext() {
BeanFactoryLocator bfloc = ContextSingletonBeanFactoryLocator.getInstance(
"classpath:/serpro/mailarchiver/config/beanRefContext.xml");
BeanFactoryReference bfref = bfloc.useBeanFactory("global.context");
ConfigurableApplicationContext context = (ConfigurableApplicationContext) bfref.getFactory();
context.registerShutdownHook();
ConfigurableBeanFactory bf = (ConfigurableBeanFactory)context.getAutowireCapableBeanFactory();
bf.registerScope("session", new SessionScope());
bf.registerScope("request", new RequestScope());
return context;
}
private void setupLog() {
userAppConfig = UserAppConfig.getInstance();
Exception ex1 = null, ex2 = null;
try {
userAppConfig.load();
}
catch(Exception ex) {
ex1 = ex;
}
for(Map.Entry logger : userAppConfig.LOG.getLoggers().entrySet()) {
if(logger.getKey().equalsIgnoreCase("root")) {
Logger.getRootLogger().setLevel(Level.toLevel(logger.getValue().toUpperCase()));
}
else {
Logger.getLogger(logger.getKey()).setLevel(Level.toLevel(logger.getValue().toUpperCase()));
}
}
PatternLayout layout = new PatternLayout(userAppConfig.LOG.getLayout());
ConsoleAppender consoleAppender = new ConsoleAppender(layout);
consoleAppender.setThreshold(Level.ERROR);
Logger.getRootLogger().addAppender(consoleAppender);
try {
Path logPath = userAppConfig.LOG.getFile();
System.out.println("logPath: " + logPath);
TimeBasedRollingPolicy rollingPolicy = new TimeBasedRollingPolicy();
rollingPolicy.setFileNamePattern(logPath.toString());
rollingPolicy.activateOptions();
RollingFileAppender rollingFileAppender = new RollingFileAppender();
rollingFileAppender.setEncoding("UTF-8");
rollingFileAppender.setLayout(layout);
rollingFileAppender.setRollingPolicy(rollingPolicy);
rollingFileAppender.activateOptions();
Logger.getRootLogger().addAppender(rollingFileAppender);
}
catch(Exception ex) {
ex2 = ex;
}
String socketHost = userAppConfig.LOG.getSocketHost();
if(!socketHost.isEmpty()) {
SocketAppender socketAppender = new SocketAppender(socketHost, userAppConfig.LOG.getSocketPort());
socketAppender.setLocationInfo(true);
Logger.getRootLogger().addAppender(socketAppender);
}
log.info("Log configurado");
if(ex1 != null) {
log.error(ex1, "log setup");
}
if(ex2 != null) {
log.error(ex2, "log setup");
}
}
private void logSystemProperties() {
StringBuilder sb = new StringBuilder();
sb.append("System properties\n\n");
for(Map.Entry