kustvakt extension db merge and maven build for light version
diff --git a/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java b/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
index 42aa8c7..028a9f4 100644
--- a/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
+++ b/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
@@ -17,7 +17,7 @@
*/
public class BeanConfiguration {
- private static final String config_file = "default-config.xml";
+ private static final String config_file = "light-config.xml";
public static final String KUSTVAKT_DB = "kustvakt_db";
public static final String KUSTVAKT_ENCRYPTION = "kustvakt_encryption";
diff --git a/src/main/java/de/ids_mannheim/korap/config/ParamFields.java b/src/main/java/de/ids_mannheim/korap/config/ParamFields.java
new file mode 100644
index 0000000..f796ca7
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/config/ParamFields.java
@@ -0,0 +1,41 @@
+package de.ids_mannheim.korap.config;
+
+import lombok.Getter;
+
+import java.util.Collection;
+import java.util.HashMap;
+
+/**
+ * @author hanl
+ * @date 21/07/2015
+ */
+// could also be an array or list!
+public class ParamFields extends HashMap<String, ParamFields.Param> {
+
+ public void add(Param param) {
+ this.put(Param.class.getName(), param);
+ }
+
+ public <T extends Param> T get(Class<T> cl) {
+ return (T) this.get(cl.getName());
+ }
+
+ public <T extends Param> T remove(Class<T> cl) {
+ return (T) this.remove(cl.getName());
+ }
+
+ public void addAll(Collection<Param> params) {
+ for (Param p : params)
+ super.put(p.getClass().getName(), p);
+ }
+
+ @Getter
+ public abstract static class Param {
+
+ public boolean hasValues(){
+ return false;
+ }
+
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/KorAPException.java b/src/main/java/de/ids_mannheim/korap/exceptions/KorAPException.java
deleted file mode 100644
index d3435f7..0000000
--- a/src/main/java/de/ids_mannheim/korap/exceptions/KorAPException.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package de.ids_mannheim.korap.exceptions;
-
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * @author hanl
- * @date 11/12/2013
- */
-//fixme: redundant with baseexception
-@Deprecated
-@Setter
-@Getter
-public class KorAPException extends BaseException {
-
- private String userid;
-
- public KorAPException(Integer status) {
- super(status);
- }
-
- public KorAPException(Object userid, Integer status) {
- this(status);
- this.userid = String.valueOf(userid);
- }
-
- public KorAPException(Object userid, Integer status, String message,
- String entity) {
- super(status, message, entity);
- this.userid = String.valueOf(userid);
- }
-
- public KorAPException(Integer status, String message, String entity) {
- super(status, message, entity);
- }
-
- public KorAPException(Throwable cause, Integer status) {
- super(cause, status);
- }
-
- public KorAPException(String message, Throwable cause, Integer status) {
- super(message, cause, status);
- }
-
- @Override
- public String toString() {
- return "Excpt{" +
- "status=" + getStatusCode() +
- ", message=" + getMessage() +
- ", args=" + getEntity() +
- ", userid=" + userid +
- '}';
- }
-}
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java b/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
new file mode 100644
index 0000000..1c0c5aa
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
@@ -0,0 +1,61 @@
+package de.ids_mannheim.korap.exceptions;
+
+import de.ids_mannheim.korap.auditing.AuditRecord;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author hanl
+ * @date 11/12/2013
+ */
+//fixme: redundant with baseexception
+@Deprecated
+@Setter
+@Getter
+public class KustvaktException extends Exception {
+
+ protected List<AuditRecord> records = new ArrayList<>();
+ private String userid;
+ private Integer statusCode;
+ private String entity;
+
+ public KustvaktException(Integer status) {
+ this.statusCode = status;
+ }
+
+ public KustvaktException(Object userid, Integer status) {
+ this(status);
+ this.userid = String.valueOf(userid);
+ }
+
+ public KustvaktException(Object userid, Integer status, String message,
+ String entity) {
+ super(status, message, entity);
+ this.userid = String.valueOf(userid);
+ }
+
+ public KustvaktException(Integer status, String message, String entity) {
+ super(status, message, entity);
+ }
+
+ public KustvaktException(Throwable cause, Integer status) {
+ super(cause, status);
+ }
+
+ public KustvaktException(String message, Throwable cause, Integer status) {
+ super(message, cause, status);
+ }
+
+ @Override
+ public String toString() {
+ return "Excpt{" +
+ "status=" + getStatusCode() +
+ ", message=" + getMessage() +
+ ", args=" + getEntity() +
+ ", userid=" + userid +
+ '}';
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/BatchBuilder.java b/src/main/java/de/ids_mannheim/korap/handlers/BatchBuilder.java
new file mode 100644
index 0000000..17f3616
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/BatchBuilder.java
@@ -0,0 +1,70 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.utils.KustvaktLogger;
+import org.slf4j.Logger;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.JdbcOperations;
+import org.springframework.jdbc.core.RowMapper;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author hanl
+ * @date 24/03/2014
+ */
+public class BatchBuilder {
+
+ private static final int SINGLE_BATCH = 1;
+ private static final int SMALL_BATCH = 4;
+ private static final int SMALL_MEDIUM_BATCH = 6;
+ private static final int MEDIUM_BATCH = 8;
+ private static final int LARGE_BATCH = 12;
+ private Logger log = KustvaktLogger.initiate(BatchBuilder.class);
+
+ private JdbcOperations operations;
+
+ public BatchBuilder(JdbcOperations operations) {
+ this.operations = operations;
+ }
+
+ public <T> List<T> selectFromIDs(String query, Collection ids, RowMapper<T> mapper) {
+ List l = new ArrayList(ids);
+ int size = ids.size();
+ List<T> values = new ArrayList<>();
+ while (size > 0) {
+ int batchSize = SINGLE_BATCH;
+ if (size >= LARGE_BATCH)
+ batchSize = LARGE_BATCH;
+ else if (size >= MEDIUM_BATCH)
+ batchSize = MEDIUM_BATCH;
+ else if (size >= SMALL_MEDIUM_BATCH)
+ batchSize = SMALL_MEDIUM_BATCH;
+ else if (size >= SMALL_BATCH)
+ batchSize = SMALL_BATCH;
+ size -= batchSize;
+ StringBuilder inClause = new StringBuilder();
+ for (int i = 0; i < batchSize; i++) {
+ inClause.append('?');
+ inClause.append(',');
+ }
+ inClause.deleteCharAt(inClause.length() - 1);
+ String sql = query + " (" + inClause.toString() + ");";
+ Object[] args = new Object[batchSize];
+ List d = new ArrayList();
+ for (int idx = 0; idx < batchSize; idx++) {
+ args[idx] = l.get(idx);
+ d.add(idx, args[idx]);
+ }
+ l.removeAll(d);
+ try {
+ values.addAll(this.operations.query(sql, args, mapper));
+ } catch (DataAccessException e) {
+ log.error("Exception during database retrieval", e);
+ }
+
+ }
+ return values;
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/CollectionDao.java b/src/main/java/de/ids_mannheim/korap/handlers/CollectionDao.java
new file mode 100644
index 0000000..7f4fb22
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/CollectionDao.java
@@ -0,0 +1,167 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.ext.interfaces.ResourceOperationIface;
+import de.ids_mannheim.korap.ext.resource.KorAPResource;
+import de.ids_mannheim.korap.ext.resource.VirtualCollection;
+import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.KustvaktLogger;
+import org.slf4j.Logger;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author hanl
+ * @date 11/01/2014
+ */
+
+//todo?! cache with ehcache and put token/sentence/paragraph numbers into cache
+public class CollectionDao
+ implements ResourceOperationIface<VirtualCollection> {
+
+ private static Logger log = KustvaktLogger.initiate(CollectionDao.class);
+ private BatchBuilder batchBuilder;
+ protected final NamedParameterJdbcTemplate jdbcTemplate;
+
+ public CollectionDao(PersistenceClient client) {
+ this.jdbcTemplate = (NamedParameterJdbcTemplate) client.getSource();
+ this.batchBuilder = new BatchBuilder(
+ this.jdbcTemplate.getJdbcOperations());
+ }
+
+ @Override
+ public Class<VirtualCollection> getType() {
+ return VirtualCollection.class;
+ }
+
+ // fixme: persistentid can be done, persistence is achieved by specifing a date until which documents
+ // are to be included. this excludes documents that are part of the "sperreinträge"
+ public <T extends KorAPResource> T findbyId(String id, User user)
+ throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("id", id);
+ source.addValue("user", user.getId());
+ final String sql = "select * from coll_store where persistentID=:id and userID=:user;";
+ try {
+ return (T) this.jdbcTemplate.queryForObject(sql, source,
+ new RowMapperFactory.CollectionMapper());
+ }catch (DataAccessException e) {
+ log.error("Exception during database get for id '" + id + "'", e);
+ return null;
+ }
+ }
+
+ public VirtualCollection findbyId(Integer id, User user)
+ throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("id", id);
+ final String sql = "select * from coll_store where id=:id";
+ try {
+ return this.jdbcTemplate.queryForObject(sql, source,
+ new RowMapperFactory.CollectionMapper());
+ }catch (DataAccessException e) {
+ log.error("Exception during database get for id '" + id + "'", e);
+ return null;
+ }
+ }
+
+ public int updateResource(VirtualCollection resource, User user)
+ throws KustvaktException {
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ np.addValue("id", resource.getPersistentID());
+ np.addValue("qy", resource.getQuery());
+ np.addValue("name", resource.getName());
+ np.addValue("desc", resource.getDescription());
+ final String sql = "UPDATE coll_store SET query=:qy, name=:name, description=:desc WHERE persistentID=:id;";
+ try {
+ return this.jdbcTemplate.update(sql, np);
+ }catch (DataAccessException e) {
+ log.error("Exception during database update for id '" + resource
+ .getId() + "'", e);
+ throw new KustvaktException(e, StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ public int[] updateResources(List<VirtualCollection> resources, User user)
+ throws KustvaktException {
+ MapSqlParameterSource[] sources = new MapSqlParameterSource[resources
+ .size()];
+ final String sql = "UPDATE coll_store SET query=:qy, name=:name, description=:desc WHERE persistentID=:id;";
+ int i = 0;
+ for (VirtualCollection c : resources) {
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ np.addValue("id", c.getPersistentID());
+ np.addValue("qy", c.getQuery());
+ np.addValue("name", c.getName());
+ np.addValue("desc", c.getDescription());
+ sources[i++] = np;
+ }
+ try {
+ return this.jdbcTemplate.batchUpdate(sql, sources);
+ }catch (DataAccessException e) {
+ log.error("Exception during database update", e);
+ throw new KustvaktException(e, StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ @Override
+ public int storeResource(VirtualCollection resource, User user)
+ throws KustvaktException {
+ if (resource.getQuery().length() > 3) {
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ np.addValue("query", resource.getQuery());
+ np.addValue("pid", resource.getPersistentID());
+ np.addValue("name", resource.getName());
+ np.addValue("desc", resource.getDescription());
+ np.addValue("us", user.getId());
+
+ final String sql =
+ "INSERT INTO coll_store (persistentID, name, description, userID, query) "
+ + "VALUES (:pid, :name, :desc, :us, :query);";
+ try {
+ return this.jdbcTemplate.update(sql, np);
+ }catch (DataAccessException e) {
+ log.error("Exception during database store for id '" + resource
+ .getId() + "'", e);
+ throw new KustvaktException(e, StatusCodes.CONNECTION_ERROR);
+ }
+ }else
+ throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+ "invalid query parameter", resource.getQuery());
+ }
+
+ public int deleteResource(String id, User user) throws KustvaktException {
+ //todo: foreign key and on delete cascade does not work currently!
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ np.addValue("id", id);
+ np.addValue("user", user.getId());
+ // final String sql = "DELETE FROM coll_store cs inner join r_store rs on rs.id=cs.id WHERE rs.persistentID=:id;";
+ final String sql = "DELETE FROM coll_store where persistentID=:id and user=:user;";
+ try {
+ return this.jdbcTemplate.update(sql, np);
+ }catch (DataAccessException e) {
+ log.error("Exception during database delete for id '" + id + "'",
+ e);
+ throw new KustvaktException(e, StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ //todo: adjust to resource id input (batch operation!)
+ // fixme: test
+ public List<VirtualCollection> getResources(Collection<Object> resources,
+ User user) throws KustvaktException {
+ final String sql1 = "SELECT * from coll_store where id in";
+ // final String sql =
+ // "SELECT rs.*, rt.name_path, cs.query FROM r_store as rs inner join r_tree as rt on rs.id=rt.childID "
+ // + "inner join coll_store as cs on cs.id=rs.id WHERE rs.id in";
+ return batchBuilder.selectFromIDs(sql1, resources,
+ new RowMapperFactory.CollectionMapper());
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/DocumentDao.java b/src/main/java/de/ids_mannheim/korap/handlers/DocumentDao.java
new file mode 100644
index 0000000..111c282
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/DocumentDao.java
@@ -0,0 +1,183 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.ext.interfaces.ResourceOperationIface;
+import de.ids_mannheim.korap.ext.resource.Document;
+import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.BooleanUtils;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.ResultSetExtractor;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author hanl
+ * @date 05/11/2014
+ */
+// todo: testing!
+// todo: error handling
+public class DocumentDao implements ResourceOperationIface<Document> {
+
+ private NamedParameterJdbcTemplate jdbcTemplate;
+
+ public DocumentDao(PersistenceClient client) {
+ this.jdbcTemplate = (NamedParameterJdbcTemplate) client.getSource();
+ }
+
+ @Override
+ public Class<Document> getType() {
+ return Document.class;
+ }
+
+ @Override
+ public Document findbyId(Integer id, User user) throws KustvaktException {
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("id", id);
+ String sql = "select * from doc_store where id=:id";
+ try {
+ return this.jdbcTemplate
+ .query(sql, s, new ResultSetExtractor<Document>() {
+ @Override
+ public Document extractData(ResultSet rs)
+ throws SQLException, DataAccessException {
+ Document doc = new Document(
+ rs.getString("persistentID"));
+ doc.setId(rs.getInt("id"));
+ doc.setCreated(
+ rs.getTimestamp("created").getTime());
+ doc.setDisabled(rs.getBoolean("disabled"));
+ return doc;
+ }
+ });
+ }catch (DataAccessException e) {
+ throw new KustvaktException(StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ // document id, consisting of corpus sigle, substring key and document number
+ @Override
+ public Document findbyId(String id, User user) throws KustvaktException {
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("id", id);
+ String sql = "select * from doc_store where persistentID=:id";
+
+ try {
+ return this.jdbcTemplate
+ .query(sql, s, new ResultSetExtractor<Document>() {
+ @Override
+ public Document extractData(ResultSet rs)
+ throws SQLException, DataAccessException {
+ Document doc = new Document(
+ rs.getString("persistentID"));
+ doc.setId(rs.getInt("id"));
+ doc.setCreated(
+ rs.getTimestamp("created").getTime());
+ doc.setDisabled(rs.getBoolean("disabled"));
+ return doc;
+ }
+ });
+ }catch (DataAccessException e) {
+ throw new KustvaktException(StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ @Override
+ public List<Document> getResources(Collection<Object> ids, User user)
+ throws KustvaktException {
+ return null;
+ }
+
+ @Override
+ public int updateResource(Document document, User user)
+ throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("pid", document.getPersistentID());
+ source.addValue("dis", BooleanUtils.getBoolean(document.isDisabled()));
+ final String sql = "UPDATE doc_store set disabled=:dis where persistentID=:pid;";
+ return this.jdbcTemplate.update(sql, source);
+ }
+
+ @Override
+ public int[] updateResources(List<Document> resources, User user)
+ throws KustvaktException {
+ return new int[0];
+ }
+
+ public List<Document> findbyCorpus(String corpus, int offset, int index)
+ throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("corpus", corpus + "%");
+ source.addValue("offset", (offset * index));
+ source.addValue("limit", offset);
+ final String sql = "select * from doc_store where (persistentID like :corpus) limit :offset, :limit";
+ try {
+ return this.jdbcTemplate
+ .query(sql, source, new RowMapper<Document>() {
+ @Override
+ public Document mapRow(ResultSet rs, int rowNum)
+ throws SQLException {
+ Document doc = new Document(
+ rs.getString("persistentID"));
+ doc.setId(rs.getInt("id"));
+ doc.setDisabled(rs.getBoolean("disabled"));
+ return doc;
+ }
+ });
+ }catch (DataAccessException e) {
+ throw new KustvaktException(StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ public List<String> findbyCorpus(String corpus, boolean disabled)
+ throws KustvaktException {
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("corpus", corpus + "%");
+ s.addValue("dis", BooleanUtils.getBoolean(disabled));
+ String sql = "SELECT persistentID FROM doc_store WHERE (persistentID like :corpus) AND disabled=:dis;";
+ try {
+ return this.jdbcTemplate.queryForList(sql, s, String.class);
+ }catch (DataAccessException e) {
+ e.printStackTrace();
+ throw new KustvaktException(StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ // parent is disabled here
+ @Override
+ public int storeResource(Document resource, User user)
+ throws KustvaktException {
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("id", resource.getPersistentID());
+ s.addValue("corpus", resource.getCorpus());
+ s.addValue("dis", BooleanUtils.getBoolean(resource.isDisabled()));
+
+ String sql = "INSERT INTO doc_store (persistentID, disabled) VALUES (:id, :dis)";
+ try {
+ return this.jdbcTemplate.update(sql, s);
+ }catch (DataAccessException e) {
+ throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+ "illegal argument given", resource.getPersistentID());
+ }
+ }
+
+ @Override
+ public int deleteResource(String id, User user) throws KustvaktException {
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("id", id);
+ String sql = "delete from doc_store where persistentID=:id;";
+ try {
+ return this.jdbcTemplate.update(sql, s);
+ }catch (DataAccessException e) {
+ throw new KustvaktException(StatusCodes.CONNECTION_ERROR);
+ }
+
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
new file mode 100644
index 0000000..fa29e59
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
@@ -0,0 +1,475 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.config.ParamFields;
+import de.ids_mannheim.korap.config.URIParam;
+import de.ids_mannheim.korap.exceptions.EmptyResultException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.interfaces.EntityHandlerIface;
+import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.user.*;
+import de.ids_mannheim.korap.utils.BooleanUtils;
+import de.ids_mannheim.korap.utils.KustvaktLogger;
+import de.ids_mannheim.korap.utils.TimeUtils;
+import org.slf4j.Logger;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+
+import java.sql.Date;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author hanl
+ * @date 13/01/2014
+ */
+public class EntityDao implements EntityHandlerIface {
+
+ private static Logger jlog = KustvaktLogger.initiate(EntityDao.class);
+ private NamedParameterJdbcTemplate jdbcTemplate;
+
+ public EntityDao(PersistenceClient client) {
+ this.jdbcTemplate = (NamedParameterJdbcTemplate) client.getSource();
+ }
+
+ @Override
+ public UserSettings getUserSettings(Integer userid) throws
+ KustvaktException {
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ np.addValue("us", userid);
+ final String sql =
+ "SELECT user.* FROM user_settings as user inner join korap_users as a "
+ + "on a.id=user.user_id WHERE user.user_id=:us";
+ try {
+ Map s = this.jdbcTemplate.queryForMap(sql, np);
+ return UserSettings.fromObjectMap(s);
+ }catch (EmptyResultDataAccessException ex) {
+ return new UserSettings();
+ }catch (DataAccessException e) {
+ jlog.error("Could not retrieve user settings for user: " + userid,
+ e);
+ throw new dbException(userid, "user_settings",
+ StatusCodes.DB_GET_FAILED, userid.toString());
+ }
+ }
+
+ @Override
+ public int updateSettings(UserSettings settings) throws KustvaktException {
+ final String sql =
+ "UPDATE user_settings SET fileNameForExport=:fileNameForExport,"
+ +
+ "leftContextItemForExport=:leftContextItemForExport," +
+ "leftContextSizeForExport=:leftContextSizeForExport,locale=:locale,leftContextItem=:leftContextItem,"
+ +
+ "leftContextSize=:leftContextSize," +
+ "rightContextItem=:rightContextItem,rightContextItemForExport=:rightContextItemForExport,"
+ +
+ "rightContextSize=:rightContextSize," +
+ "POSFoundry=:defaultPOSfoundry, lemmaFoundry=:defaultLemmafoundry, constFoundry=:defaultConstfoundry, "
+ +
+ "relFoundry=:defaultRelfoundry, " +
+ "rightContextSizeForExport=:rightContextSizeForExport,selectedCollection=:selectedCollection,queryLanguage=:queryLanguage,"
+ +
+ "pageLength=:pageLength,metadataQueryExpertModus=:metadataQueryExpertModus,collectData=:collectData "
+ +
+ "WHERE user_id=:userID";
+ try {
+ return this.jdbcTemplate
+ .update(sql, new BeanPropertySqlParameterSource(settings));
+ }catch (DataAccessException e) {
+ jlog.error("Could not update user settings for user: " + settings
+ .getUserID(), e);
+ throw new dbException(settings.getUserID(), "userSettings",
+ StatusCodes.DB_UPDATE_FAILED, settings.toString());
+ // throw new KorAPException(e, StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ /**
+ * @param settings
+ * @throws KustvaktException
+ */
+
+ private void createSettings(UserSettings settings) throws
+ KustvaktException {
+ final String sql =
+ "INSERT INTO user_settings (user_id, fileNameForExport,leftContextItemForExport,"
+ +
+ "leftContextSizeForExport,locale,leftContextItem,leftContextSize,"
+ +
+ "rightContextItem,rightContextItemForExport,rightContextSize,"
+ +
+ "rightContextSizeForExport,selectedCollection,queryLanguage,"
+ +
+ "pageLength,metadataQueryExpertModus, POSFoundry, lemmaFoundry, constFoundry, relFoundry, collectData) "
+ +
+ "VALUES (:userID, :fileNameForExport, :leftContextItemForExport, "
+ +
+ ":leftContextSizeForExport, :locale, :leftContextItem, :leftContextSize, "
+ +
+ ":rightContextItem,:rightContextItemForExport, :rightContextSize, "
+ +
+ ":rightContextSizeForExport, :selectedCollection, :queryLanguage, "
+ +
+ ":pageLength, :metadataQueryExpertModus, :defaultPOSfoundry, "
+ +
+ ":defaultLemmafoundry, :defaultConstfoundry, :defaultRelfoundry, :collectData);";
+
+ try {
+ if (settings == null)
+ throw new KustvaktException(StatusCodes.MISSING_ARGUMENTS,
+ "no settings provided", "user settings");
+ this.jdbcTemplate
+ .update(sql, new BeanPropertySqlParameterSource(settings));
+ }catch (DataAccessException e) {
+ jlog.error("Could not create user settings for user: " + settings
+ .getUserID(), e);
+ throw new dbException(settings.getUserID(), "userSettings",
+ StatusCodes.DB_INSERT_FAILED, settings.toString());
+ }
+ }
+
+ @Override
+ public UserDetails getUserDetails(Integer userid) throws KustvaktException {
+ final String sql = "SELECT us.* FROM user_details as us inner join korap_users as ku on ku.id=us.user_id WHERE us.user_id=:user";
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ np.addValue("user", userid);
+
+ try {
+ return this.jdbcTemplate
+ .queryForObject(sql, np, new RowMapper<UserDetails>() {
+ @Override
+ public UserDetails mapRow(ResultSet rs, int i)
+ throws SQLException {
+ UserDetails d = new UserDetails();
+ d.setUserID(rs.getInt("user_id"));
+ d.setAddress(rs.getString("address"));
+ d.setCountry(rs.getString("country"));
+ d.setEmail(rs.getString("email"));
+ d.setFirstName(rs.getString("firstName"));
+ d.setLastName(rs.getString("lastName"));
+ d.setGender(rs.getString("gender"));
+ d.setInstitution(rs.getString("institution"));
+ d.setPhone(rs.getString("phone"));
+ d.setPrivateUsage(rs.getBoolean("privateUsage"));
+ return d;
+ }
+ });
+ }catch (EmptyResultDataAccessException ex) {
+ //todo: create audit record?
+ return null;
+ }catch (DataAccessException e) {
+ jlog.error("Could not retrieve user details for user: " + userid,
+ e);
+ throw new dbException(userid, "userDetails",
+ StatusCodes.DB_GET_FAILED, userid.toString());
+ // throw new KorAPException(e, StatusCodes.CONNECTION_ERROR);
+ }
+ }
+
+ @Override
+ public int updateUserDetails(UserDetails details) throws KustvaktException {
+ final String up =
+ "UPDATE user_details SET firstName=:firstName, lastName=:lastName, "
+ +
+ "gender=:gender, phone=:phone, institution=:institution, "
+ +
+ "email=:email, address=:address, country=:country, privateUsage=:privateUsage "
+ +
+ "WHERE userID=:userID;";
+ try {
+ return this.jdbcTemplate
+ .update(up, new BeanPropertySqlParameterSource(details));
+ }catch (DataAccessException e) {
+ jlog.error("Could not retrieve user details for user: " + details
+ .getUserID(), e);
+ // throw new KorAPException(e, StatusCodes.CONNECTION_ERROR);
+ throw new dbException(details.getUserID(), "userDetails",
+ StatusCodes.DB_UPDATE_FAILED, details.toString());
+ }
+ }
+
+ private void createUserDetails(UserDetails details) throws
+ KustvaktException {
+ final String up =
+ "INSERT INTO user_details (user_id, firstName, lastName, gender, phone, institution, "
+ +
+ "email, address, country, privateUsage) VALUES (:userID, :firstName, :lastName, :gender, "
+ +
+ ":phone, :institution, :email, :address, :country, :privateUsage);";
+ try {
+ if (details == null)
+ throw new KustvaktException(StatusCodes.MISSING_ARGUMENTS,
+ "no details provided", "user details");
+ this.jdbcTemplate
+ .update(up, new BeanPropertySqlParameterSource(details));
+ }catch (DataAccessException e) {
+ jlog.error("Could not create user details for user: " + details
+ .getUserID(), e);
+ throw new dbException(details.getUserID(), "userDetails",
+ StatusCodes.DB_INSERT_FAILED, details.toString());
+ }
+ }
+
+ // usersettings are fetched plus basic account info, no details, since i rarely use them anyway!
+ @Override
+ public User getAccount(String username)
+ throws KustvaktException {
+ Map<String, String> namedParameters = Collections
+ .singletonMap("username", username);
+ final String sql = "select a.* from korap_users as a where a.username=:username;";
+ User user;
+ try {
+ user = this.jdbcTemplate.queryForObject(sql, namedParameters,
+ new RowMapperFactory.UserMapper());
+ }catch (EmptyResultDataAccessException ae) {
+ jlog.error("No user found for name '{}'", username);
+ throw new EmptyResultException(username);
+ }catch (DataAccessException e) {
+ jlog.error("Could not retrieve user for name: " + username, e);
+ throw new dbException(username, "korap_users",
+ StatusCodes.DB_GET_FAILED, username);
+ }
+ // todo: set null!?!
+ //todo: test this
+ return user;
+ }
+
+ @Override
+ public int updateAccount(User user) throws KustvaktException {
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ final String query;
+ if (user instanceof KorAPUser) {
+ KorAPUser k = (KorAPUser) user;
+ np.addValue("ali", k.getAccountLink());
+ np.addValue("alo", k.isAccountLocked());
+ if (k.getPassword() != null)
+ np.addValue("ps", k.getPassword());
+ URIParam param = k.getField(URIParam.class);
+ if (param != null) {
+ np.addValue("frag", param.getUriFragment());
+ np.addValue("exp", new Date(param.getUriExpiration()));
+ }
+ np.addValue("id", k.getId());
+
+ query = "UPDATE korap_users SET accountLock=:alo," +
+ "accountLink=:ali, password=:ps," +
+ "uri_fragment=:frag," +
+ "uri_expiration=:exp WHERE id=:id";
+ }else if (user instanceof ShibUser) {
+ ShibUser s = (ShibUser) user;
+ //todo:
+ // np.addValue("ali", s.getAccountLink());
+ np.addValue("ali", null);
+ np.addValue("edu", s.getAffiliation());
+ np.addValue("id", s.getId());
+ np.addValue("cn", s.getCn());
+ np.addValue("mail", s.getMail());
+
+ query = "UPDATE shibusers SET AccountLink=:ali" +
+ " eduPersonScopedAffiliation=:edu" +
+ "mail=:mail, cn=:cn WHERE id=:id";
+ }else
+ return -1;
+ try {
+ return this.jdbcTemplate.update(query, np);
+ }catch (DataAccessException e) {
+ jlog.error(
+ "Could not update user account for user: " + user.getId(),
+ e);
+ // throw new KorAPException(e, StatusCodes.CONNECTION_ERROR);
+ throw new dbException(user.getId(), "korap_users",
+ StatusCodes.DB_UPDATE_FAILED, user.toString());
+ }
+ }
+
+ @Override
+ public int createAccount(User user) throws KustvaktException {
+ final String query;
+ MapSqlParameterSource np = new MapSqlParameterSource();
+
+ if (user instanceof KorAPUser) {
+ final KorAPUser k = (KorAPUser) user;
+
+ URIParam param = k.getField(URIParam.class);
+ np.addValue("us", k.getUsername());
+ np.addValue("alo", k.isAccountLocked());
+ np.addValue("ali", k.getAccountLink());
+ np.addValue("ps", k.getPassword());
+ if (param != null) {
+ np.addValue("uri", param.getUriFragment());
+ np.addValue("urie", new Date(param.getUriExpiration()));
+ }else {
+ np.addValue("uri", null);
+ np.addValue("urie", null);
+ }
+
+ np.addValue("acr", k.getAccountCreation());
+ np.addValue("id", k.getId());
+
+ if (user.getId() != -1)
+ query = "INSERT INTO korap_users (id, username, accountLock, " +
+ "accountLink, password, uri_fragment, " +
+ "accountCreation, " +
+ "uri_expiration) VALUES (:id, :us, :alo, :ali, " +
+ ":ps, :uri, :acr, :urie);";
+ else
+ query = "INSERT INTO korap_users (username, accountLock, " +
+ "accountLink, password, uri_fragment, " +
+ "accountCreation, " +
+ "uri_expiration) VALUES (:us, :alo, :ali, " +
+ ":ps, :uri, :acr, :urie);";
+
+ //fixme: still applicable?
+ }else if (user instanceof ShibUser) {
+ ShibUser s = (ShibUser) user;
+ query = "INSERT INTO shibusers (username, type, accountLink " +
+ "eduPersonScopedAffiliation, accountCreation, cn, mail) " +
+ "VALUES (:us, :type, :ali, " +
+ ":edu, :acr, :cn, :mail, :logs, :logft);";
+ np.addValue("us", s.getUsername());
+ // np.addValue("ali", s.getAccountLink());
+ np.addValue("ali", null);
+ np.addValue("edu", s.getAffiliation());
+ np.addValue("mail", s.getMail());
+ np.addValue("type", user.getType());
+ np.addValue("cn", s.getCn());
+ np.addValue("acr", new Date(TimeUtils.getNow().getMillis()));
+
+ //todo: disable after first intro
+ }else if (user instanceof DemoUser) {
+ query = "INSERT INTO korap_users (username, type, accountLock, " +
+ "password, uri_fragment, " +
+ "accountCreation, uri_expiration) VALUES (:us, :type, :alo, "
+ +
+ ":ps, :uri, :acr, :urie);";
+
+ np.addValue("us", user.getUsername());
+ np.addValue("type", user.getType());
+ // np.addValue("ali", user.getAccountLink());
+ np.addValue("ali", null);
+ np.addValue("alo", user.isAccountLocked());
+ np.addValue("urie", new Date(0));
+ np.addValue("ps", DemoUser.PASSPHRASE);
+ np.addValue("uri", "");
+ np.addValue("acr", new Date(TimeUtils.getNow().getMillis()));
+ }else
+ return -1;
+
+ KeyHolder holder = new GeneratedKeyHolder();
+
+ try {
+ int r = this.jdbcTemplate
+ .update(query, np, holder, new String[] { "id" });
+ user.setId(holder.getKey().intValue());
+
+ if (user.getDetails() == null)
+ user.setDetails(new UserDetails());
+ if (user.getSettings() == null)
+ user.setSettings(new UserSettings());
+
+ this.createUserDetails(user.getDetails());
+ this.createSettings(user.getSettings());
+ return r;
+ }catch (DataAccessException e) {
+ e.printStackTrace();
+ jlog.error("Could not create user account with username: {}",
+ user.getUsername());
+ throw new dbException(user.getUsername(), "korap_users",
+ StatusCodes.NAME_EXISTS, user.getUsername());
+ }
+ }
+
+ @Override
+ public int deleteAccount(final Integer userid) throws KustvaktException {
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("user", userid);
+
+ try {
+ int r;
+ r = this.jdbcTemplate
+ .update("DELETE FROM korap_users WHERE id=:user", s);
+ // if (user instanceof KorAPUser)
+ // r = this.jdbcTemplate
+ // .update("DELETE FROM korap_users WHERE username=:user",
+ // s);
+ // else if (user instanceof ShibUser)
+ // r = this.jdbcTemplate
+ // .update("DELETE FROM shibusers WHERE username=:user",
+ // s);
+ // else
+ // r = -1;
+ return r;
+ }catch (DataAccessException e) {
+ jlog.error("Could not delete account for user: " + userid, e);
+ // throw new KorAPException(e, StatusCodes.CONNECTION_ERROR);
+ throw new dbException(userid, "korap_users",
+ StatusCodes.DB_DELETE_FAILED, userid.toString());
+ }
+
+ }
+
+ @Override
+ public int resetPassphrase(String username, String uriToken,
+ String passphrase) throws KustvaktException {
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ final String query = "UPDATE korap_users SET " +
+ "uri_expiration=0, password=:pass WHERE uri_fragment=:uri AND uri_expiration > :now "
+ + "AND username=:us AND uri_expiration > :now;";
+ np.addValue("uri", uriToken);
+ np.addValue("now", new Date(TimeUtils.getNow().getMillis()));
+ np.addValue("pass", passphrase);
+ np.addValue("us", username);
+ try {
+ return this.jdbcTemplate.update(query, np);
+ }catch (DataAccessException e) {
+ jlog.error("Could not reset password for name: " + username, e);
+ throw new dbException(username, "korap_users",
+ StatusCodes.DB_UPDATE_FAILED, username, uriToken,
+ passphrase);
+ }
+ }
+
+ @Override
+ public int activateAccount(String username, String uriToken)
+ throws KustvaktException {
+ MapSqlParameterSource np = new MapSqlParameterSource();
+ final String query = "UPDATE korap_users SET uriFragment='', " +
+ "uri_expiration=0, accountLock=:lock WHERE uri_fragment=:uri AND username=:us AND "
+ +
+ "uri_expiration > :now;";
+ np.addValue("uri", uriToken);
+ np.addValue("now", new Date(TimeUtils.getNow().getMillis()));
+ np.addValue("us", username);
+ np.addValue("lock", BooleanUtils.getBoolean(false));
+ try {
+ return this.jdbcTemplate.update(query, np);
+ }catch (DataAccessException e) {
+ jlog.error("Could not confirm registration for name " + username,
+ e);
+ throw new dbException(username, "korap_users",
+ StatusCodes.DB_UPDATE_FAILED, username, uriToken);
+ }
+ }
+
+ //todo:
+ public List getAccountLinks(User user) {
+
+ return Collections.emptyList();
+ }
+
+ //todo:
+ public void setAccountParameters(User user) {
+ ParamFields fields = user.getFields();
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/JDBCAuditing.java b/src/main/java/de/ids_mannheim/korap/handlers/JDBCAuditing.java
new file mode 100644
index 0000000..9cfbb3d
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/JDBCAuditing.java
@@ -0,0 +1,113 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.auditing.AuditRecord;
+import de.ids_mannheim.korap.interfaces.AuditingIface;
+import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.user.User;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.core.namedparam.SqlParameterSource;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+/**
+ * @author hanl
+ * @date 13/01/2014
+ */
+public class JDBCAuditing extends AuditingIface {
+
+ private NamedParameterJdbcTemplate template;
+
+ public JDBCAuditing(PersistenceClient client) {
+ this.template = (NamedParameterJdbcTemplate) client.getSource();
+ }
+
+ @Override
+ public <T extends AuditRecord> List<T> retrieveRecords(
+ AuditRecord.CATEGORY category, DateTime day, DateTime until,
+ boolean dayOnly, int limit) {
+ MapSqlParameterSource p = new MapSqlParameterSource();
+ p.addValue("limit", limit);
+ p.addValue("cat", category.toString());
+
+ String sql =
+ "select * from audit_records where aud_timestamp > :today AND"
+ + " aud_timestamp < :tomorr AND aud_category=:cat limit :limit;";
+
+ if (dayOnly) {
+ LocalDate today = day.toLocalDate();
+ DateTime start = today.toDateTimeAtStartOfDay(day.getZone());
+ DateTime end = today.plusDays(1)
+ .toDateTimeAtStartOfDay(day.getZone());
+ p.addValue("today", start.getMillis());
+ p.addValue("tomorr", end.getMillis());
+ }else {
+ p.addValue("today", day.getMillis());
+ p.addValue("tomorr", until.getMillis());
+ }
+ return (List<T>) this.template
+ .query(sql, p, new RowMapperFactory.AuditMapper());
+ }
+
+ @Override
+ public <T extends AuditRecord> List<T> retrieveRecords(
+ AuditRecord.CATEGORY category, User user, int limit) {
+ MapSqlParameterSource p = new MapSqlParameterSource();
+ p.addValue("limit", limit);
+ p.addValue("us", user.getUsername());
+ p.addValue("cat", category.toString());
+
+ String sql =
+ "select * from audit_records where aud_category=:cat and aud_user=:us "
+ + "order by aud_timestamp desc limit :limit;";
+
+ return (List<T>) this.template
+ .query(sql, p, new RowMapperFactory.AuditMapper());
+ }
+
+ @Override
+ public <T extends AuditRecord> List<T> retrieveRecords(LocalDate day,
+ int hitMax) {
+ return null;
+ }
+
+ @Override
+ public <T extends AuditRecord> List<T> retrieveRecords(String userID,
+ LocalDate start, LocalDate end, int hitMax) {
+ return null;
+ }
+
+ @Override
+ public void apply() {
+ String sql;
+ sql = "INSERT INTO audit_records (aud_target, aud_category, aud_user, aud_location, aud_timestamp, "
+ + "aud_status, aud_field_1, aud_args) "
+ + "VALUES (:target, :category, :account, :loc, :timestamp, :status, :field, :args);";
+ List<AuditRecord> records = getRecordsToSave();
+ SqlParameterSource[] s = new SqlParameterSource[records.size()];
+ for (int i = 0; i < records.size(); i++) {
+ AuditRecord rec = records.get(i);
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("category", rec.getCategory().toString());
+ source.addValue("account", rec.getUserid());
+ source.addValue("target", rec.getTarget());
+ source.addValue("loc", rec.getLoc());
+ source.addValue("timestamp", new Timestamp(rec.getTimestamp()));
+ source.addValue("status", rec.getStatus());
+ source.addValue("field", rec.getField_1());
+ source.addValue("args", rec.getArgs());
+ s[i] = source;
+ }
+ this.template.batchUpdate(sql, s);
+ records.clear();
+ }
+
+ @Override
+ public void finish() {
+
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/JDBCClient.java b/src/main/java/de/ids_mannheim/korap/handlers/JDBCClient.java
new file mode 100644
index 0000000..1b277d6
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/JDBCClient.java
@@ -0,0 +1,84 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.utils.BooleanUtils;
+import lombok.AccessLevel;
+import lombok.Data;
+import lombok.Setter;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.Resource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.SQLException;
+import java.util.HashMap;
+
+/**
+ * @author hanl
+ * @date 13/01/2014
+ */
+@Data
+public class JDBCClient extends PersistenceClient<NamedParameterJdbcTemplate> {
+
+ @Setter(AccessLevel.NONE)
+ private DataSource dataSource;
+
+ public JDBCClient(DataSource datasource) {
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(
+ datasource);
+ template.setCacheLimit(500);
+ super.setSource(template);
+ this.dataSource = datasource;
+ }
+
+ public JDBCClient(DataSource dataSource, Resource resource)
+ throws IOException {
+ this(dataSource);
+ this.setSchema(resource.getInputStream());
+ }
+
+ @Override
+ public void setSchema(InputStream stream) throws IOException {
+ super.setSchema(stream);
+ }
+
+ @Override
+ public boolean checkDatabase() {
+ NamedParameterJdbcTemplate tmp = this.getSource();
+ try {
+ // todo: use a table that doesnt change!!!!!
+ tmp.queryForObject("select count(id) from korap_users limit 1;",
+ new HashMap<String, Object>(), Integer.class);
+ }catch (Exception e) {
+ System.out.println("No database schema found!");
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void setDatabase(String name) {
+ super.setDatabase(name);
+ BooleanUtils.dbname = name;
+ }
+
+ // get schema file from configuration and create database
+ @Override
+ public void createDatabase() {
+ if (!checkDatabase()) {
+ final ResourceDatabasePopulator rdp = new ResourceDatabasePopulator();
+ rdp.addScript(new InputStreamResource(this.getSchema()));
+ rdp.setSeparator("$$");
+ try {
+ rdp.populate(this.dataSource.getConnection());
+ }catch (SQLException e) {
+ // do nothing
+ e.printStackTrace();
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java b/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
new file mode 100644
index 0000000..71ecbaf
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
@@ -0,0 +1,49 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.config.AuthCodeInfo;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.user.User;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+
+/**
+ * @author hanl
+ * @date 04/05/2015
+ */
+public class OAuth2Handler extends OAuthDb {
+
+ private Cache cache;
+
+ public OAuth2Handler(PersistenceClient client) {
+ super(client);
+ this.cache = CacheManager.getInstance().getCache("auth_codes");
+ }
+
+ public AuthCodeInfo getAuthorization(String code) {
+ Element e = this.cache.get(code);
+ if (e != null)
+ return (AuthCodeInfo) e.getObjectValue();
+ return null;
+ }
+
+ public void authorize(AuthCodeInfo code, User user) throws
+ KustvaktException {
+ code.setUserId(user.getId());
+ cache.put(new Element(code.getCode(), code));
+ }
+
+ public boolean addToken(String code, String token, int ttl)
+ throws KustvaktException {
+ Element e = cache.get(code);
+ if (e != null) {
+ AuthCodeInfo info = (AuthCodeInfo) e.getObjectValue();
+ cache.remove(code);
+ return super.addToken(token, info.getUserId(), info.getClientId(),
+ info.getScopes(), ttl);
+ }
+ return false;
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java b/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
new file mode 100644
index 0000000..b0bee5a
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
@@ -0,0 +1,267 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.config.ClientInfo;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.user.Attributes;
+import de.ids_mannheim.korap.user.TokenContext;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.BooleanUtils;
+import de.ids_mannheim.korap.utils.KustvaktLogger;
+import de.ids_mannheim.korap.utils.TimeUtils;
+import edu.emory.mathcs.backport.java.util.Collections;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.List;
+
+/**
+ * Created by hanl on 7/14/14.
+ */
+public class OAuthDb {
+
+ private static final Logger errorLogger = LoggerFactory
+ .getLogger(KustvaktLogger.ERROR_LOG);
+ private NamedParameterJdbcTemplate jdbcTemplate;
+
+ public OAuthDb(PersistenceClient client) {
+ this.jdbcTemplate = (NamedParameterJdbcTemplate) client.getSource();
+ }
+
+ public ClientInfo getClient(String clientid) {
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("cl", clientid);
+ String sql = "select * from oauth2_client where client_id=:cl;";
+
+ try {
+ return this.jdbcTemplate
+ .queryForObject(sql, s, new RowMapper<ClientInfo>() {
+ @Override
+ public ClientInfo mapRow(ResultSet rs, int rowNum)
+ throws SQLException {
+ ClientInfo info = new ClientInfo(
+ rs.getString("client_id"),
+ rs.getString("client_secret"));
+ info.setId(rs.getInt("id"));
+ info.setClient_type(rs.getString("client_type"));
+ info.setRedirect_uri(rs.getString("redirect_uri"));
+ info.setUrl(rs.getString("url"));
+ info.setConfidential(
+ rs.getBoolean("is_confidential"));
+ return info;
+ }
+ });
+ }catch (EmptyResultDataAccessException ex) {
+ errorLogger.error("no client found", ex.fillInStackTrace());
+ return null;
+ }
+ }
+
+ // fixme: what to delete? difference client/application table?
+ public boolean revokeToken(String token) throws KustvaktException {
+ String sql = "delete from oauth2_access_token WHERE access_token=:token;";
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("token", token);
+ try {
+ return this.jdbcTemplate.update(sql, s) == 1;
+ }catch (DataAccessException e) {
+ errorLogger
+ .error("token could not be revoked", e.fillInStackTrace());
+ return false;
+ }
+ }
+
+ public boolean revokeAuthorization(ClientInfo info, User user) {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("us", user.getId());
+ source.addValue("cls", info.getClient_secret());
+ source.addValue("clid", info.getClient_id());
+
+ String tokens =
+ "delete from oauth2_access_token where user_id=:us and client_id in "
+ + "(select client_id from oauth2_client where client_id=:clid and client_secret=:cls);";
+
+ try {
+ this.jdbcTemplate.update(tokens, source);
+ }catch (DataAccessException e) {
+ errorLogger
+ .error("authorization could not be revoked for user '{}'",
+ user.getUsername());
+ return false;
+ }
+ //fixme: if int row not updated, false!!
+ return true;
+ }
+
+ public boolean addToken(String token, Integer userid, String client_id,
+ String scopes, int expiration) throws KustvaktException {
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("token", token);
+ s.addValue("ex",
+ new Timestamp(TimeUtils.plusSeconds(expiration).getMillis()));
+ s.addValue("us", userid);
+ s.addValue("sc", scopes);
+ s.addValue("st", BooleanUtils.getBoolean(true));
+ s.addValue("cli", client_id);
+ String sql =
+ "insert into oauth2_access_token (access_token, scopes, client_id, user_id, expiration, status) "
+ + "values (:token, :sc, :cli, :us, :ex, :st);";
+ try {
+ return this.jdbcTemplate.update(sql, s) == 1;
+ }catch (DataAccessException e) {
+ e.printStackTrace();
+ errorLogger
+ .error("token '{}' could not be added for user '{}'", token,
+ userid);
+ return false;
+ }
+ }
+
+ // returns the first token to find
+ public String getToken(String client_id, Integer userid) {
+ String sql =
+ "select access_token from oauth2_access_token where user_id=:uid"
+ + " and status=1 and client_id=:cli limit 1;";
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("uid", userid);
+ s.addValue("cli", client_id);
+ try {
+ return this.jdbcTemplate.queryForObject(sql, s, String.class);
+ }catch (EmptyResultDataAccessException ex) {
+ errorLogger.error("no token found for user '{}'", userid);
+ return null;
+ }catch (DataAccessException ex) {
+ errorLogger.error("token retrieval failed for user '{}'", userid);
+ return null;
+ }
+ }
+
+ public List<ClientInfo> getAuthorizedClients(Integer userid) {
+ String sql =
+ "select cl.* from oauth2_client as cl where cl.client_id in (select cd.client_id from oauth2_access_token as cd "
+ + "where cd.user_id=:user) or cl.is_confidential=:conf;";
+
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("user", userid);
+ s.addValue("conf", BooleanUtils.getBoolean(true));
+ try {
+ // secret is not returned for this function
+ return this.jdbcTemplate.query(sql, s, new RowMapper<ClientInfo>() {
+
+ @Override
+ public ClientInfo mapRow(ResultSet rs, int rowNum)
+ throws SQLException {
+ ClientInfo info = new ClientInfo(rs.getString("client_id"),
+ "*****");
+ info.setConfidential(rs.getBoolean("is_confidential"));
+ info.setUrl(rs.getString("url"));
+ info.setId(rs.getInt("id"));
+ info.setRedirect_uri(rs.getString("redirect_uri"));
+ return info;
+ }
+ });
+ }catch (DataAccessException e) {
+ errorLogger.error("Data access error", e);
+ return Collections.emptyList();
+ }
+
+ }
+
+ public TokenContext getContext(final String token) throws
+ KustvaktException {
+ String sql =
+ "select ko.username, oa.expiration, oa.scopes from oauth2_access_token as oa inner join korap_users as ko "
+ + "on ko.id=oa.user_id where oa.access_token=:token and oa.expiration > :now;";
+ MapSqlParameterSource s = new MapSqlParameterSource();
+ s.addValue("token", token);
+ s.addValue("now", new Timestamp(TimeUtils.getNow().getMillis()));
+
+ try {
+ TokenContext context = this.jdbcTemplate
+ .queryForObject(sql, s, new RowMapper<TokenContext>() {
+ @Override
+ public TokenContext mapRow(ResultSet rs, int rowNum)
+ throws SQLException {
+ long exp = rs.getTimestamp("expiration").getTime();
+ TokenContext c = new TokenContext(
+ rs.getString(Attributes.USERNAME));
+ c.setExpirationTime(exp);
+ c.setToken(token);
+ c.setTokenType(Attributes.OAUTH2_AUTHORIZATION);
+ c.addContextParameter(Attributes.SCOPES,
+ rs.getString(Attributes.SCOPES));
+ return c;
+ }
+ });
+ return context;
+ }catch (EmptyResultDataAccessException ee) {
+ errorLogger.error("no context found for token '{}'", token);
+ revokeToken(token);
+ throw new KustvaktException(StatusCodes.EXPIRED, "token", token);
+ }catch (DataAccessException e) {
+ errorLogger.error("token context retrieval failed for '{}'", token);
+ throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+ "invalid token", token);
+ }
+
+ }
+
+ // subsequently delete all access and auth code tokens associated!
+ public void removeClient(ClientInfo info, User user) throws
+ KustvaktException {
+ MapSqlParameterSource p = new MapSqlParameterSource();
+ p.addValue("url", info.getUrl());
+ p.addValue("cls", info.getClient_secret());
+ p.addValue("clid", info.getClient_id());
+ String sql =
+ "delete from oauth2_client where client_id=:clid and client_secret=:cls and"
+ + " url=:url;";
+ try {
+ this.jdbcTemplate.update(sql, p);
+ }catch (DataAccessException e) {
+ e.printStackTrace();
+ errorLogger
+ .error("removing client '{}' failed", info.getClient_id());
+ throw new dbException(new KustvaktException(user.getId(),
+ StatusCodes.ILLEGAL_ARGUMENT, "arguments given not valid",
+ info.toJSON()), StatusCodes.CLIENT_REMOVAL_FAILURE,
+ info.toJSON());
+
+ }
+ }
+
+ public void registerClient(ClientInfo info, User user)
+ throws KustvaktException {
+ MapSqlParameterSource p = new MapSqlParameterSource();
+ p.addValue("clid", info.getClient_id());
+ p.addValue("con", info.isConfidential());
+ p.addValue("cls", info.getClient_secret());
+ p.addValue("clt", info.getClient_type());
+ p.addValue("url", info.getUrl());
+ p.addValue("r_url", info.getRedirect_uri());
+ String sql =
+ "insert into oauth2_client (client_id, client_secret, client_type, url, is_confidential, redirect_uri) "
+ + "VALUES (:clid, :cls, :clt, :url, :con, :r_url);";
+ try {
+ this.jdbcTemplate.update(sql, p);
+ }catch (DataAccessException e) {
+ e.printStackTrace();
+ errorLogger.error("registering client '{}' failed",
+ info.getClient_id());
+ throw new dbException(new KustvaktException(user.getId(),
+ StatusCodes.ILLEGAL_ARGUMENT, "arguments given not valid",
+ info.toJSON()), StatusCodes.CLIENT_REGISTRATION_FAILURE,
+ info.toJSON());
+ }
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java b/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java
new file mode 100644
index 0000000..6039c79
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java
@@ -0,0 +1,172 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.ext.interfaces.ResourceOperationIface;
+import de.ids_mannheim.korap.ext.resource.KorAPResource;
+import de.ids_mannheim.korap.ext.resource.ResourceFactory;
+import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.KustvaktLogger;
+import de.ids_mannheim.korap.utils.TimeUtils;
+import org.slf4j.Logger;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Created by hanl on 7/21/14.
+ */
+//todo: auditing // testing
+public class ResourceDao<T extends KorAPResource>
+ implements ResourceOperationIface<T> {
+
+ private static Logger log = KustvaktLogger.initiate(ResourceDao.class);
+ protected final NamedParameterJdbcTemplate jdbcTemplate;
+
+ public ResourceDao(PersistenceClient client) {
+ this.jdbcTemplate = (NamedParameterJdbcTemplate) client.getSource();
+ }
+
+ @Override
+ public Class<T> getType() {
+ return (Class<T>) KorAPResource.class;
+ }
+
+ @Override
+ public List<T> getResources(Collection<Object> ids, User user)
+ throws KustvaktException {
+ return null;
+ }
+
+ @Override
+ public int updateResource(T resource, User user) throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("id", resource.getPersistentID());
+ source.addValue("name", resource.getName());
+ source.addValue("desc", resource.getDescription());
+ final String sql = "UPDATE resource_store set name=:name, description=:desc where persistent_id=:id;";
+ try {
+ return this.jdbcTemplate.update(sql, source);
+ }catch (DataAccessException e) {
+ log.error("Exception during database update for id '" + resource
+ .getPersistentID() + "'", e);
+ throw new dbException(user.getId(), "resource_store",
+ StatusCodes.DB_UPDATE_FAILED, resource.toString());
+ }
+ }
+
+ @Override
+ public int[] updateResources(List<T> resources, User user)
+ throws KustvaktException {
+ return new int[1];
+ }
+
+ @Override
+ public <T extends KorAPResource> T findbyId(String id, User user)
+ throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("pid", id);
+ String sql =
+ "SELECT rs.*, rt.name_path FROM resource_store as rs inner join resource_tree as rt"
+ + " on rs.id=rt.child_id WHERE rs.persistent_id=:pid group by rs.id;";
+ try {
+ return (T) this.jdbcTemplate.queryForObject(sql, source,
+ new RowMapperFactory.ResourceMapper());
+ }catch (DataAccessException e) {
+ return null;
+ }
+ }
+
+ public KorAPResource findbyPath(String path, User user)
+ throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("path", path);
+ String sql = "SELECT rs.*, rt.name_path FROM resource_store as rs inner join resource_tree as rt on rs.id=rt.child_id WHERE rt.name_path=:path;";
+ try {
+ return this.jdbcTemplate.queryForObject(sql, source,
+ new RowMapperFactory.ResourceMapper());
+ }catch (DataAccessException e) {
+ if (e instanceof IncorrectResultSizeDataAccessException)
+ throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+ "invalid request path given!", path);
+ return null;
+ }
+ }
+
+ @Override
+ public <T extends KorAPResource> T findbyId(Integer id, User user)
+ throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("id", id);
+ String sql =
+ "SELECT rs.*, rt.name_path FROM resource_store as rs inner join resource_tree as rt on rs.id=rt.child_id "
+ + "WHERE rs.id=:id group by rs.id order by rt.depth desc;";
+ try {
+ return (T) this.jdbcTemplate.queryForObject(sql, source,
+ new RowMapperFactory.ResourceMapper());
+ }catch (DataAccessException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public int storeResource(T resource, User user) throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ KeyHolder holder = new GeneratedKeyHolder();
+ // parent_id necessary so trigger can be used for tree insert!
+ final String sql, parid;
+ if (resource.getParentID() == null) {
+ sql = "INSERT INTO resource_store (name, parent_id, persistent_id, description, creator, type, created) "
+ + "VALUES (:name, :parent, :pid, :desc, :ow, :type, :created);";
+ parid = null;
+ }else {
+ sql = "INSERT INTO resource_store (name, parent_id, persistent_id, description, creator, type, created) "
+ + "select :name, id, :pid, :desc, :ow, :type, :created from resource_store where persistent_id=:parent;";
+ parid = resource.getParentID();
+ }
+
+ source.addValue("name", resource.getName());
+ source.addValue("pid", resource.getPersistentID());
+ source.addValue("parent", parid);
+ source.addValue("ow", resource.getOwner());
+ source.addValue("desc", resource.getDescription());
+ source.addValue("type",
+ ResourceFactory.getResourceMapping(resource.getClass()));
+ source.addValue("created",
+ new Timestamp(TimeUtils.getNow().getMillis()));
+ try {
+ this.jdbcTemplate
+ .update(sql, source, holder, new String[] { "id" });
+ }catch (DataAccessException e) {
+ log.error("Exception during database store for id '" + resource
+ .getPersistentID() + "'", e);
+ throw new dbException(user.getId(), "resource_store",
+ StatusCodes.DB_INSERT_FAILED, resource.toString());
+ }
+ resource.setId(holder.getKey().intValue());
+ return resource.getId();
+ }
+
+ @Override
+ public int deleteResource(String id, User user) throws KustvaktException {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.addValue("id", id);
+ final String sql = "DELETE FROM resource_store WHERE persistent_id=:id;";
+ try {
+ return this.jdbcTemplate.update(sql, source);
+ }catch (DataAccessException e) {
+ e.printStackTrace();
+ throw new dbException(user.getId(), "resource_store",
+ StatusCodes.DB_DELETE_FAILED, id);
+ }
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/RowMapperFactory.java b/src/main/java/de/ids_mannheim/korap/handlers/RowMapperFactory.java
new file mode 100644
index 0000000..c5cc374
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/RowMapperFactory.java
@@ -0,0 +1,139 @@
+package de.ids_mannheim.korap.handlers;
+
+import de.ids_mannheim.korap.auditing.AuditRecord;
+import de.ids_mannheim.korap.config.URIParam;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.resources.ResourceFactory;
+import de.ids_mannheim.korap.resources.VirtualCollection;
+import de.ids_mannheim.korap.user.Attributes;
+import de.ids_mannheim.korap.user.KorAPUser;
+import de.ids_mannheim.korap.user.ShibUser;
+import de.ids_mannheim.korap.user.User;
+import org.springframework.jdbc.core.RowMapper;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Map;
+
+/**
+ * @author hanl
+ * @date 14/01/2014
+ */
+public class RowMapperFactory {
+
+ public static class UserMapMapper implements RowMapper<Map> {
+
+ @Override
+ public Map mapRow(ResultSet rs, int rowNum) throws SQLException {
+ User user = new UserMapper().mapRow(rs, rowNum);
+ return user.toMap();
+ }
+ }
+
+ public static class UserMapper implements RowMapper<User> {
+
+ @Override
+ public User mapRow(ResultSet rs, int rowNum) throws SQLException {
+ User user;
+ switch (rs.getInt("type")) {
+ case 0:
+ user = getKorAP(rs);
+ break;
+ case 1:
+ user = getShib(rs);
+ break;
+ default:
+ user = User.UserFactory.getDemoUser();
+ user.setId(rs.getInt("id"));
+ user.setAccountCreation(
+ rs.getTimestamp(Attributes.ACCOUNT_CREATION)
+ .getTime());
+ return user;
+ }
+ return user;
+ }
+
+ private KorAPUser getKorAP(ResultSet rs) throws SQLException {
+ KorAPUser user = User.UserFactory
+ .getUser(rs.getString(Attributes.USERNAME));
+ user.setPassword(rs.getString(Attributes.PASSWORD));
+ user.setId(rs.getInt(Attributes.ID));
+ user.setAccountLocked(rs.getBoolean(Attributes.ACCOUNTLOCK));
+ user.setAccountCreation(
+ rs.getTimestamp(Attributes.ACCOUNT_CREATION).getTime());
+ user.setAccountLink(rs.getString(Attributes.ACCOUNTLINK));
+
+ URIParam param = new URIParam(rs.getString(Attributes.URI_FRAGMENT),
+ rs.getDate(Attributes.URI_EXPIRATION).getTime());
+ user.addField(param);
+ return user;
+ }
+
+ private ShibUser getShib(ResultSet rs) throws SQLException {
+ ShibUser user = User.UserFactory
+ .getShibInstance(rs.getString(Attributes.USERNAME),
+ rs.getString(Attributes.MAIL),
+ rs.getString(Attributes.CN));
+ user.setId(rs.getInt(Attributes.ID));
+ return user;
+ }
+
+ }
+
+ public static class AuditMapper implements RowMapper<AuditRecord> {
+
+ @Override
+ public AuditRecord mapRow(ResultSet rs, int rowNum)
+ throws SQLException {
+ AuditRecord r = new AuditRecord(
+ AuditRecord.CATEGORY.valueOf(rs.getString("aud_category")));
+ r.setUserid(rs.getString("aud_user"));
+ r.setField_1(rs.getString("aud_field_1"));
+ r.setTimestamp(rs.getTimestamp("aud_timestamp").getTime());
+ r.setId(rs.getInt("aud_id"));
+ r.setStatus(rs.getInt("aud_status"));
+ r.setLoc(rs.getString("aud_location"));
+ return r;
+ }
+ }
+
+ public static class ResourceMapper implements RowMapper<KustvaktResource> {
+
+ @Override
+ public KustvaktResource mapRow(ResultSet rs, int rowNum)
+ throws SQLException {
+ KustvaktResource r = ResourceFactory.getResource(rs.getInt("type"));
+ if (r != null) {
+ r.setId(rs.getInt("id"));
+ r.setOwner(rs.getInt("creator"));
+ r.setName(rs.getString("name"));
+ r.setDescription(rs.getString("description"));
+ r.setCreated(rs.getTimestamp("created").getTime());
+ r.setPath(rs.getString("name_path"));
+ r.setPersistentID(rs.getString("persistent_id"));
+ }
+ return r;
+ }
+ }
+
+ // todo: ??!
+ public static class CollectionMapper
+ implements RowMapper<VirtualCollection> {
+
+ @Override
+ public VirtualCollection mapRow(ResultSet rs, int i)
+ throws SQLException {
+ VirtualCollection c = ResourceFactory
+ .getCollection(rs.getInt("id"), false);
+ c.setPersistentID(rs.getString("persistentId"));
+ c.setCreated(rs.getTimestamp("created").getTime());
+ c.setName(rs.getString("name"));
+ c.setDescription(rs.getString("description"));
+ c.setOwner(rs.getInt("userId"));
+ c.setQuery(rs.getString("query"));
+ c.checkNull();
+ return c;
+ }
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/resource/rewrite/MetaConstraint.java b/src/main/java/de/ids_mannheim/korap/resource/rewrite/MetaConstraint.java
new file mode 100644
index 0000000..4660235
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/resource/rewrite/MetaConstraint.java
@@ -0,0 +1,24 @@
+package de.ids_mannheim.korap.resource.rewrite;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * @author hanl
+ * @date 04/07/2015
+ */
+public class MetaConstraint extends RewriteQuery {
+
+ public MetaConstraint() {
+ super();
+ }
+
+ @Override
+ public JsonNode rewrite(KoralNode node) {
+ if (node.rawNode().has("meta")) {
+ JsonNode meta = node.rawNode().path("meta");
+ //todo: check meta parameter
+ System.out.println("HAVE TO CHECK THE META ENTRIES");
+ }
+ return node.rawNode();
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/resource/rewrite/PublicCollection.java b/src/main/java/de/ids_mannheim/korap/resource/rewrite/PublicCollection.java
new file mode 100644
index 0000000..d6685ea
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/resource/rewrite/PublicCollection.java
@@ -0,0 +1,20 @@
+package de.ids_mannheim.korap.resource.rewrite;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * @author hanl
+ * @date 04/07/2015
+ */
+public class PublicCollection extends RewriteQuery {
+
+ @Override
+ public JsonNode rewrite(KoralNode node) {
+ JsonNode subnode = node.rawNode();
+ if (!subnode.at("/collection").findValuesAsText("key")
+ .contains("corpusID")) {
+ //todo: inject public collection node
+ }
+ return subnode;
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/resource/rewrite/TreeConstraint.java b/src/main/java/de/ids_mannheim/korap/resource/rewrite/TreeConstraint.java
new file mode 100644
index 0000000..e285114
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/resource/rewrite/TreeConstraint.java
@@ -0,0 +1,57 @@
+package de.ids_mannheim.korap.resource.rewrite;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * #ELEM(W ANA=N)
+ * <p/>
+ * {
+ * "@context": "http://korap.ids-mannheim.de/ns/koral/0.3/context.jsonld",
+ * "errors": [],
+ * "warnings": [],
+ * "messages": [],
+ * "collection": {},
+ * "query": {
+ * "@type": "koral:span",
+ * "key": "w",
+ * "attr": {
+ * "@type": "koral:term",
+ * "layer": "p",
+ * "key": "N",
+ * "match": "match:eq"
+ * }
+ * },
+ * "meta": {}
+ * }
+ * <p/>
+ * <p/>
+ * email reference:
+ * Hallo Michael,
+ * mir fiel gestern bei der neuen KoralQuery Serialisierung noch ein Fall
+ * für default-Werte ein, die zumindest für viele Beispiele, die wir haben,
+ * relevant ist: Wenn ein koral:term in einem koral:span gewrappt ist, dann
+ * kann er eventuell nur einen Schlüssel haben ("s" oder "p" von "<s>" oder
+ * "<p>". In diesem Fall wäre der default layer "s" und die default foundry
+ * "base". (Im alten KoralQuery wurden spans nicht gewrappt - der Fall
+ * sollte aber erstmal weiter unterstützt werden.)
+ * Viele Grüße,
+ * Nils
+ *
+ * @author hanl
+ * @date 02/07/2015
+ */
+public class TreeConstraint extends RewriteQuery {
+
+ private String pointer;
+
+ public TreeConstraint(String constraint_pointer) {
+ this.pointer = constraint_pointer;
+ }
+
+ @Override
+ public JsonNode rewrite(KoralNode node) {
+ System.out.println("FIND PATH " + node.rawNode().findParent(pointer));
+
+ return node.rawNode();
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/web/KustvaktLightServer.java b/src/main/java/de/ids_mannheim/korap/web/KustvaktLightServer.java
new file mode 100644
index 0000000..65f21c3
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/web/KustvaktLightServer.java
@@ -0,0 +1,117 @@
+package de.ids_mannheim.korap.web;
+
+import com.sun.jersey.api.core.PackagesResourceConfig;
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+import de.ids_mannheim.korap.config.BeanConfiguration;
+import lombok.Getter;
+import lombok.Setter;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.bio.SocketConnector;
+import org.eclipse.jetty.server.ssl.SslSocketConnector;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+/**
+ * @author hanl
+ * @date 01/06/2015
+ */
+public class KustvaktLightServer {
+
+ public static void main(String[] args) throws Exception {
+ KustvaktArgs kargs = readAttributes(args);
+
+ if (kargs.config != null)
+ BeanConfiguration.loadFileContext(kargs.config);
+ else
+ BeanConfiguration.loadClasspathContext();
+
+ kargs.setRootClasses(
+ new String[] { "de.ids_mannheim.korap.web.service" });
+ startServer(kargs);
+ }
+
+ public static KustvaktArgs readAttributes(String[] args) {
+ KustvaktArgs kargs = new KustvaktArgs();
+ for (int i = 0; i < args.length; i++) {
+ switch ((args[i])) {
+ case "--debug":
+ kargs.setDebug(true);
+ break;
+ case "--config":
+ kargs.setConfig(args[i + 1]);
+ break;
+ case "--port":
+ kargs.setPort(Integer.valueOf(args[i + 1]));
+ break;
+ }
+ }
+ return kargs;
+ }
+
+ public static void startServer(KustvaktArgs kargs) {
+ if (kargs.port == -1)
+ kargs.setPort(
+ BeanConfiguration.getBeans().getConfiguration().getPort());
+
+ System.out.println(
+ "Starting Kustvakt Service on port '" + kargs.port + "'");
+ try {
+ // from http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty
+ Server server = new Server();
+ ServletContextHandler contextHandler = new ServletContextHandler(
+ ServletContextHandler.NO_SESSIONS);
+ contextHandler.setContextPath("/");
+
+ SocketConnector connector = new SocketConnector();
+ connector.setPort(kargs.port);
+ connector.setMaxIdleTime(60000);
+
+ // http://stackoverflow.com/questions/9670363/how-do-i-programmatically-configure-jersey-to-use-jackson-for-json-deserializa
+ final PackagesResourceConfig prc = new PackagesResourceConfig(
+ kargs.rootClasses);
+ // from http://stackoverflow.com/questions/7421574/embedded-jetty-with-jersey-or-resteasy
+ contextHandler
+ .addServlet(new ServletHolder(new ServletContainer(prc)),
+ "/api/*");
+
+ server.setHandler(contextHandler);
+
+ if (kargs.sslContext != null) {
+ SslSocketConnector sslConnector = new SslSocketConnector(
+ kargs.sslContext);
+ sslConnector.setPort(8443);
+ sslConnector.setMaxIdleTime(60000);
+ server.setConnectors(
+ new Connector[] { connector, sslConnector });
+ }else
+ server.setConnectors(new Connector[] { connector });
+
+ server.start();
+ server.join();
+ }catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ @Setter
+ public static class KustvaktArgs {
+
+ private boolean debug;
+ @Getter
+ private String config;
+ private int port;
+ private SslContextFactory sslContext;
+ private String[] rootClasses;
+
+ public KustvaktArgs() {
+ this.port = -1;
+ this.sslContext = null;
+ this.debug = false;
+ this.config = null;
+ }
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/LightService.java b/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
similarity index 97%
rename from src/main/java/de/ids_mannheim/korap/web/service/LightService.java
rename to src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
index 247759c..a2d27ca 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/LightService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
@@ -1,10 +1,10 @@
-package de.ids_mannheim.korap.web.service;
+package de.ids_mannheim.korap.web.service.light;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import de.ids_mannheim.korap.config.BeanConfiguration;
import de.ids_mannheim.korap.config.KustvaktConfiguration;
import de.ids_mannheim.korap.config.QueryBuilderUtil;
-import de.ids_mannheim.korap.exceptions.KorAPException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.query.serialize.MetaQueryBuilder;
import de.ids_mannheim.korap.query.serialize.QuerySerializer;
@@ -58,7 +58,7 @@
String result;
try {
result = graphDBhandler.getResponse("distCollo", "q", query);
- }catch (KorAPException e) {
+ }catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
return Response.ok(result).build();
@@ -146,7 +146,7 @@
String.valueOf(meta.getSpanContext().getRight_size()));
try {
result = this.graphDBhandler.getResponse(map, "distKwic");
- }catch (KorAPException e) {
+ }catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
}else