package org.gbif.ipt.config;
import org.gbif.ipt.model.factory.ExtensionFactory;
import org.gbif.ipt.model.factory.ThesaurusHandlingRule;
import org.gbif.ipt.model.factory.VocabularyFactory;
import org.gbif.ipt.struts2.SimpleTextProvider;
import org.gbif.ipt.task.GenerateDwca;
import org.gbif.ipt.task.GenerateDwcaFactory;
import org.gbif.ipt.task.ReportingTask;
import org.gbif.ipt.utils.InputStreamUtils;
import org.gbif.ipt.utils.PBEEncrypt;
import org.gbif.ipt.utils.PBEEncrypt.EncryptionException;
import org.gbif.utils.HttpUtil;
import org.gbif.utils.PreemptiveAuthenticationInterceptor;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.xml.parsers.SAXParserFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
/**
* A guice module containing wiring used for both test and production.
*/
public class IPTModule extends AbstractModule {
private static final Logger LOG = Logger.getLogger(IPTModule.class);
private static final String DATA_DIR_ENV_VAR = "IPT_DATA_DIR";
// 2 minute timeout
protected static final int CONNECTION_TIMEOUT_MSEC = 120000;
protected static final int MAX_CONNECTIONS = 100;
protected static final int MAX_PER_ROUTE = 10;
@Override
protected void configure() {
// singletons
bind(AppConfig.class).in(Scopes.SINGLETON);
bind(InputStreamUtils.class).in(Scopes.SINGLETON);
bind(SimpleTextProvider.class).in(Scopes.SINGLETON);
bind(ExtensionFactory.class).in(Scopes.SINGLETON);
bind(VocabularyFactory.class).in(Scopes.SINGLETON);
// prototypes
bind(ThesaurusHandlingRule.class).in(Scopes.NO_SCOPE);
// assisted inject factories
install(
new FactoryModuleBuilder().implement(ReportingTask.class, GenerateDwca.class).build(GenerateDwcaFactory.class));
}
@Provides
@Singleton
@Inject
public DataDir provideDataDir(ServletContext ctx) {
DataDir dd;
String dataDirectoryLocation = System.getenv(DATA_DIR_ENV_VAR);
if (dataDirectoryLocation == null) {
File dataDirSettingFile = new File(ctx.getRealPath("/") + "/WEB-INF/datadir.location");
LOG.info("Using location settings file for data directory location at: " + dataDirSettingFile.getAbsolutePath());
dd = DataDir.buildFromLocationFile(dataDirSettingFile);
} else {
LOG.info(
"Using environment variable " + DATA_DIR_ENV_VAR + " for data directory location: " + dataDirectoryLocation);
dd = DataDir.buildFromString(dataDirectoryLocation);
}
try {
if (dd != null && dd.isConfigured()) {
dd.clearTmp();
}
} catch (IOException e) {
LOG.warn("Couldn't clear temporary data dir folder", e);
}
return dd;
}
/**
* Provides a freemarker template loader as a singleton to be used anywhere needed. It is configured to access the
* utf8 templates folder on the classpath, i.e. /src/resources/templates
*/
@Provides
@Singleton
@Inject
public Configuration provideFreemarker(DataDir datadir) {
Configuration fm = new Configuration(Configuration.VERSION_2_3_25);
// load templates from classpath by prefixing /templates
List<TemplateLoader> tLoader = new ArrayList<TemplateLoader>();
tLoader.add(new ClassTemplateLoader(AppConfig.class, "/templates"));
try {
TemplateLoader tlDataDir = new DataDirTemplateLoader(datadir.dataFile(""));
tLoader.add(tlDataDir);
} catch (IOException e) {
LOG.warn("Cannot load custom templates from data dir: " + e.getMessage(), e);
}
TemplateLoader tl = new MultiTemplateLoader(tLoader.toArray(new TemplateLoader[tLoader.size()]));
fm.setDefaultEncoding("UTF-8");
fm.setTemplateLoader(tl);
return fm;
}
@Provides
@Singleton
@Inject
public DefaultHttpClient provideHttpClient() {
// new threadsafe, multithreaded http client with support for http and https.
DefaultHttpClient client = HttpUtil.newMultithreadedClient(CONNECTION_TIMEOUT_MSEC, MAX_CONNECTIONS, MAX_PER_ROUTE);
// registry currently requires Preemptive authentication
// Add as the very first interceptor in the protocol chain
client.addRequestInterceptor(new PreemptiveAuthenticationInterceptor(), 0);
return client;
}
@Provides
@Inject
public HttpUtil provideHttpUtil(DefaultHttpClient client) {
// Return a singleton instance of HttpUtil
return new HttpUtil(client);
}
@Provides
@Singleton
public JdbcSupport provideJdbcSupport() {
JdbcSupport jdbcs = new JdbcSupport();
InputStreamUtils streamUtils = new InputStreamUtils();
InputStream configStream = streamUtils.classpathStream(JdbcSupport.CLASSPATH_PROPFILE);
if (configStream == null) {
LOG.error("Could not find supported jdbc driver information file " + JdbcSupport.CLASSPATH_PROPFILE);
} else {
try {
Properties props = new Properties();
props.load(configStream);
jdbcs.setProperties(props);
LOG.debug("Loaded supported jdbc driver information from " + JdbcSupport.CLASSPATH_PROPFILE);
} catch (IOException e) {
LOG.error("Could not load supported jdbc driver information from " + JdbcSupport.CLASSPATH_PROPFILE, e);
}
}
return jdbcs;
}
@Provides
@Inject
@Singleton
public SAXParserFactory provideNsAwareSaxParserFactory() {
SAXParserFactory saxf = null;
try {
saxf = SAXParserFactory.newInstance();
saxf.setValidating(false);
saxf.setNamespaceAware(true);
} catch (Exception e) {
LOG.error("Cant create namespace aware SAX Parser Factory: " + e.getMessage(), e);
}
return saxf;
}
@Provides
@Inject
@Singleton
public PBEEncrypt providePasswordEncryption() {
final byte[] salt = {0x00, 0x05, 0x02, 0x05, 0x04, 0x25, 0x06, 0x17};
PBEEncrypt enc = null;
try {
enc = new PBEEncrypt("Carla Maria Luise", salt, 9);
} catch (EncryptionException e) {
LOG.error("Cannot create password encryption", e);
}
return enc;
}
}