diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 714351ae..2f5cc74c 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,5 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
diff --git a/pom.xml b/pom.xml
index 9062184d..ed2d8cd1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,19 +94,17 @@
-
- genepi
- genepi-db
- 1.2.1
-
-
- log4j
- log4j
-
-
-
-
+ commons-dbutils
+ commons-dbutils
+ 1.7
+
+
+
+ commons-dbcp
+ commons-dbcp
+ 1.4
+
genepi
genepi-hadoop
diff --git a/src/main/java/cloudgene/mapred/Main.java b/src/main/java/cloudgene/mapred/Main.java
index 9dbaafc4..00ee9e3f 100644
--- a/src/main/java/cloudgene/mapred/Main.java
+++ b/src/main/java/cloudgene/mapred/Main.java
@@ -21,7 +21,10 @@
import com.esotericsoftware.yamlbeans.YamlReader;
import cloudgene.mapred.database.updates.BcryptHashUpdate;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.DatabaseConnector;
import cloudgene.mapred.database.util.DatabaseConnectorFactory;
+import cloudgene.mapred.database.util.DatabaseUpdater;
import cloudgene.mapred.database.util.Fixtures;
import cloudgene.mapred.jobs.PersistentWorkflowEngine;
import cloudgene.mapred.jobs.WorkflowEngine;
@@ -29,9 +32,6 @@
import cloudgene.mapred.util.BuildUtil;
import cloudgene.mapred.util.Config;
import cloudgene.mapred.util.Settings;
-import genepi.db.Database;
-import genepi.db.DatabaseConnector;
-import genepi.db.DatabaseUpdater;
import genepi.io.FileUtil;
public class Main {
diff --git a/src/main/java/cloudgene/mapred/WebApp.java b/src/main/java/cloudgene/mapred/WebApp.java
index 367e9759..02e87560 100644
--- a/src/main/java/cloudgene/mapred/WebApp.java
+++ b/src/main/java/cloudgene/mapred/WebApp.java
@@ -73,15 +73,14 @@
import cloudgene.mapred.api.v2.users.UpdatePassword;
import cloudgene.mapred.api.v2.users.UserProfile;
import cloudgene.mapred.api.v2.users.VerifyApiToken;
-import cloudgene.mapred.apps.ApplicationRepository;
import cloudgene.mapred.database.TemplateDao;
+import cloudgene.mapred.database.util.Database;
import cloudgene.mapred.jobs.WorkflowEngine;
import cloudgene.mapred.representations.CustomStatusService;
import cloudgene.mapred.resources.Admin;
import cloudgene.mapred.resources.Index;
import cloudgene.mapred.resources.Start;
import cloudgene.mapred.util.Settings;
-import genepi.db.Database;
public class WebApp extends Application {
diff --git a/src/main/java/cloudgene/mapred/WebServer.java b/src/main/java/cloudgene/mapred/WebServer.java
index f689b5fc..5b9b596d 100644
--- a/src/main/java/cloudgene/mapred/WebServer.java
+++ b/src/main/java/cloudgene/mapred/WebServer.java
@@ -8,11 +8,10 @@
import org.restlet.data.Protocol;
import org.restlet.routing.VirtualHost;
-import cloudgene.mapred.apps.Application;
import cloudgene.mapred.cron.CronJobScheduler;
+import cloudgene.mapred.database.util.Database;
import cloudgene.mapred.jobs.WorkflowEngine;
import cloudgene.mapred.util.Settings;
-import genepi.db.Database;
public class WebServer extends Component {
diff --git a/src/main/java/cloudgene/mapred/api/v2/jobs/NextflowWebLog.java b/src/main/java/cloudgene/mapred/api/v2/jobs/NextflowWebLog.java
index 23c4999d..3ee706f5 100644
--- a/src/main/java/cloudgene/mapred/api/v2/jobs/NextflowWebLog.java
+++ b/src/main/java/cloudgene/mapred/api/v2/jobs/NextflowWebLog.java
@@ -1,7 +1,5 @@
package cloudgene.mapred.api.v2.jobs;
-import java.io.IOException;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.restlet.representation.Representation;
diff --git a/src/main/java/cloudgene/mapred/apps/ApplicationRepository.java b/src/main/java/cloudgene/mapred/apps/ApplicationRepository.java
index 0776157d..54e81ce6 100644
--- a/src/main/java/cloudgene/mapred/apps/ApplicationRepository.java
+++ b/src/main/java/cloudgene/mapred/apps/ApplicationRepository.java
@@ -1,8 +1,6 @@
package cloudgene.mapred.apps;
import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
@@ -18,15 +16,13 @@
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
-import com.esotericsoftware.yamlbeans.YamlReader;
-import com.esotericsoftware.yamlbeans.YamlWriter;
import cloudgene.mapred.core.User;
+import cloudgene.mapred.database.util.DatabaseUpdater;
import cloudgene.mapred.util.GitHubException;
import cloudgene.mapred.util.GitHubUtil;
import cloudgene.mapred.util.GitHubUtil.Repository;
import cloudgene.mapred.wdl.WdlApp;
-import genepi.db.DatabaseUpdater;
import genepi.hadoop.S3Util;
import genepi.io.FileUtil;
import net.lingala.zip4j.ZipFile;
diff --git a/src/main/java/cloudgene/mapred/core/ApiTokenVerifier.java b/src/main/java/cloudgene/mapred/core/ApiTokenVerifier.java
index a3ee2819..4f6bdd54 100644
--- a/src/main/java/cloudgene/mapred/core/ApiTokenVerifier.java
+++ b/src/main/java/cloudgene/mapred/core/ApiTokenVerifier.java
@@ -10,7 +10,7 @@
import com.nimbusds.jose.crypto.MACVerifier;
import cloudgene.mapred.database.UserDao;
-import genepi.db.Database;
+import cloudgene.mapred.database.util.Database;
public class ApiTokenVerifier {
diff --git a/src/main/java/cloudgene/mapred/core/JWTUtil.java b/src/main/java/cloudgene/mapred/core/JWTUtil.java
index 071678bf..dd9a4360 100644
--- a/src/main/java/cloudgene/mapred/core/JWTUtil.java
+++ b/src/main/java/cloudgene/mapred/core/JWTUtil.java
@@ -10,7 +10,7 @@
import org.restlet.util.Series;
import cloudgene.mapred.database.UserDao;
-import genepi.db.Database;
+import cloudgene.mapred.database.util.Database;
public class JWTUtil {
diff --git a/src/main/java/cloudgene/mapred/cron/CleanUpTasks.java b/src/main/java/cloudgene/mapred/cron/CleanUpTasks.java
index caf21121..c2e56589 100644
--- a/src/main/java/cloudgene/mapred/cron/CleanUpTasks.java
+++ b/src/main/java/cloudgene/mapred/cron/CleanUpTasks.java
@@ -8,13 +8,13 @@
import cloudgene.mapred.WebApp;
import cloudgene.mapred.database.JobDao;
+import cloudgene.mapred.database.util.Database;
import cloudgene.mapred.jobs.AbstractJob;
import cloudgene.mapred.jobs.workspace.ExternalWorkspaceFactory;
import cloudgene.mapred.util.MailUtil;
import cloudgene.mapred.util.Settings;
import cloudgene.mapred.util.Template;
import cloudgene.sdk.internal.IExternalWorkspace;
-import genepi.db.Database;
import genepi.hadoop.HdfsUtil;
import genepi.io.FileUtil;
diff --git a/src/main/java/cloudgene/mapred/cron/RetireJob.java b/src/main/java/cloudgene/mapred/cron/RetireJob.java
index aa352ff6..e9be7b0b 100644
--- a/src/main/java/cloudgene/mapred/cron/RetireJob.java
+++ b/src/main/java/cloudgene/mapred/cron/RetireJob.java
@@ -6,8 +6,8 @@
import org.quartz.JobExecutionException;
import cloudgene.mapred.WebApp;
+import cloudgene.mapred.database.util.Database;
import cloudgene.mapred.util.Settings;
-import genepi.db.Database;
public class RetireJob implements Job {
diff --git a/src/main/java/cloudgene/mapred/cron/StatisticsJob.java b/src/main/java/cloudgene/mapred/cron/StatisticsJob.java
index b35a3031..53269514 100644
--- a/src/main/java/cloudgene/mapred/cron/StatisticsJob.java
+++ b/src/main/java/cloudgene/mapred/cron/StatisticsJob.java
@@ -12,9 +12,9 @@
import cloudgene.mapred.core.User;
import cloudgene.mapred.database.CounterHistoryDao;
import cloudgene.mapred.database.UserDao;
+import cloudgene.mapred.database.util.Database;
import cloudgene.mapred.jobs.AbstractJob;
import cloudgene.mapred.jobs.WorkflowEngine;
-import genepi.db.Database;
public class StatisticsJob implements Job {
diff --git a/src/main/java/cloudgene/mapred/database/CounterDao.java b/src/main/java/cloudgene/mapred/database/CounterDao.java
index 46628110..d7fe1498 100644
--- a/src/main/java/cloudgene/mapred/database/CounterDao.java
+++ b/src/main/java/cloudgene/mapred/database/CounterDao.java
@@ -8,10 +8,10 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IRowMapMapper;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
import cloudgene.mapred.jobs.AbstractJob;
-import genepi.db.Database;
-import genepi.db.IRowMapMapper;
-import genepi.db.JdbcDataAccessObject;
public class CounterDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/CounterHistoryDao.java b/src/main/java/cloudgene/mapred/database/CounterHistoryDao.java
index 899c52ce..5344957c 100644
--- a/src/main/java/cloudgene/mapred/database/CounterHistoryDao.java
+++ b/src/main/java/cloudgene/mapred/database/CounterHistoryDao.java
@@ -14,8 +14,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import genepi.db.Database;
-import genepi.db.JdbcDataAccessObject;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
public class CounterHistoryDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/DownloadDao.java b/src/main/java/cloudgene/mapred/database/DownloadDao.java
index d20a8438..a473585b 100644
--- a/src/main/java/cloudgene/mapred/database/DownloadDao.java
+++ b/src/main/java/cloudgene/mapred/database/DownloadDao.java
@@ -8,11 +8,11 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IRowMapper;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
import cloudgene.mapred.jobs.CloudgeneParameterOutput;
import cloudgene.mapred.jobs.Download;
-import genepi.db.Database;
-import genepi.db.IRowMapper;
-import genepi.db.JdbcDataAccessObject;
public class DownloadDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/JobDao.java b/src/main/java/cloudgene/mapred/database/JobDao.java
index 275deab4..ac65f39f 100644
--- a/src/main/java/cloudgene/mapred/database/JobDao.java
+++ b/src/main/java/cloudgene/mapred/database/JobDao.java
@@ -10,14 +10,15 @@
import cloudgene.mapred.core.User;
import cloudgene.mapred.database.UserDao.UserMapper;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IRowMapper;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
+import cloudgene.mapred.database.util.JdbcDataAccessObject.IntegerMapper;
import cloudgene.mapred.jobs.AbstractJob;
import cloudgene.mapred.jobs.CloudgeneJob;
import cloudgene.mapred.jobs.CloudgeneParameterInput;
import cloudgene.mapred.jobs.CloudgeneParameterOutput;
import cloudgene.mapred.jobs.CloudgeneStep;
-import genepi.db.Database;
-import genepi.db.IRowMapper;
-import genepi.db.JdbcDataAccessObject;
public class JobDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/MessageDao.java b/src/main/java/cloudgene/mapred/database/MessageDao.java
index 21ef49ca..bb4f9642 100644
--- a/src/main/java/cloudgene/mapred/database/MessageDao.java
+++ b/src/main/java/cloudgene/mapred/database/MessageDao.java
@@ -8,11 +8,11 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IRowMapper;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
import cloudgene.mapred.jobs.CloudgeneStep;
import cloudgene.mapred.jobs.Message;
-import genepi.db.Database;
-import genepi.db.IRowMapper;
-import genepi.db.JdbcDataAccessObject;
public class MessageDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/ParameterDao.java b/src/main/java/cloudgene/mapred/database/ParameterDao.java
index 1cfa7499..eb2decc2 100644
--- a/src/main/java/cloudgene/mapred/database/ParameterDao.java
+++ b/src/main/java/cloudgene/mapred/database/ParameterDao.java
@@ -8,15 +8,15 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IRowMapper;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
import cloudgene.mapred.jobs.AbstractJob;
import cloudgene.mapred.jobs.CloudgeneParameterInput;
import cloudgene.mapred.jobs.CloudgeneParameterOutput;
import cloudgene.mapred.jobs.Download;
import cloudgene.mapred.wdl.WdlParameterInputType;
import cloudgene.mapred.wdl.WdlParameterOutputType;
-import genepi.db.Database;
-import genepi.db.IRowMapper;
-import genepi.db.JdbcDataAccessObject;
public class ParameterDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/StepDao.java b/src/main/java/cloudgene/mapred/database/StepDao.java
index b5ac44c4..f2881439 100644
--- a/src/main/java/cloudgene/mapred/database/StepDao.java
+++ b/src/main/java/cloudgene/mapred/database/StepDao.java
@@ -8,13 +8,13 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IRowMapper;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
import cloudgene.mapred.jobs.CloudgeneJob;
import cloudgene.mapred.jobs.CloudgeneStep;
import cloudgene.mapred.jobs.Message;
import cloudgene.mapred.steps.EmptyStep;
-import genepi.db.Database;
-import genepi.db.IRowMapper;
-import genepi.db.JdbcDataAccessObject;
public class StepDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/TemplateDao.java b/src/main/java/cloudgene/mapred/database/TemplateDao.java
index 2d2e838b..8499ccf8 100644
--- a/src/main/java/cloudgene/mapred/database/TemplateDao.java
+++ b/src/main/java/cloudgene/mapred/database/TemplateDao.java
@@ -8,10 +8,10 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IRowMapper;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
import cloudgene.mapred.util.Template;
-import genepi.db.Database;
-import genepi.db.IRowMapper;
-import genepi.db.JdbcDataAccessObject;
public class TemplateDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/UserDao.java b/src/main/java/cloudgene/mapred/database/UserDao.java
index 1cf7f0fc..37af8957 100644
--- a/src/main/java/cloudgene/mapred/database/UserDao.java
+++ b/src/main/java/cloudgene/mapred/database/UserDao.java
@@ -9,10 +9,10 @@
import org.apache.commons.logging.LogFactory;
import cloudgene.mapred.core.User;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IRowMapper;
+import cloudgene.mapred.database.util.JdbcDataAccessObject;
import cloudgene.mapred.util.PublicUser;
-import genepi.db.Database;
-import genepi.db.IRowMapper;
-import genepi.db.JdbcDataAccessObject;
public class UserDao extends JdbcDataAccessObject {
diff --git a/src/main/java/cloudgene/mapred/database/updates/BcryptHashUpdate.java b/src/main/java/cloudgene/mapred/database/updates/BcryptHashUpdate.java
index 8359b3dd..41620aa6 100644
--- a/src/main/java/cloudgene/mapred/database/updates/BcryptHashUpdate.java
+++ b/src/main/java/cloudgene/mapred/database/updates/BcryptHashUpdate.java
@@ -8,8 +8,8 @@
import cloudgene.mapred.core.User;
import cloudgene.mapred.database.UserDao;
-import genepi.db.Database;
-import genepi.db.IUpdateListener;
+import cloudgene.mapred.database.util.Database;
+import cloudgene.mapred.database.util.IUpdateListener;
public class BcryptHashUpdate implements IUpdateListener {
diff --git a/src/main/java/cloudgene/mapred/database/util/AbstractDatabaseConnector.java b/src/main/java/cloudgene/mapred/database/util/AbstractDatabaseConnector.java
new file mode 100644
index 00000000..2bb0b28c
--- /dev/null
+++ b/src/main/java/cloudgene/mapred/database/util/AbstractDatabaseConnector.java
@@ -0,0 +1,81 @@
+package cloudgene.mapred.database.util;
+
+import org.apache.commons.dbcp.BasicDataSource;
+
+public abstract class AbstractDatabaseConnector implements DatabaseConnector {
+
+ private int maxActive = 10;
+
+ private int maxWait = 10000;
+
+ private boolean defaultAutoCommit = true;
+
+ private boolean testWhileIdle = true;
+
+ private int minEvictableIdleTimeMillis = 1800000;
+
+ private int timeBetweenEvictionRunsMillis = 1800000;
+
+ protected BasicDataSource createDataSource() {
+
+ BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setMaxActive(maxActive);
+ dataSource.setMaxWait(maxWait);
+ dataSource.setMaxIdle(maxActive);
+ dataSource.setDefaultAutoCommit(defaultAutoCommit);
+ dataSource.setTestWhileIdle(testWhileIdle);
+ dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+ dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+ return dataSource;
+
+ }
+
+ public int getMaxActive() {
+ return maxActive;
+ }
+
+ public void setMaxActive(int maxActive) {
+ this.maxActive = maxActive;
+ }
+
+ public int getMaxWait() {
+ return maxWait;
+ }
+
+ public void setMaxWait(int maxWait) {
+ this.maxWait = maxWait;
+ }
+
+ public boolean isDefaultAutoCommit() {
+ return defaultAutoCommit;
+ }
+
+ public void setDefaultAutoCommit(boolean defaultAutoCommit) {
+ this.defaultAutoCommit = defaultAutoCommit;
+ }
+
+ public boolean isTestWhileIdle() {
+ return testWhileIdle;
+ }
+
+ public void setTestWhileIdle(boolean testWhileIdle) {
+ this.testWhileIdle = testWhileIdle;
+ }
+
+ public int getMinEvictableIdleTimeMillis() {
+ return minEvictableIdleTimeMillis;
+ }
+
+ public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
+ this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ }
+
+ public int getTimeBetweenEvictionRunsMillis() {
+ return timeBetweenEvictionRunsMillis;
+ }
+
+ public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
+ this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ }
+
+}
diff --git a/src/main/java/cloudgene/mapred/database/util/Database.java b/src/main/java/cloudgene/mapred/database/util/Database.java
new file mode 100644
index 00000000..5902cdce
--- /dev/null
+++ b/src/main/java/cloudgene/mapred/database/util/Database.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (C) 2009-2016 Lukas Forer and Sebastian Schönherr
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ ******************************************************************************/
+
+package cloudgene.mapred.database.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Database
+ *
+ * @author Lukas Forer
+ *
+ */
+public class Database {
+
+ private static final Log log = LogFactory.getLog(Database.class);
+
+ private DatabaseConnector connector;
+
+ public Database() {
+ }
+
+ public void connect(DatabaseConnector connector) throws SQLException {
+ this.connector = connector;
+ try {
+
+ connector.connect();
+
+ log.debug("Establish connection successful");
+
+ fireChangeEvent(DatabaseListener.AFTER_CONNECTION);
+ } catch (SQLException e) {
+ log.error("Establish connection failed", e);
+ throw e;
+ }
+ }
+
+ public void disconnect() throws SQLException {
+
+ if (connector != null) {
+
+ if (connector.getDataSource() != null) {
+
+ log.debug("Disconnecting");
+
+ fireChangeEvent(DatabaseListener.BEFORE_DISCONNECTION);
+ try {
+
+ connector.disconnect();
+
+ log.debug("Disconnection successful");
+ fireChangeEvent(DatabaseListener.AFTER_DISCONNECTION);
+ } catch (SQLException e) {
+ log.error("Disconnection failed", e);
+ throw e;
+ }
+ }
+
+ }
+ }
+
+ public boolean isConnected() {
+ if (connector != null) {
+ return !connector.getDataSource().isClosed();
+ } else {
+ return false;
+ }
+ }
+
+ public BasicDataSource getDataSource() {
+ return connector.getDataSource();
+ }
+
+ /*
+ * ListenerSupport
+ */
+
+ private Vector listeners = new Vector();
+
+ public void addDatabaseListener(DatabaseListener listener) {
+ if (!listeners.contains(listener)) {
+ listeners.add(listener);
+ }
+ }
+
+ public void removeDatabaseListener(DatabaseListener listener) {
+ listeners.remove(listener);
+ }
+
+ private void fireChangeEvent(int event) {
+ Iterator iter = listeners.iterator();
+ while (iter.hasNext()) {
+ (iter.next()).onDatabaseEvent(event);
+ }
+ }
+
+ public void executeSQL(InputStream is) throws SQLException, IOException,
+ URISyntaxException {
+ connector.executeSQL(is);
+ }
+
+ public DatabaseConnector getConnector() {
+ return connector;
+ }
+
+}
diff --git a/src/main/java/cloudgene/mapred/database/util/DatabaseConnector.java b/src/main/java/cloudgene/mapred/database/util/DatabaseConnector.java
new file mode 100644
index 00000000..d95978e5
--- /dev/null
+++ b/src/main/java/cloudgene/mapred/database/util/DatabaseConnector.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (C) 2009-2016 Lukas Forer and Sebastian Schönherr
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ ******************************************************************************/
+
+package cloudgene.mapred.database.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.sql.SQLException;
+
+import org.apache.commons.dbcp.BasicDataSource;
+
+public interface DatabaseConnector {
+
+ public void connect() throws SQLException;
+
+ public void disconnect() throws SQLException;
+
+ public BasicDataSource getDataSource();
+
+ public void executeSQL(InputStream is) throws SQLException, IOException,
+ URISyntaxException;
+
+ public String getSchema();
+
+ boolean existsTable(String table) throws SQLException;
+}
+
diff --git a/src/main/java/cloudgene/mapred/database/util/DatabaseConnectorFactory.java b/src/main/java/cloudgene/mapred/database/util/DatabaseConnectorFactory.java
index 1bd9a1eb..b49f7cbd 100644
--- a/src/main/java/cloudgene/mapred/database/util/DatabaseConnectorFactory.java
+++ b/src/main/java/cloudgene/mapred/database/util/DatabaseConnectorFactory.java
@@ -2,9 +2,8 @@
import java.util.Map;
-import genepi.db.DatabaseConnector;
-import genepi.db.h2.H2Connector;
-import genepi.db.mysql.MySqlConnector;
+import cloudgene.mapred.database.util.h2.H2Connector;
+import cloudgene.mapred.database.util.mysql.MySqlConnector;
public class DatabaseConnectorFactory {
diff --git a/src/main/java/cloudgene/mapred/database/util/DatabaseListener.java b/src/main/java/cloudgene/mapred/database/util/DatabaseListener.java
new file mode 100644
index 00000000..96fabb57
--- /dev/null
+++ b/src/main/java/cloudgene/mapred/database/util/DatabaseListener.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (C) 2009-2016 Lukas Forer and Sebastian Schönherr
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ ******************************************************************************/
+
+package cloudgene.mapred.database.util;
+
+public interface DatabaseListener {
+
+ public static final int AFTER_CONNECTION = 1;
+ public static final int AFTER_DISCONNECTION = 2;
+ public static final int BEFORE_DISCONNECTION = 3;
+ public static final int ERROR = 4;
+
+ public void onDatabaseEvent(int event);
+
+}
diff --git a/src/main/java/cloudgene/mapred/database/util/DatabaseUpdater.java b/src/main/java/cloudgene/mapred/database/util/DatabaseUpdater.java
new file mode 100644
index 00000000..31c90d35
--- /dev/null
+++ b/src/main/java/cloudgene/mapred/database/util/DatabaseUpdater.java
@@ -0,0 +1,378 @@
+/*******************************************************************************
+ * Copyright (C) 2009-2016 Lukas Forer and Sebastian Schönherr
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ ******************************************************************************/
+
+package cloudgene.mapred.database.util;
+
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URISyntaxException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import genepi.io.FileUtil;
+
+public class DatabaseUpdater {
+
+ protected static final Log log = LogFactory.getLog(DatabaseUpdater.class);
+
+ private DatabaseConnector connector;
+
+ private Database database;
+
+ private String oldVersion;
+
+ private String currentVersion;
+
+ private String filename;
+
+ private InputStream updateFileAsStream;
+
+ private boolean needUpdate = false;
+
+ private Map listeners = new HashMap();
+
+ public DatabaseUpdater(Database database, String filename, InputStream updateFileAsStream, String currentVersion) {
+
+ this.filename = filename;
+ this.database = database;
+ this.connector = database.getConnector();
+ this.updateFileAsStream = updateFileAsStream;
+ this.currentVersion = currentVersion;
+
+ if (isVersionTableAvailable(database)) {
+
+ oldVersion = readVersionDB();
+ log.info("Read current DB version: " + oldVersion);
+
+ // should not happen, since an entry is created when metadata table
+ // exists
+ if (oldVersion == null) {
+ oldVersion = readVersion(filename);
+ log.info("Read curent version from DB was not successful, read it from file: " + oldVersion);
+ }
+
+ } else {
+ // check also file for backwards compatibility
+ oldVersion = readVersion(filename);
+ log.info("Read current version from file: " + oldVersion);
+ }
+ log.info("Current app version: " + currentVersion);
+ needUpdate = (compareVersion(currentVersion, oldVersion) > 0);
+
+ }
+
+ public void addUpdate(String version, IUpdateListener listener) {
+ listeners.put(version, listener);
+ }
+
+ public boolean updateDB() {
+
+ if (needUpdate()) {
+ log.info("Database needs update...");
+ if (!update()) {
+ log.error("Updating database failed.");
+ try {
+ database.disconnect();
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return false;
+ }
+ log.info("Update database done.");
+ } else {
+ log.info("Database is already up-to-date.");
+ if (!isVersionTableAvailable(database)) {
+ writeVersion(currentVersion);
+ }
+ }
+
+ String dbVersion = readVersionDB();
+ if (!dbVersion.equals(currentVersion)) {
+ log.error("App version (v" + currentVersion + ") and DB version (v" + dbVersion
+ + ") does not match. Update Application to latest version.");
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean update() {
+ if (needUpdate) {
+
+ log.info("Updating database from " + oldVersion + " to " + currentVersion + "...");
+
+ try {
+ readAndPrepareSqlClasspath(updateFileAsStream, oldVersion, currentVersion);
+ } catch (IOException | URISyntaxException | SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ // check if DB version match with Main version
+ if (isVersionTableAvailable(database)) {
+ String currentDBVersion = readVersionDB();
+ if ((compareVersion(currentVersion, currentDBVersion) > 0)) {
+ writeVersion(currentVersion);
+ }
+ } else {
+ writeVersion(currentVersion);
+ }
+
+ log.info("Updating database was successful.");
+
+ }
+
+ return true;
+
+ }
+
+ public boolean needUpdate() {
+ return needUpdate;
+ }
+
+ public void writeVersion(String newVersion) {
+
+ try {
+
+ if (!isVersionTableAvailable(database)) {
+ createVersionTable(database);
+ }
+
+ Connection connection = connector.getDataSource().getConnection();
+ PreparedStatement ps = connection.prepareStatement("INSERT INTO database_versions (version) VALUES (?)");
+ ps.setString(1, newVersion);
+ ps.executeUpdate();
+ log.info("Version in DB updated to: " + newVersion);
+
+ if (new File(filename).exists()) {
+ FileUtil.deleteFile(filename);
+ log.info("Deleted version.txt on file system.");
+ }
+
+ connection.close();
+
+ } catch (SQLException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ }
+
+ public String readVersion(String versionFile) {
+
+ File file = new File(versionFile);
+
+ if (file.exists()) {
+
+ try {
+
+ return readFileAsString(versionFile);
+
+ } catch (Exception e) {
+
+ return "0.0.0";
+
+ }
+
+ } else {
+
+ return "0.0.0";
+
+ }
+
+ }
+
+ public String readVersionDB() {
+
+ String version = null;
+
+ try {
+ Connection connection = connector.getDataSource().getConnection();
+ PreparedStatement ps = connection.prepareStatement(
+ "select version from database_versions where updated_on = (SELECT MAX(updated_on) from database_versions) "
+ + "order by updated_on, id DESC");
+ ResultSet result = ps.executeQuery();
+
+ if (result.next()) {
+ version = result.getString(1);
+ }
+
+ connection.close();
+
+ } catch (SQLException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ return version;
+ }
+
+ public static String readFileAsString(String filename) throws java.io.IOException, URISyntaxException {
+
+ InputStream is = new FileInputStream(filename);
+
+ DataInputStream in = new DataInputStream(is);
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+ String strLine;
+ StringBuilder builder = new StringBuilder();
+ while ((strLine = br.readLine()) != null) {
+ // builder.append("\n");
+ builder.append(strLine);
+ }
+
+ in.close();
+
+ return builder.toString();
+ }
+
+ public String readAndPrepareSqlClasspath(InputStream filestream, String minVersion, String maxVersion)
+ throws java.io.IOException, URISyntaxException, SQLException {
+
+ DataInputStream in = new DataInputStream(filestream);
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+ String strLine;
+ StringBuilder builder = new StringBuilder();
+ boolean reading = false;
+ String version = null;
+
+ while ((strLine = br.readLine()) != null) {
+
+ if (strLine.startsWith("--")) {
+
+ if (builder.length() > 0) {
+ executeSQLFile(builder.toString(), version);
+ builder.setLength(0);
+ IUpdateListener listener = listeners.get(version);
+ if (listener != null) {
+ listener.afterUpdate(database);
+ }
+ }
+
+ version = strLine.replace("--", "").trim();
+ reading = (compareVersion(version, minVersion) > 0 && compareVersion(version, maxVersion) <= 0);
+ if (reading) {
+ log.info("Loading SQL update for version " + version);
+ IUpdateListener listener = listeners.get(version);
+ if (listener != null) {
+ listener.beforeUpdate(database);
+ }
+ }
+
+ } else if (reading && !strLine.trim().isEmpty()) {
+ builder.append("\n");
+ builder.append(strLine);
+ }
+ }
+
+ // last block
+ executeSQLFile(builder.toString(), version);
+
+ in.close();
+
+ return builder.toString();
+
+ }
+
+ public void executeSQLFile(String sqlContent, String version) throws SQLException {
+
+ if (sqlContent.length() > 0) {
+ Connection connection;
+ connection = connector.getDataSource().getConnection();
+ PreparedStatement ps = connection.prepareStatement(sqlContent);
+ ps.executeUpdate();
+ connection.close();
+ log.info("DB SQL Update " + version + " finished");
+ writeVersion(version);
+ }
+
+ }
+
+ public static int compareVersion(String version1, String version2) {
+
+ String parts1[] = version1.split("-", 2);
+ String parts2[] = version2.split("-", 2);
+
+ String tiles1[] = parts1[0].split("\\.");
+ String tiles2[] = parts2[0].split("\\.");
+
+ for (int i = 0; i < tiles1.length; i++) {
+ int number1 = Integer.parseInt(tiles1[i].trim());
+ int number2 = Integer.parseInt(tiles2[i].trim());
+
+ if (number1 != number2) {
+
+ return number1 > number2 ? 1 : -1;
+
+ }
+
+ }
+
+ if (parts1.length > 1) {
+ if (parts2.length > 1) {
+ return parts1[1].compareTo(parts2[1]);
+ } else {
+ return -1;
+ }
+ } else {
+ if (parts2.length > 1) {
+ return 1;
+ }
+ }
+
+ return 0;
+
+ }
+
+ public boolean isVersionTableAvailable(Database database) {
+ try {
+ return database.getConnector().existsTable("database_versions");
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public void createVersionTable(Database database) {
+ try {
+ Connection connection = connector.getDataSource().getConnection();
+ String statement = "create table database_versions ( \r\n"
+ + " id integer not null auto_increment primary key,\r\n"
+ + " version varchar(255) not null,\r\n"
+ + " updated_on timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP \r\n" + ")";
+ PreparedStatement ps = connection.prepareStatement(statement);
+ ps.executeUpdate();
+ connection.close();
+ log.info("Table database_versions created.");
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/cloudgene/mapred/database/util/Fixtures.java b/src/main/java/cloudgene/mapred/database/util/Fixtures.java
index ebbce4d1..bb9bd12e 100644
--- a/src/main/java/cloudgene/mapred/database/util/Fixtures.java
+++ b/src/main/java/cloudgene/mapred/database/util/Fixtures.java
@@ -8,7 +8,6 @@
import cloudgene.mapred.database.UserDao;
import cloudgene.mapred.util.HashUtil;
import cloudgene.mapred.util.Template;
-import genepi.db.Database;
public class Fixtures {
diff --git a/src/main/java/cloudgene/mapred/database/util/GroupedListHandler.java b/src/main/java/cloudgene/mapred/database/util/GroupedListHandler.java
new file mode 100644
index 00000000..cea1f679
--- /dev/null
+++ b/src/main/java/cloudgene/mapred/database/util/GroupedListHandler.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (C) 2009-2016 Lukas Forer and Sebastian Schönherr
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ ******************************************************************************/
+
+package cloudgene.mapred.database.util;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.commons.dbutils.ResultSetHandler;
+
+public class GroupedListHandler implements ResultSetHandler