diff --git a/README.md b/README.md
index c9970c9b..64e71255 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,10 @@ Features
- SHA-256 encryption
- Tag system
- Multi-users ACL system
+- Audit log
- Document sharing by URL
- RESTful Web API
-- Modern Android client
+- Fully featured Android client
Download
--------
@@ -71,7 +72,7 @@ From the `docs-web` directory:
mvn -Pprod -DskipTests clean install
-You will get your deployable WAR in the `target` directory.
+You will get your deployable WAR in the `docs-web/target` directory.
License
-------
diff --git a/docs-core/pom.xml b/docs-core/pom.xml
index f9d5932d..c2729773 100644
--- a/docs-core/pom.xml
+++ b/docs-core/pom.xml
@@ -146,8 +146,8 @@
- org.hsqldb
- hsqldb
+ com.h2database
+ h2
test
diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/AuditLogDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/AuditLogDao.java
index 786173c8..f66c9df9 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/AuditLogDao.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/AuditLogDao.java
@@ -11,6 +11,7 @@ import java.util.UUID;
import javax.persistence.EntityManager;
import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
import com.sismics.docs.core.constant.AuditLogType;
import com.sismics.docs.core.dao.jpa.criteria.AuditLogCriteria;
import com.sismics.docs.core.dao.jpa.dto.AuditLogDto;
@@ -57,37 +58,29 @@ public class AuditLogDao {
*/
public void findByCriteria(PaginatedList paginatedList, AuditLogCriteria criteria, SortCriteria sortCriteria) throws Exception {
Map parameterMap = new HashMap();
- List criteriaList = new ArrayList();
- StringBuilder sb = new StringBuilder("select l.LOG_ID_C c0, l.LOG_CREATEDATE_D c1, l.LOG_IDENTITY_C c2, l.LOG_CLASSENTITY_C c3, l.LOG_TYPE_C c4, l.LOG_MESSAGE_C c5 ");
- sb.append(" from T_AUDIT_LOG l ");
+ String baseQuery = "select l.LOG_ID_C c0, l.LOG_CREATEDATE_D c1, l.LOG_IDENTITY_C c2, l.LOG_CLASSENTITY_C c3, l.LOG_TYPE_C c4, l.LOG_MESSAGE_C c5 from T_AUDIT_LOG l ";
+ List queries = Lists.newArrayList();
// Adds search criteria
if (criteria.getDocumentId() != null) {
// ACL on document is not checked here, it's assumed
- StringBuilder sb0 = new StringBuilder(" (l.LOG_IDENTITY_C = :documentId and l.LOG_CLASSENTITY_C = 'Document' ");
- sb0.append(" or l.LOG_IDENTITY_C in (select f.FIL_ID_C from T_FILE f where f.FIL_IDDOC_C = :documentId) and l.LOG_CLASSENTITY_C = 'File' ");
- sb0.append(" or l.LOG_IDENTITY_C in (select a.ACL_ID_C from T_ACL a where a.ACL_SOURCEID_C = :documentId) and l.LOG_CLASSENTITY_C = 'Acl') ");
- criteriaList.add(sb0.toString());
+ queries.add(baseQuery + " where l.LOG_IDENTITY_C = :documentId ");
+ queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select f.FIL_ID_C from T_FILE f where f.FIL_IDDOC_C = :documentId) ");
+ queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select a.ACL_ID_C from T_ACL a where a.ACL_SOURCEID_C = :documentId) ");
parameterMap.put("documentId", criteria.getDocumentId());
}
if (criteria.getUserId() != null) {
- StringBuilder sb0 = new StringBuilder(" (l.LOG_IDENTITY_C = :userId and l.LOG_CLASSENTITY_C = 'User' ");
- sb0.append(" or l.LOG_IDENTITY_C in (select t.TAG_ID_C from T_TAG t where t.TAG_IDUSER_C = :userId) and l.LOG_CLASSENTITY_C = 'Tag' ");
+ queries.add(baseQuery + " where l.LOG_IDENTITY_C = :userId ");
+ queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select t.TAG_ID_C from T_TAG t where t.TAG_IDUSER_C = :userId) ");
// Show only logs from owned documents, ACL are lost on delete
- sb0.append(" or l.LOG_IDENTITY_C in (select d.DOC_ID_C from T_DOCUMENT d where d.DOC_IDUSER_C = :userId) and l.LOG_CLASSENTITY_C = 'Document') ");
- criteriaList.add(sb0.toString());
+ queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select d.DOC_ID_C from T_DOCUMENT d where d.DOC_IDUSER_C = :userId) ");
parameterMap.put("userId", criteria.getUserId());
}
- if (!criteriaList.isEmpty()) {
- sb.append(" where ");
- sb.append(Joiner.on(" and ").join(criteriaList));
- }
-
// Perform the search
- QueryParam queryParam = new QueryParam(sb.toString(), parameterMap);
+ QueryParam queryParam = new QueryParam(Joiner.on(" union ").join(queries), parameterMap);
List l = PaginatedLists.executePaginatedQuery(paginatedList, queryParam, sortCriteria);
// Assemble results
diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/DocumentDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/DocumentDao.java
index f6ae41f1..0d82f40f 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/DocumentDao.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/DocumentDao.java
@@ -183,7 +183,7 @@ public class DocumentDao {
Map parameterMap = new HashMap();
List criteriaList = new ArrayList();
- StringBuilder sb = new StringBuilder("select distinct d.DOC_ID_C c0, d.DOC_TITLE_C c1, d.DOC_DESCRIPTION_C c2, d.DOC_CREATEDATE_D c3, d.DOC_LANGUAGE_C c4, ");
+ StringBuilder sb = new StringBuilder("select d.DOC_ID_C c0, d.DOC_TITLE_C c1, d.DOC_DESCRIPTION_C c2, d.DOC_CREATEDATE_D c3, d.DOC_LANGUAGE_C c4, ");
sb.append(" (select count(s.SHA_ID_C) from T_SHARE s, T_ACL ac where ac.ACL_SOURCEID_C = d.DOC_ID_C and ac.ACL_TARGETID_C = s.SHA_ID_C and ac.ACL_DELETEDATE_D is null and s.SHA_DELETEDATE_D is null) c5, ");
sb.append(" (select count(f.FIL_ID_C) from T_FILE f where f.FIL_DELETEDATE_D is null and f.FIL_IDDOC_C = d.DOC_ID_C) c6 ");
sb.append(" from T_DOCUMENT d ");
@@ -215,8 +215,7 @@ public class DocumentDao {
if (criteria.getTagIdList() != null && !criteria.getTagIdList().isEmpty()) {
int index = 0;
for (String tagId : criteria.getTagIdList()) {
- sb.append(" left join T_DOCUMENT_TAG dt" + index + " on dt" + index + ".DOT_IDDOCUMENT_C = d.DOC_ID_C and dt" + index + ".DOT_IDTAG_C = :tagId" + index + " ");
- criteriaList.add("dt" + index + ".DOT_ID_C is not null");
+ sb.append(" join T_DOCUMENT_TAG dt" + index + " on dt" + index + ".DOT_IDDOCUMENT_C = d.DOC_ID_C and dt" + index + ".DOT_IDTAG_C = :tagId" + index + " ");
parameterMap.put("tagId" + index, tagId);
index++;
}
diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileDao.java
index 54da76f9..4fcf3fda 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileDao.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileDao.java
@@ -121,9 +121,6 @@ public class FileDao {
fileFromDb.setContent(file.getContent());
fileFromDb.setOrder(file.getOrder());
- // Create audit log
- AuditLogUtil.create(fileFromDb, AuditLogType.UPDATE);
-
return file;
}
diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/DirectoryUtil.java b/docs-core/src/main/java/com/sismics/docs/core/util/DirectoryUtil.java
index a4aad893..38b410da 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/util/DirectoryUtil.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/util/DirectoryUtil.java
@@ -104,10 +104,10 @@ public class DirectoryUtil {
*/
private static File getDataSubDirectory(String subdirectory) {
File baseDataDir = getBaseDataDirectory();
- File faviconDirectory = new File(baseDataDir.getPath() + File.separator + subdirectory);
- if (!faviconDirectory.isDirectory()) {
- faviconDirectory.mkdirs();
+ File directory = new File(baseDataDir.getPath() + File.separator + subdirectory);
+ if (!directory.isDirectory()) {
+ directory.mkdirs();
}
- return faviconDirectory;
+ return directory;
}
}
diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java b/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java
index 12a52a8e..5e47124f 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java
@@ -88,7 +88,7 @@ public class FileUtil {
log.info("Starting OCR with TESSDATA_PREFIX=" + System.getenv("TESSDATA_PREFIX") + ";LC_NUMERIC=" + System.getenv("LC_NUMERIC"));
instance.setLanguage(document.getLanguage());
content = instance.doOCR(image);
- } catch (Exception e) {
+ } catch (Throwable e) {
log.error("Error while OCR-izing the image", e);
}
diff --git a/docs-core/src/main/java/com/sismics/util/jpa/EMF.java b/docs-core/src/main/java/com/sismics/util/jpa/EMF.java
index fee2bb55..7dbc8746 100644
--- a/docs-core/src/main/java/com/sismics/util/jpa/EMF.java
+++ b/docs-core/src/main/java/com/sismics/util/jpa/EMF.java
@@ -71,17 +71,17 @@ public final class EMF {
properties.load(is);
return properties;
}
- } catch (IOException e) {
+ } catch (IOException | IllegalArgumentException e) {
log.error("Error reading hibernate.properties", e);
}
// Use environment parameters
log.info("Configuring EntityManager from environment parameters");
Map props = new HashMap();
- props.put("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
+ props.put("hibernate.connection.driver_class", "org.h2.Driver");
File dbDirectory = DirectoryUtil.getDbDirectory();
String dbFile = dbDirectory.getAbsoluteFile() + File.separator + "docs";
- props.put("hibernate.connection.url", "jdbc:hsqldb:file:" + dbFile + ";hsqldb.write_delay=false;shutdown=true");
+ props.put("hibernate.connection.url", "jdbc:h2:file:" + dbFile + ";CACHE_SIZE=65536");
props.put("hibernate.connection.username", "sa");
props.put("hibernate.hbm2ddl.auto", "none");
props.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
diff --git a/docs-core/src/main/resources/config.properties b/docs-core/src/main/resources/config.properties
index 592e6288..c0e441b7 100644
--- a/docs-core/src/main/resources/config.properties
+++ b/docs-core/src/main/resources/config.properties
@@ -1 +1 @@
-db.version=10
\ No newline at end of file
+db.version=0
\ No newline at end of file
diff --git a/docs-core/src/main/resources/db/update/dbupdate-000-0.sql b/docs-core/src/main/resources/db/update/dbupdate-000-0.sql
index 33198eb1..b8fa4a2a 100644
--- a/docs-core/src/main/resources/db/update/dbupdate-000-0.sql
+++ b/docs-core/src/main/resources/db/update/dbupdate-000-0.sql
@@ -1,18 +1,23 @@
SET IGNORECASE TRUE;
-create memory table T_AUTHENTICATION_TOKEN ( AUT_ID_C varchar(36) not null, AUT_IDUSER_C varchar(36) not null, AUT_LONGLASTED_B bit not null, AUT_CREATIONDATE_D datetime not null, AUT_LASTCONNECTIONDATE_D datetime, primary key (AUT_ID_C) );
+create memory table T_AUTHENTICATION_TOKEN ( AUT_ID_C varchar(36) not null, AUT_IDUSER_C varchar(36) not null, AUT_LONGLASTED_B bit not null, AUT_CREATIONDATE_D datetime not null, AUT_LASTCONNECTIONDATE_D datetime, AUT_IP_C varchar(45), AUT_UA_C varchar(1000), primary key (AUT_ID_C) );
create memory table T_BASE_FUNCTION ( BAF_ID_C varchar(20) not null, primary key (BAF_ID_C) );
-create cached table T_FILE ( FIL_ID_C varchar(36) not null, FIL_IDDOC_C varchar(36) not null, FIL_MIMETYPE_C varchar(100) not null, FIL_CREATEDATE_D datetime, FIL_DELETEDATE_D datetime, primary key (FIL_ID_C) );
+create cached table T_FILE ( FIL_ID_C varchar(36) not null, FIL_IDDOC_C varchar(36), FIL_IDUSER_C varchar(36) not null, FIL_MIMETYPE_C varchar(100) not null, FIL_CREATEDATE_D datetime, FIL_DELETEDATE_D datetime, FIL_ORDER_N int, FIL_CONTENT_C longvarchar, primary key (FIL_ID_C) );
create memory table T_CONFIG ( CFG_ID_C varchar(50) not null, CFG_VALUE_C varchar(250) not null, primary key (CFG_ID_C) );
create memory table T_LOCALE ( LOC_ID_C varchar(10) not null, primary key (LOC_ID_C) );
-create cached table T_DOCUMENT ( DOC_ID_C varchar(36) not null, DOC_IDUSER_C varchar(36) not null, DOC_TITLE_C varchar(100) not null, DOC_DESCRIPTION_C varchar(4000), DOC_CREATEDATE_D datetime, DOC_DELETEDATE_D datetime, primary key (DOC_ID_C) );
-create memory table T_USER ( USE_ID_C varchar(36) not null, USE_IDLOCALE_C varchar(10) not null, USE_IDROLE_C varchar(36) not null, USE_USERNAME_C varchar(50) not null, USE_PASSWORD_C varchar(60) not null, USE_EMAIL_C varchar(100) not null, USE_THEME_C varchar(100) not null, USE_FIRSTCONNECTION_B bit not null, USE_CREATEDATE_D datetime not null, USE_DELETEDATE_D datetime, primary key (USE_ID_C) );
+create cached table T_DOCUMENT ( DOC_ID_C varchar(36) not null, DOC_IDUSER_C varchar(36) not null, DOC_TITLE_C varchar(100) not null, DOC_DESCRIPTION_C varchar(4000), DOC_CREATEDATE_D datetime, DOC_DELETEDATE_D datetime, DOC_LANGUAGE_C varchar(3) default 'fra' not null, primary key (DOC_ID_C) );
+create memory table T_USER ( USE_ID_C varchar(36) not null, USE_IDLOCALE_C varchar(10) not null, USE_IDROLE_C varchar(36) not null, USE_USERNAME_C varchar(50) not null, USE_PASSWORD_C varchar(60) not null, USE_EMAIL_C varchar(100) not null, USE_THEME_C varchar(100) not null, USE_FIRSTCONNECTION_B bit not null, USE_CREATEDATE_D datetime not null, USE_DELETEDATE_D datetime, USE_PRIVATEKEY_C varchar(100) default '' not null, primary key (USE_ID_C) );
create memory table T_ROLE ( ROL_ID_C varchar(36) not null, ROL_NAME_C varchar(36) not null, ROL_CREATEDATE_D datetime not null, ROL_DELETEDATE_D datetime, primary key (ROL_ID_C) );
create memory table T_ROLE_BASE_FUNCTION ( RBF_ID_C varchar(36) not null, RBF_IDROLE_C varchar(36) not null, RBF_IDBASEFUNCTION_C varchar(20) not null, RBF_CREATEDATE_D datetime not null, RBF_DELETEDATE_D datetime, primary key (RBF_ID_C) );
-create cached table T_TAG ( TAG_ID_C varchar(36) not null, TAG_IDUSER_C varchar(36) not null, TAG_NAME_C varchar(36) not null, TAG_CREATEDATE_D datetime, TAG_DELETEDATE_D datetime, primary key (TAG_ID_C) );
-create cached table T_DOCUMENT_TAG ( DOT_ID_C varchar(36) not null, DOT_IDDOCUMENT_C varchar(36) not null, DOT_IDTAG_C varchar(36) not null, primary key (DOT_ID_C) );
+create cached table T_TAG ( TAG_ID_C varchar(36) not null, TAG_IDUSER_C varchar(36) not null, TAG_NAME_C varchar(36) not null, TAG_CREATEDATE_D datetime, TAG_DELETEDATE_D datetime, TAG_COLOR_C varchar(7) default '#3a87ad' not null, primary key (TAG_ID_C) );
+create cached table T_DOCUMENT_TAG ( DOT_ID_C varchar(36) not null, DOT_IDDOCUMENT_C varchar(36) not null, DOT_IDTAG_C varchar(36) not null, DOT_DELETEDATE_D datetime, primary key (DOT_ID_C) );
+create cached table T_ACL ( ACL_ID_C varchar(36) not null, ACL_PERM_C varchar(30) not null, ACL_SOURCEID_C varchar(36) not null, ACL_TARGETID_C varchar(36) not null, ACL_DELETEDATE_D datetime, primary key (ACL_ID_C) );
+create cached table T_SHARE ( SHA_ID_C varchar(36) not null, SHA_NAME_C varchar(36), SHA_CREATEDATE_D datetime, SHA_DELETEDATE_D datetime, primary key (SHA_ID_C) );
+create cached table T_AUDIT_LOG ( LOG_ID_C varchar(36) not null, LOG_IDENTITY_C varchar(36) not null, LOG_CLASSENTITY_C varchar(50) not null, LOG_TYPE_C varchar(50) not null, LOG_MESSAGE_C varchar(1000), LOG_CREATEDATE_D datetime, primary key (LOG_ID_C) );
+
alter table T_AUTHENTICATION_TOKEN add constraint FK_AUT_IDUSER_C foreign key (AUT_IDUSER_C) references T_USER (USE_ID_C) on delete restrict on update restrict;
alter table T_DOCUMENT add constraint FK_DOC_IDUSER_C foreign key (DOC_IDUSER_C) references T_USER (USE_ID_C) on delete restrict on update restrict;
alter table T_FILE add constraint FK_FIL_IDDOC_C foreign key (FIL_IDDOC_C) references T_DOCUMENT (DOC_ID_C) on delete restrict on update restrict;
+alter table T_FILE add constraint FK_FIL_IDUSER_C foreign key (FIL_IDUSER_C) references T_USER (USE_ID_C) on delete restrict on update restrict;
alter table T_USER add constraint FK_USE_IDLOCALE_C foreign key (USE_IDLOCALE_C) references T_LOCALE (LOC_ID_C) on delete restrict on update restrict;
alter table T_USER add constraint FK_USE_IDROLE_C foreign key (USE_IDROLE_C) references T_ROLE (ROL_ID_C) on delete restrict on update restrict;
alter table T_TAG add constraint FK_TAG_IDUSER_C foreign key (TAG_IDUSER_C) references T_USER (USE_ID_C) on delete restrict on update restrict;
@@ -20,11 +25,20 @@ alter table T_DOCUMENT_TAG add constraint FK_DOT_IDDOCUMENT_C foreign key (DOT_I
alter table T_DOCUMENT_TAG add constraint FK_DOT_IDTAG_C foreign key (DOT_IDTAG_C) references T_TAG (TAG_ID_C) on delete restrict on update restrict;
alter table T_ROLE_BASE_FUNCTION add constraint FK_RBF_IDROLE_C foreign key (RBF_IDROLE_C) references T_ROLE (ROL_ID_C) on delete restrict on update restrict;
alter table T_ROLE_BASE_FUNCTION add constraint FK_RBF_IDBASEFUNCTION_C foreign key (RBF_IDBASEFUNCTION_C) references T_BASE_FUNCTION (BAF_ID_C) on delete restrict on update restrict;
+
+create index IDX_DOC_TITLE_C on T_DOCUMENT (DOC_TITLE_C);
+create index IDX_DOC_CREATEDATE_D on T_DOCUMENT (DOC_CREATEDATE_D);
+create index IDX_DOC_LANGUAGE_C on T_DOCUMENT (DOC_LANGUAGE_C);
+create index IDX_ACL_SOURCEID_C on T_ACL (ACL_SOURCEID_C);
+create index IDX_ACL_TARGETID_C on T_ACL (ACL_TARGETID_C);
+create index IDX_LOG_IDENTITY_C on T_AUDIT_LOG (LOG_IDENTITY_C);
+
insert into T_CONFIG(CFG_ID_C, CFG_VALUE_C) values('DB_VERSION', '0');
insert into T_CONFIG(CFG_ID_C, CFG_VALUE_C) values('LUCENE_DIRECTORY_STORAGE', 'FILE');
insert into T_BASE_FUNCTION(BAF_ID_C) values('ADMIN');
insert into T_LOCALE(LOC_ID_C) values('en');
insert into T_LOCALE(LOC_ID_C) values('fr');
insert into T_ROLE(ROL_ID_C, ROL_NAME_C, ROL_CREATEDATE_D) values('admin', 'Admin', NOW());
+insert into T_ROLE(ROL_ID_C, ROL_NAME_C, ROL_CREATEDATE_D) values('user', 'User', NOW());
insert into T_ROLE_BASE_FUNCTION(RBF_ID_C, RBF_IDROLE_C, RBF_IDBASEFUNCTION_C, RBF_CREATEDATE_D) values('admin_ADMIN', 'admin', 'ADMIN', NOW());
-insert into T_USER(USE_ID_C, USE_IDLOCALE_C, USE_IDROLE_C, USE_USERNAME_C, USE_PASSWORD_C, USE_EMAIL_C, USE_THEME_C, USE_FIRSTCONNECTION_B, USE_CREATEDATE_D) values('admin', 'en', 'admin', 'admin', '$2a$05$6Ny3TjrW3aVAL1or2SlcR.fhuDgPKp5jp.P9fBXwVNePgeLqb4i3C', 'admin@localhost', 'default.less', true, NOW());
+insert into T_USER(USE_ID_C, USE_IDLOCALE_C, USE_IDROLE_C, USE_USERNAME_C, USE_PASSWORD_C, USE_EMAIL_C, USE_THEME_C, USE_FIRSTCONNECTION_B, USE_CREATEDATE_D, USE_PRIVATEKEY_C) values('admin', 'en', 'admin', 'admin', '$2a$05$6Ny3TjrW3aVAL1or2SlcR.fhuDgPKp5jp.P9fBXwVNePgeLqb4i3C', 'admin@localhost', 'default.less', true, NOW(), 'AdminPk');
diff --git a/docs-core/src/main/resources/db/update/dbupdate-001-0.sql b/docs-core/src/main/resources/db/update/dbupdate-001-0.sql
deleted file mode 100644
index 400b1628..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-001-0.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-alter table T_FILE add column FIL_ORDER_N int;
-update T_CONFIG set CFG_VALUE_C='1' where CFG_ID_C='DB_VERSION';
diff --git a/docs-core/src/main/resources/db/update/dbupdate-002-0.sql b/docs-core/src/main/resources/db/update/dbupdate-002-0.sql
deleted file mode 100644
index f83c630f..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-002-0.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-alter table T_TAG add column TAG_COLOR_C varchar(7) default '#3a87ad' not null;
-update T_CONFIG set CFG_VALUE_C='2' where CFG_ID_C='DB_VERSION';
diff --git a/docs-core/src/main/resources/db/update/dbupdate-003-0.sql b/docs-core/src/main/resources/db/update/dbupdate-003-0.sql
deleted file mode 100644
index 1d05a145..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-003-0.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-insert into T_ROLE(ROL_ID_C, ROL_NAME_C, ROL_CREATEDATE_D) values('user', 'User', NOW());
-update T_CONFIG set CFG_VALUE_C='3' where CFG_ID_C='DB_VERSION';
diff --git a/docs-core/src/main/resources/db/update/dbupdate-004-0.sql b/docs-core/src/main/resources/db/update/dbupdate-004-0.sql
deleted file mode 100644
index 08bd0ede..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-004-0.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-create cached table T_SHARE ( SHA_ID_C varchar(36) not null, SHA_NAME_C varchar(36), SHA_IDDOCUMENT_C varchar(36) not null, SHA_CREATEDATE_D datetime, SHA_DELETEDATE_D datetime, primary key (SHA_ID_C) );
-update T_CONFIG set CFG_VALUE_C='4' where CFG_ID_C='DB_VERSION';
diff --git a/docs-core/src/main/resources/db/update/dbupdate-005-0.sql b/docs-core/src/main/resources/db/update/dbupdate-005-0.sql
deleted file mode 100644
index a6465ec1..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-005-0.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-alter table T_FILE add column FIL_CONTENT_C LONGVARCHAR;
-alter table T_DOCUMENT add column DOC_LANGUAGE_C varchar(3) default 'fra' not null;
-update T_CONFIG set CFG_VALUE_C='5' where CFG_ID_C='DB_VERSION';
diff --git a/docs-core/src/main/resources/db/update/dbupdate-006-0.sql b/docs-core/src/main/resources/db/update/dbupdate-006-0.sql
deleted file mode 100644
index 1377ff03..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-006-0.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-alter table T_USER add column USE_PRIVATEKEY_C varchar(100) default '' not null;
-update T_USER set USE_PRIVATEKEY_C = 'AdminPk' where USE_ID_C = 'admin';
-update T_CONFIG set CFG_VALUE_C='6' where CFG_ID_C='DB_VERSION';
diff --git a/docs-core/src/main/resources/db/update/dbupdate-007-0.sql b/docs-core/src/main/resources/db/update/dbupdate-007-0.sql
deleted file mode 100644
index 7660c00c..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-007-0.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-alter table T_FILE alter column FIL_IDDOC_C set null;
-alter table T_FILE add column FIL_IDUSER_C varchar(36);
-update T_CONFIG set CFG_VALUE_C='7' where CFG_ID_C='DB_VERSION';
diff --git a/docs-core/src/main/resources/db/update/dbupdate-008-0.sql b/docs-core/src/main/resources/db/update/dbupdate-008-0.sql
deleted file mode 100644
index 639e641b..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-008-0.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-create cached table T_ACL ( ACL_ID_C varchar(36) not null, ACL_PERM_C varchar(30) not null, ACL_SOURCEID_C varchar(36) not null, ACL_TARGETID_C varchar(36) not null, ACL_DELETEDATE_D datetime, primary key (ACL_ID_C) );
-drop table T_SHARE;
-create cached table T_SHARE ( SHA_ID_C varchar(36) not null, SHA_NAME_C varchar(36), SHA_CREATEDATE_D datetime, SHA_DELETEDATE_D datetime, primary key (SHA_ID_C) );
-update T_CONFIG set CFG_VALUE_C='8' where CFG_ID_C='DB_VERSION';
diff --git a/docs-core/src/main/resources/db/update/dbupdate-009-0.sql b/docs-core/src/main/resources/db/update/dbupdate-009-0.sql
deleted file mode 100644
index cd34b316..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-009-0.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-create index IDX_ACL_COMPOSITE on T_ACL (ACL_SOURCEID_C, ACL_TARGETID_C, ACL_PERM_C, ACL_DELETEDATE_D);
-update T_CONFIG set CFG_VALUE_C='9' where CFG_ID_C='DB_VERSION';
\ No newline at end of file
diff --git a/docs-core/src/main/resources/db/update/dbupdate-010-0.sql b/docs-core/src/main/resources/db/update/dbupdate-010-0.sql
deleted file mode 100644
index 3f0127d2..00000000
--- a/docs-core/src/main/resources/db/update/dbupdate-010-0.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-alter table T_FILE alter column FIL_IDUSER_C set not null;
-alter table T_AUTHENTICATION_TOKEN add column AUT_IP_C varchar(45);
-alter table T_AUTHENTICATION_TOKEN add column AUT_UA_C varchar(1000);
-create cached table T_AUDIT_LOG ( LOG_ID_C varchar(36) not null, LOG_IDENTITY_C varchar(36) not null, LOG_CLASSENTITY_C varchar(50) not null, LOG_TYPE_C varchar(50) not null, LOG_MESSAGE_C varchar(1000), LOG_CREATEDATE_D datetime, primary key (LOG_ID_C) );
-create index IDX_LOG_COMPOSITE on T_AUDIT_LOG (LOG_IDENTITY_C, LOG_CLASSENTITY_C);
-alter table T_DOCUMENT_TAG add column DOT_DELETEDATE_D datetime;
-update T_CONFIG set CFG_VALUE_C='10' where CFG_ID_C='DB_VERSION';
\ No newline at end of file
diff --git a/docs-core/src/test/resources/hibernate.properties b/docs-core/src/test/resources/hibernate.properties
index 44bb9ddf..edd32f92 100644
--- a/docs-core/src/test/resources/hibernate.properties
+++ b/docs-core/src/test/resources/hibernate.properties
@@ -1,5 +1,5 @@
-hibernate.connection.driver_class=org.hsqldb.jdbcDriver
-hibernate.connection.url=jdbc:hsqldb:mem:docs
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:mem:docs
hibernate.connection.username=sa
hibernate.connection.password=
hibernate.hbm2ddl.auto=none
diff --git a/docs-parent/pom.xml b/docs-parent/pom.xml
index 7124e327..dd6eaf53 100644
--- a/docs-parent/pom.xml
+++ b/docs-parent/pom.xml
@@ -24,7 +24,7 @@
1.6.4
1.6.6
4.7
- 2.3.0
+ 1.4.188
1.17
0.3m
3.1.6
@@ -35,6 +35,8 @@
4.2.0
1.0.5
4.2
+ 1.8.10
+ 1.49
1.9.18-m
4.1.0.Final
@@ -62,8 +64,6 @@
8.1.2.v20120308
1.0.1
1.7
- 1.8.8
- 1.49
@@ -317,6 +317,12 @@
jersey-multipart
${com.sun.jersey.version}
+
+
+ com.sun.jersey
+ jersey-client
+ ${com.sun.jersey.version}
+
com.sun.grizzly
@@ -331,9 +337,9 @@
- org.hsqldb
- hsqldb
- ${org.hsqldb.hsqldb.version}
+ com.h2database
+ h2
+ ${com.h2database.h2.version}
diff --git a/docs-stress/pom.xml b/docs-stress/pom.xml
new file mode 100644
index 00000000..6b7c1efe
--- /dev/null
+++ b/docs-stress/pom.xml
@@ -0,0 +1,71 @@
+
+
+
+
+ com.sismics.docs
+ docs-parent
+ 1.0-SNAPSHOT
+ ../docs-parent
+
+
+ 4.0.0
+ docs-stress
+ jar
+ Docs Stress
+
+
+
+
+ com.sun.jersey
+ jersey-client
+
+
+
+
+ com.sismics.docs
+ docs-web-common
+ test-jar
+
+
+
+
+ com.google.guava
+ guava
+
+
+
+ log4j
+ log4j
+
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ org.slf4j
+ jcl-over-slf4j
+
+
+
+ junit
+ junit
+
+
+
+
+
+
+
+ src/main/resources
+
+
+
+
diff --git a/docs-stress/src/main/java/com/sismics/docs/stress/Main.java b/docs-stress/src/main/java/com/sismics/docs/stress/Main.java
new file mode 100644
index 00000000..fa349ed2
--- /dev/null
+++ b/docs-stress/src/main/java/com/sismics/docs/stress/Main.java
@@ -0,0 +1,140 @@
+package com.sismics.docs.stress;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.ws.rs.core.MediaType;
+
+import junit.framework.Assert;
+
+import org.codehaus.jettison.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.sismics.docs.rest.filter.CookieAuthenticationFilter;
+import com.sismics.docs.rest.util.ClientUtil;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+import com.sun.jersey.multipart.FormDataBodyPart;
+import com.sun.jersey.multipart.FormDataMultiPart;
+
+/**
+ * Stress app for Sismics Docs.
+ *
+ * @author bgamard
+ */
+public class Main {
+ /**
+ * Logger.
+ */
+ private static final Logger log = LoggerFactory.getLogger(Main.class);
+
+ private static final String API_URL = "http://localhost:9999/docs-web/api/";
+ private static final int USER_COUNT = 50;
+ private static final int DOCUMENT_PER_USER_COUNT = 2000;
+ private static final int TAG_PER_USER_COUNT = 20;
+ private static final int FILE_PER_DOCUMENT_COUNT = 0;
+
+ private static Client client = Client.create();
+ private static ClientUtil clientUtil;
+
+ private static Set userSet = Sets.newHashSet();
+
+ /**
+ * Entry point.
+ *
+ * @param args Args
+ */
+ public static void main(String[] args) {
+ log.info("Starting stress test...");
+
+ WebResource resource = client.resource(API_URL);
+ clientUtil = new ClientUtil(resource);
+
+ // Create users
+ for (int i = 0; i < USER_COUNT; i++) {
+ String username = generateString();
+ clientUtil.createUser(username);
+ userSet.add(new User(username, (clientUtil.login(username))));
+ log.info("Created user " + (i + 1) + "/" + USER_COUNT);
+ }
+
+ // Create tags for each user
+ int tagCreatedCount = 1;
+ for (User user : userSet) {
+ WebResource tagResource = resource.path("/tag");
+ tagResource.addFilter(new CookieAuthenticationFilter(user.authToken));
+
+ for (int j = 0; j < TAG_PER_USER_COUNT; j++) {
+ MultivaluedMapImpl postParams = new MultivaluedMapImpl();
+ String name = generateString();
+ postParams.add("name", name);
+ postParams.add("color", "#ff0000");
+ ClientResponse response = tagResource.put(ClientResponse.class, postParams);
+ JSONObject json = response.getEntity(JSONObject.class);
+ user.tagList.add(json.optString("id"));
+ log.info("Created tag " + (tagCreatedCount++) + "/" + TAG_PER_USER_COUNT * USER_COUNT);
+ }
+ }
+
+ // Create documents for each user
+ int documentCreatedCount = 1;
+ for (User user : userSet) {
+ for (int i = 0; i < DOCUMENT_PER_USER_COUNT; i++) {
+ WebResource documentResource = resource.path("/document");
+ documentResource.addFilter(new CookieAuthenticationFilter(user.authToken));
+ MultivaluedMapImpl postParams = new MultivaluedMapImpl();
+ postParams.add("title", generateString());
+ postParams.add("description", generateString());
+ postParams.add("tags", user.tagList.get(ThreadLocalRandom.current().nextInt(user.tagList.size()))); // Random tag
+ postParams.add("language", "eng");
+ long createDate = new Date().getTime();
+ postParams.add("create_date", createDate);
+ ClientResponse response = documentResource.put(ClientResponse.class, postParams);
+ JSONObject json = response.getEntity(JSONObject.class);
+ String documentId = json.optString("id");
+ log.info("Created document " + (documentCreatedCount++) + "/" + DOCUMENT_PER_USER_COUNT * USER_COUNT + " for user: " + user.username);
+
+ // Add files for each document
+ for (int j = 0; j < FILE_PER_DOCUMENT_COUNT; j++) {
+ WebResource fileResource = resource.path("/file");
+ fileResource.addFilter(new CookieAuthenticationFilter(user.authToken));
+ FormDataMultiPart form = new FormDataMultiPart();
+ InputStream file = Main.class.getResourceAsStream("/empty.png");
+ FormDataBodyPart fdp = new FormDataBodyPart("file",
+ new BufferedInputStream(file),
+ MediaType.APPLICATION_OCTET_STREAM_TYPE);
+ form.bodyPart(fdp);
+ form.field("id", documentId);
+ response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form);
+ Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
+ }
+ }
+ }
+ }
+
+ private static String generateString() {
+ return UUID.randomUUID().toString().replace("-", "");
+ }
+
+ private static class User {
+ public String username;
+ public List tagList = Lists.newArrayList();
+ public String authToken;
+
+ public User(String username, String authToken) {
+ this.username = username;
+ this.authToken = authToken;
+ }
+ }
+}
diff --git a/docs-stress/src/main/resources/empty.png b/docs-stress/src/main/resources/empty.png
new file mode 100644
index 00000000..cee81591
Binary files /dev/null and b/docs-stress/src/main/resources/empty.png differ
diff --git a/docs-stress/src/main/resources/log4j.properties b/docs-stress/src/main/resources/log4j.properties
new file mode 100644
index 00000000..d7ea887b
--- /dev/null
+++ b/docs-stress/src/main/resources/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootCategory=WARN, CONSOLE
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d{DATE} %p %l %m %n
+
+log4j.logger.com.sismics=DEBUG
diff --git a/docs-web-common/pom.xml b/docs-web-common/pom.xml
index b7cfdccf..736159da 100644
--- a/docs-web-common/pom.xml
+++ b/docs-web-common/pom.xml
@@ -97,12 +97,6 @@
test
-
- org.hsqldb
- hsqldb
- test
-
-
org.subethamail
subethasmtp-wiser
diff --git a/docs-web-common/src/main/java/com/sismics/util/filter/TokenBasedSecurityFilter.java b/docs-web-common/src/main/java/com/sismics/util/filter/TokenBasedSecurityFilter.java
index b469885d..bec48de0 100644
--- a/docs-web-common/src/main/java/com/sismics/util/filter/TokenBasedSecurityFilter.java
+++ b/docs-web-common/src/main/java/com/sismics/util/filter/TokenBasedSecurityFilter.java
@@ -1,26 +1,34 @@
package com.sismics.util.filter;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+
+import org.joda.time.DateTimeZone;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.sismics.docs.core.constant.Constants;
import com.sismics.docs.core.dao.jpa.AuthenticationTokenDao;
import com.sismics.docs.core.dao.jpa.RoleBaseFunctionDao;
import com.sismics.docs.core.dao.jpa.UserDao;
import com.sismics.docs.core.model.jpa.AuthenticationToken;
import com.sismics.docs.core.model.jpa.User;
+import com.sismics.docs.core.util.TransactionUtil;
import com.sismics.security.AnonymousPrincipal;
import com.sismics.security.UserPrincipal;
import com.sismics.util.LocaleUtil;
-import org.joda.time.DateTimeZone;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.*;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Set;
/**
* This filter is used to authenticate the user having an active session via an authentication token stored in database.
@@ -110,6 +118,7 @@ public class TokenBasedSecurityFilter implements Filter {
// Update the last connection date
authenticationTokenDao.updateLastConnectionDate(authenticationToken.getId());
+ TransactionUtil.commit();
} else {
injectAnonymousUser(request);
}
diff --git a/docs-web/pom.xml b/docs-web/pom.xml
index 6177bacc..8f0f4640 100644
--- a/docs-web/pom.xml
+++ b/docs-web/pom.xml
@@ -85,8 +85,8 @@
- org.hsqldb
- hsqldb
+ com.h2database
+ h2
@@ -152,37 +152,6 @@
-
-
-
-
- org.eclipse.m2e
- lifecycle-mapping
- 1.0.0
-
-
-
-
-
- com.samaxes.maven
-
- minify-maven-plugin
-
- [1.5,)
-
- minify
-
-
-
-
-
-
-
-
-
-
-
-
@@ -234,6 +203,53 @@
+
+
+ stress
+
+
+ env
+ stress
+
+
+
+
+
+
+ src/stress/resources
+ false
+
+ **/config.properties
+
+
+
+ src/stress/resources
+ true
+
+ **/config.properties
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+
+ 0
+
+ /docs-web
+ target/classes;../docs-core/target/classes
+ src/stress/main/webapp/web-override.xml
+
+ STOPKEY
+ 1099
+
+
+
+
+
+
prod
diff --git a/docs-web/src/dev/resources/config.properties b/docs-web/src/dev/resources/config.properties
index f935e8fa..c7bed5d9 100644
--- a/docs-web/src/dev/resources/config.properties
+++ b/docs-web/src/dev/resources/config.properties
@@ -1,3 +1,3 @@
api.current_version=${project.version}
api.min_version=1.0
-db.version=10
\ No newline at end of file
+db.version=0
\ No newline at end of file
diff --git a/docs-web/src/dev/resources/hibernate.properties b/docs-web/src/dev/resources/hibernate.properties
index f229d8f0..0f7dfbdd 100644
--- a/docs-web/src/dev/resources/hibernate.properties
+++ b/docs-web/src/dev/resources/hibernate.properties
@@ -1,5 +1,5 @@
-hibernate.connection.driver_class=org.hsqldb.jdbcDriver
-hibernate.connection.url=jdbc:hsqldb:mem:docs
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:mem:docs
hibernate.connection.username=sa
hibernate.connection.password=
hibernate.hbm2ddl.auto=none
diff --git a/docs-web/src/prod/resources/config.properties b/docs-web/src/prod/resources/config.properties
index f935e8fa..c7bed5d9 100644
--- a/docs-web/src/prod/resources/config.properties
+++ b/docs-web/src/prod/resources/config.properties
@@ -1,3 +1,3 @@
api.current_version=${project.version}
api.min_version=1.0
-db.version=10
\ No newline at end of file
+db.version=0
\ No newline at end of file
diff --git a/docs-web/src/stress/main/webapp/web-override.xml b/docs-web/src/stress/main/webapp/web-override.xml
new file mode 100644
index 00000000..ea56b8c9
--- /dev/null
+++ b/docs-web/src/stress/main/webapp/web-override.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ default
+
+ useFileMappedBuffer
+ false
+
+
+
diff --git a/docs-web/src/stress/resources/config.properties b/docs-web/src/stress/resources/config.properties
new file mode 100644
index 00000000..c7bed5d9
--- /dev/null
+++ b/docs-web/src/stress/resources/config.properties
@@ -0,0 +1,3 @@
+api.current_version=${project.version}
+api.min_version=1.0
+db.version=0
\ No newline at end of file
diff --git a/docs-web/src/stress/resources/hibernate.properties b/docs-web/src/stress/resources/hibernate.properties
new file mode 100644
index 00000000..b6b34941
--- /dev/null
+++ b/docs-web/src/stress/resources/hibernate.properties
@@ -0,0 +1 @@
+\ugggg
\ No newline at end of file
diff --git a/docs-web/src/stress/resources/log4j.properties b/docs-web/src/stress/resources/log4j.properties
new file mode 100644
index 00000000..0b05e8e9
--- /dev/null
+++ b/docs-web/src/stress/resources/log4j.properties
@@ -0,0 +1,8 @@
+log4j.rootCategory=WARN, CONSOLE, MEMORY
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d{DATE} %p %l %m %n
+log4j.appender.MEMORY=com.sismics.util.log4j.MemoryAppender
+log4j.appender.MEMORY.size=1000
+
+log4j.logger.com.sismics=DEBUG
diff --git a/docs-web/src/test/resources/hibernate.properties b/docs-web/src/test/resources/hibernate.properties
index 8385a2fb..edd32f92 100644
--- a/docs-web/src/test/resources/hibernate.properties
+++ b/docs-web/src/test/resources/hibernate.properties
@@ -1,5 +1,5 @@
-hibernate.connection.driver_class=org.hsqldb.jdbcDriver
-hibernate.connection.url=jdbc:hsqldb:mem:docs;get_column_name=false
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:mem:docs
hibernate.connection.username=sa
hibernate.connection.password=
hibernate.hbm2ddl.auto=none