diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..030ca8708 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,86 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/configuration-reference/#job +jobs: + build-and-test: + machine: + image: ubuntu-2204:current + resource_class: large + + steps: + - checkout + - run: + name: Setup java version + command: | + sudo apt update + sudo apt-get install openjdk-11-jdk + sudo update-java-alternatives --set java-1.11.0-openjdk-amd64 + java -version + - run: + name: Compile and Run Tests Saving docker image as tar file + command: | + mvn clean install + - run: + name: Saving docker image as tar file + command: | + docker save -o ./sync-endpoint-docker-swarm/sync-endpoint.tar odk/sync-endpoint:latest + + - persist_to_workspace: + root: . + paths: + - . + - save_cache: + key: v1-odk/sync-endpoint + paths: + - . + deploy-jar: + docker: + - image: circleci/openjdk:11 + + steps: + - restore_cache: + key: v1-odk/sync-endpoint + - attach_workspace: + at: /home/circleci/project + - run: + name: Deploying jars to github maven repo + command: | + mvn -gs settings.xml -N clean deploy + mvn -gs settings.xml -pl 'odkx-rest-interface' clean deploy -DskipTests + + deploy-image: + machine: + image: ubuntu-2204:current + + steps: + - restore_cache: + key: v1-odk/sync-endpoint + - attach_workspace: + at: /home/circleci/project + - run: + name: Setting up ghcr repo + command: | + export CR_PAT=$GITHUB_TOKEN + echo $CR_PAT | docker login ghcr.io -u odk-x-bot --password-stdin + docker load -i ./sync-endpoint-docker-swarm/sync-endpoint.tar + - run: + name: Pushing the image to GHCR + command: | + docker tag odk/sync-endpoint:latest ghcr.io/odk-x/sync-endpoint:latest + docker push ghcr.io/odk-x/sync-endpoint:latest + +# Invoke jobs via workflows +# See: https://circleci.com/docs/configuration-reference/#workflows +workflows: + Build-Test-Deploy: + jobs: + - build-and-test + - deploy-jar: + requires: + - build-and-test + - deploy-image: + requires: + - build-and-test + diff --git a/mysql-test/external-resources/integration.properties b/mysql-test/external-resources/integration.properties index 043a19899..b7651404d 100644 --- a/mysql-test/external-resources/integration.properties +++ b/mysql-test/external-resources/integration.properties @@ -3,6 +3,16 @@ test.server.port = 8888 test.server.secure.port = 8443 test.sync.dir = ../src/it/testfiles/sync +test.adminUsername=testadmin +test.adminPassword=admin123 + +test.superUsername=testsuper +test.superPassword=super123 + +test.syncUsername=testuser +test.syncPassword=user123 + + jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.resourceName=jdbc/odk_aggregate jdbc.url=jdbc:mysql://localhost/odk_unit?autoDeserialize=true&useSSL=false diff --git a/mysql-test/mysql/create_db_and_user.sql b/mysql-test/mysql/create_db_and_user.sql index e194942b2..ada6f20e2 100644 --- a/mysql-test/mysql/create_db_and_user.sql +++ b/mysql-test/mysql/create_db_and_user.sql @@ -1,4 +1,5 @@ CREATE USER 'odk_unit'@'%' IDENTIFIED BY 'odk_unit'; +CREATE DATABASE odk_unit; GRANT ALL PRIVILEGES ON odk_unit.* TO 'odk_unit'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES; diff --git a/mysql-test/openldap/bootstrap.ldif b/mysql-test/openldap/bootstrap.ldif index a0ef30946..fd75eb990 100644 --- a/mysql-test/openldap/bootstrap.ldif +++ b/mysql-test/openldap/bootstrap.ldif @@ -1,30 +1,31 @@ -dn: ou=groups,{{ LDAP_BASE_DN }} +dn: ou=groups,dc=example,dc=org changetype: add ou: groups objectClass: organizationalUnit objectClass: top -dn: ou=people,{{ LDAP_BASE_DN }} +dn: ou=people,dc=example,dc=org changetype: add ou: people objectClass: organizationalUnit objectClass: top -dn: ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: ou=default_prefix,ou=groups,dc=example,dc=org changetype: add ou: default_prefix objectClass: organizationalUnit objectClass: top -dn: gidNumber=500,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=500,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix site_admins gidNumber: 500 objectClass: posixGroup objectClass: top memberUid: john +memberUid: testadmin -dn: gidNumber=501,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=501,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix administer_tables gidNumber: 501 @@ -32,42 +33,44 @@ objectClass: posixGroup objectClass: top memberUid: john -dn: gidNumber=502,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=502,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix super_user_tables gidNumber: 502 objectClass: posixGroup objectClass: top +memberUid: testsuper -dn: gidNumber=503,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=503,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix synchronize_tables gidNumber: 503 objectClass: posixGroup objectClass: top +memberUid: testuser -dn: gidNumber=504,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=504,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix form_managers gidNumber: 504 objectClass: posixGroup objectClass: top -dn: gidNumber=505,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=505,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix data_viewers gidNumber: 505 objectClass: posixGroup objectClass: top -dn: gidNumber=506,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=506,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix data_collectors gidNumber: 506 objectClass: posixGroup objectClass: top -dn: uid=john,ou=people,{{ LDAP_BASE_DN }} +dn: uid=john,ou=people,dc=example,dc=org changetype: add cn: john gidnumber: 501 @@ -79,3 +82,43 @@ sn: john uid: john uidnumber: 1000 userpassword: {MD5}JdVa0oOqQAr0ZMdtcTwHrQ== + +dn: uid=testsuper,ou=people,dc=example,dc=org +changetype: add +cn: testsuper +gidnumber: 502 +homedirectory: /home/users/testsuper +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: testsuper +uid: testsuper +uidnumber: 1001 +userpassword: {MD5}81NkvICLB5hT3loeND5xWQ== + + +dn: uid=testuser,ou=people,dc=example,dc=org +changetype: add +cn: testuser +gidnumber: 503 +homedirectory: /home/users/testuser +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: testuser +uid: testuser +uidnumber: 1002 +userpassword: {MD5}atFLqZhuNhVCPfyiVtBOPw== + +dn: uid=testadmin,ou=people,dc=example,dc=org +changetype: add +cn: testadmin +gidnumber: 500 +homedirectory: /home/users/testadmin +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: testadmin +uid: testadmin +uidnumber: 1003 +userpassword: {MD5}AZICOnu9cyUFFvBp3xi1AA== diff --git a/mysql-test/pom.xml b/mysql-test/pom.xml index 7164bba6d..fb57c826d 100644 --- a/mysql-test/pom.xml +++ b/mysql-test/pom.xml @@ -7,13 +7,15 @@ org.opendatakit sync-endpoint-common-dependencies - 2.1.9 + 2.2.0-SNAPSHOT ../sync-endpoint-common-dependencies/pom.xml mysql-test jar + ${toplevel.directory}/src/main/java + ${toplevel.directory}/src/test/java org.apache.maven.plugins @@ -54,29 +56,8 @@ db - mysql:5.7 - - SetupScripts - - - - ${project.basedir}/mysql/create_db_and_user.sql - 777 - unix - - - ${project.basedir}/mysql/executeMysql.sh - 777 - unix - - - - /tmp - dir - auto - + mysql:8.0 - custom @@ -86,6 +67,8 @@ odkdatabase odk_unit + odk_unit + odk_unit mysqlPassword @@ -94,9 +77,6 @@ - - /tmp/executeMysql.sh - @@ -193,6 +173,22 @@ org.apache.maven.plugins maven-compiler-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + false + ${surefire.argLine} + + 8888 + localhost + john + 12345678 + testadmin + admin123 + + + org.apache.maven.plugins maven-failsafe-plugin @@ -206,6 +202,8 @@ localhost john 12345678 + testadmin + admin123 @@ -233,8 +231,8 @@ pom - mysql - mysql-connector-java + com.mysql + mysql-connector-j diff --git a/mysql-test/resources/jdbc.properties b/mysql-test/resources/jdbc.properties index 3696e05e8..70deb3971 100644 --- a/mysql-test/resources/jdbc.properties +++ b/mysql-test/resources/jdbc.properties @@ -1,6 +1,6 @@ -jdbc.driverClassName=com.mysql.jdbc.Driver +jdbc.driverClassName=com.mysql.cj.jdbc.Driver jdbc.resourceName=jdbc/odk_aggregate -jdbc.url=jdbc:mysql://odkdatabase/odk_unit?autoDeserialize=true&useSSL=false +jdbc.url=jdbc:mysql://odkdatabase/odk_unit?autoDeserialize=true&allowPublicKeyRetrieval=true&useSSL=false jdbc.username=odk_unit jdbc.password=odk_unit jdbc.schema=odk_unit \ No newline at end of file diff --git a/odk-rest-interface/pom.xml b/odkx-rest-interface/pom.xml similarity index 82% rename from odk-rest-interface/pom.xml rename to odkx-rest-interface/pom.xml index 41302c88d..7b1c3d1b1 100644 --- a/odk-rest-interface/pom.xml +++ b/odkx-rest-interface/pom.xml @@ -5,21 +5,22 @@ org.opendatakit sync-endpoint - 2.1.9 + 2.2.0-SNAPSHOT ../pom.xml - odk-rest-interface + odkx-rest-interface jar ${project.basedir}/../src/main/java ${project.basedir}/target + org.apache.maven.plugins maven-compiler-plugin - org/opendatakit/aggregate/odktables/rest/** + org/opendatakit/aggregate/odktables/rest/**/*.java @@ -28,7 +29,6 @@ org.apache.maven.plugins maven-jar-plugin - maven-javadoc-plugin @@ -61,25 +61,6 @@ - - - - maven-dependency-plugin - - - package - - copy-dependencies - - - ${project.build.directory} - simple-xml,joda-time,commons-text - - - - - - diff --git a/odkx-rest-interface/settings.xml b/odkx-rest-interface/settings.xml new file mode 100644 index 000000000..a560f9eb3 --- /dev/null +++ b/odkx-rest-interface/settings.xml @@ -0,0 +1,36 @@ + + + + github + + + + + github + + + central + https://repo1.maven.org/maven2 + + + github + https://maven.pkg.github.com/odk-x/sync-endpoint + + true + + + + + + + + + github + ${env.GITHUB_USERNAME} + ${env.GITHUB_TOKEN} + + + diff --git a/pom.xml b/pom.xml index 7f5c67304..7175f15a8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.opendatakit sync-endpoint - 2.1.9 + 2.2.0-SNAPSHOT pom @@ -28,72 +28,69 @@ ${project.basedir}/../src/test/testfiles/sync UTF-8 - 8 - 8 - 8 + 11 + 11 + 11 3.0.2 - 4.13.1 - 2.0.2 + 4.13.2 + 1.0.b2 1.7.30 - 1.68 - 2.8.6 - 30.1.1-jre 1.4.0 - 2.10.10 + 2.12.5 2.3.0 - 4.1.60.Final - 2.1.5 + 4.1.104.Final - 5.1.47 - 42.2.18 + 8.2.0 + 42.7.1 4.0.1 1.3 2.3.1 + 8.0.1 + 2.0 - 0.34.1 + 0.43.4 - 4.5.13 - 4.4.14 - 4.5.13 + 5.3 + 5.2.4 1.4 - 2.9.0 - 2.8.0 - 1.4 - 2.8.0 - 1.9 - 1.2 + 2.12.0 + 2.11.0 + 1.5 + 2.15.1 + 1.11.0 + 1.3.0 + 1.15 1.0 - - 3.0.0-M5 - 3.0.0-M5 + 3.2.3 -Xms300m -Xmx3048m - 3.0.0-M5 - 3.2.0 - 3.2.0 - 3.2.0 - 3.2.1 - 3.3.1 - 3.8.1 - 3.1.2 - 1.1.0 - 3.2.0 + 3.2.3 + 3.3.0 + 3.6.3 + 3.3.0 + 3.4.0 + 3.12.0 + 3.6.1 + 3.3.1 + 3.3.2 + 3.1.1 + + 3.5.0 + 1.5.0 - 2.11.4 - 2.11.4 2.11.4 - 5.2.13.RELEASE - 5.1.13.RELEASE - 2.3.3.RELEASE + 5.3.29 + 5.6.12 + 2.4.1 org.opendatakit @@ -129,19 +146,6 @@ sync-endpoint-docker-test ${project.version} - - - javax - javaee-web-api - 6.0 - provided - - - javax.ws.rs - javax.ws.rs-api - 2.0 - - org.apache.commons commons-pool2 @@ -152,149 +156,70 @@ commons-dbcp2 ${org.apache.commons.commons-dhcp2.version} - - - - com.microsoft.sqlserver - mssql-jdbc - 7.2.0.jre8 - compile - - - - com.microsoft.azure - adal4j - 1.6.4 - compile - - - com.google.code.gson - gson - - - org.slf4j - slf4j-api - - - - - - org.bouncycastle - bcprov-jdk15on - ${org.bouncycastle.version} - compile - - - - org.bouncycastle - bcpkix-jdk15on - ${org.bouncycastle.version} - compile - commons-fileupload commons-fileupload ${org.apache.commons.commons-fileupload.version} - jar - compile commons-io commons-io ${org.apache.commons.commons-io.version} - jar - compile org.apache.commons commons-text ${org.apache.commons.commons-text.version} - jar - compile commons-logging commons-logging ${org.apache.commons.commons-logging.version} - jar - compile - - - com.google.code.gson - gson - ${com.google.code.gson.version} - jar - compile - - - com.google.guava - guava - ${com.google.guava.version} - jar - compile - org.apache.httpcomponents - httpclient - ${apache.httpclient.version} - - - commons-codec - commons-codec - - + commons-codec + commons-codec + ${org.apache.commons.commons-codec.version} - org.apache.httpcomponents - httpcore - ${apache.httpcore.version} + org.apache.httpcomponents.client5 + httpclient5 + ${apache.httpclient5.version} - org.apache.httpcomponents - httpmime - ${apache.httpmime.version} + org.apache.httpcomponents.core5 + httpcore5 + ${apache.httpcore5.version} com.fasterxml.jackson.core jackson-annotations - ${com.fasterxml.jackson.base.version} - jar - compile + ${com.fasterxml.jackson.version} com.fasterxml.jackson.core jackson-core - ${com.fasterxml.jackson.core.version} - jar - compile + ${com.fasterxml.jackson.version} com.fasterxml.jackson.core jackson-databind ${com.fasterxml.jackson.version} - jar - compile com.fasterxml.jackson.dataformat jackson-dataformat-xml - ${com.fasterxml.jackson.base.version} - jar - compile + ${com.fasterxml.jackson.version} com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider - ${com.fasterxml.jackson.base.version} - jar - compile + ${com.fasterxml.jackson.version} com.fasterxml.jackson.jaxrs jackson-jaxrs-xml-provider - ${com.fasterxml.jackson.base.version} - jar - compile + ${com.fasterxml.jackson.version} com.github.jai-imageio @@ -305,8 +230,6 @@ joda-time joda-time ${joda-time.version} - jar - compile com.google.code.findbugs @@ -317,12 +240,10 @@ net.sf.kxml kxml2 ${net.sf.kxml.kxml2.version} - jar - compile - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${mysql.mysql-connector-java.version} test @@ -330,15 +251,6 @@ org.postgresql postgresql ${org.postgresql.version} - jar - compile - - - javax.servlet - javax.servlet-api - ${javax.servlet.servlet-api.version} - jar - provided org.slf4j @@ -354,8 +266,6 @@ org.springframework spring-aop ${org.springframework.version} - jar - compile org.springframework @@ -366,29 +276,21 @@ org.springframework spring-beans ${org.springframework.version} - jar - compile org.springframework spring-context ${org.springframework.version} - jar - compile org.springframework spring-context-support ${org.springframework.version} - jar - compile org.springframework spring-core ${org.springframework.version} - jar - compile org.springframework @@ -422,8 +324,6 @@ org.springframework spring-jdbc ${org.springframework.version} - jar - compile org.springframework @@ -453,13 +353,11 @@ org.springframework spring-tx ${org.springframework.version} - compile org.springframework spring-web ${org.springframework.version} - compile org.springframework.security @@ -524,19 +422,6 @@ ${junit.version} test - - - net.lightbody.bmp - browsermob-core - ${net.lightbody.bmp.browsermob-core.version} - test - - - org.slf4j - jcl-over-slf4j - - - io.netty netty-all @@ -572,8 +457,6 @@ ${maven-dependency-plugin.version} - org.apache.maven.plugins maven-compiler-plugin ${maven.compiler.plugin.version} @@ -581,22 +464,6 @@ ${java.version} ${java.version} - - - compile-java-source - compile - - compile - - - - compile-test-source - test-compile - - testCompile - - - org.apache.maven.plugins @@ -618,26 +485,6 @@ maven-surefire-plugin ${maven.surefire.plugin.version} - - org.codehaus.mojo - build-helper-maven-plugin - ${build.helper.maven.plugin.version} - - - add-java-source - - generate-sources - - add-source - - - - ${toplevel.directory}/src/main/java - - - - - org.apache.maven.plugins maven-war-plugin @@ -659,14 +506,50 @@ org.apache.maven.plugins maven-failsafe-plugin - ${maven.surefire.plugin.version} + ${maven.failsafe.plugin.version} + + + org.apache.maven.plugins + maven-clean-plugin + ${maven-clean-plugin.version} + + + org.apache.maven.plugins + maven-install-plugin + ${maven-install-plugin.version} org.codehaus.mojo flatten-maven-plugin ${flatten-maven-plugin.version} + + org.codehaus.mojo + build-helper-maven-plugin + ${build.helper.maven.plugin.version} + + + org.basepom.maven + dependency-versions-check-maven-plugin + + + + apr + + dependency:dependencyA + + + + + + + + github + GitHubPackages + https://maven.pkg.github.com/odk-x/sync-endpoint + + diff --git a/postgres-test/external-resources/integration.properties b/postgres-test/external-resources/integration.properties index b08b29f9a..5cd5716c0 100644 --- a/postgres-test/external-resources/integration.properties +++ b/postgres-test/external-resources/integration.properties @@ -3,6 +3,15 @@ test.server.port = 8888 test.server.secure.port = 8443 test.sync.dir = ../src/it/testfiles/sync +test.adminUsername=testadmin +test.adminPassword=admin123 + +test.superUsername=testsuper +test.superPassword=super123 + +test.syncUsername=testuser +test.syncPassword=user123 + jdbc.driverClassName=org.postgresql.Driver jdbc.resourceName=jdbc/odk_aggregate jdbc.url=jdbc:postgresql://localhost/postgres?autoDeserialize=true diff --git a/postgres-test/openldap/Dockerfile b/postgres-test/openldap/Dockerfile index 578129150..30e399a85 100644 --- a/postgres-test/openldap/Dockerfile +++ b/postgres-test/openldap/Dockerfile @@ -1,4 +1,4 @@ -FROM osixia/openldap +FROM osixia/openldap:1.2.2 # should move this file to ldif/custom directory # feature should be in the next release diff --git a/postgres-test/openldap/bootstrap.ldif b/postgres-test/openldap/bootstrap.ldif index a0ef30946..fd75eb990 100644 --- a/postgres-test/openldap/bootstrap.ldif +++ b/postgres-test/openldap/bootstrap.ldif @@ -1,30 +1,31 @@ -dn: ou=groups,{{ LDAP_BASE_DN }} +dn: ou=groups,dc=example,dc=org changetype: add ou: groups objectClass: organizationalUnit objectClass: top -dn: ou=people,{{ LDAP_BASE_DN }} +dn: ou=people,dc=example,dc=org changetype: add ou: people objectClass: organizationalUnit objectClass: top -dn: ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: ou=default_prefix,ou=groups,dc=example,dc=org changetype: add ou: default_prefix objectClass: organizationalUnit objectClass: top -dn: gidNumber=500,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=500,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix site_admins gidNumber: 500 objectClass: posixGroup objectClass: top memberUid: john +memberUid: testadmin -dn: gidNumber=501,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=501,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix administer_tables gidNumber: 501 @@ -32,42 +33,44 @@ objectClass: posixGroup objectClass: top memberUid: john -dn: gidNumber=502,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=502,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix super_user_tables gidNumber: 502 objectClass: posixGroup objectClass: top +memberUid: testsuper -dn: gidNumber=503,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=503,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix synchronize_tables gidNumber: 503 objectClass: posixGroup objectClass: top +memberUid: testuser -dn: gidNumber=504,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=504,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix form_managers gidNumber: 504 objectClass: posixGroup objectClass: top -dn: gidNumber=505,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=505,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix data_viewers gidNumber: 505 objectClass: posixGroup objectClass: top -dn: gidNumber=506,ou=default_prefix,ou=groups,{{ LDAP_BASE_DN }} +dn: gidNumber=506,ou=default_prefix,ou=groups,dc=example,dc=org changetype: add cn: default_prefix data_collectors gidNumber: 506 objectClass: posixGroup objectClass: top -dn: uid=john,ou=people,{{ LDAP_BASE_DN }} +dn: uid=john,ou=people,dc=example,dc=org changetype: add cn: john gidnumber: 501 @@ -79,3 +82,43 @@ sn: john uid: john uidnumber: 1000 userpassword: {MD5}JdVa0oOqQAr0ZMdtcTwHrQ== + +dn: uid=testsuper,ou=people,dc=example,dc=org +changetype: add +cn: testsuper +gidnumber: 502 +homedirectory: /home/users/testsuper +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: testsuper +uid: testsuper +uidnumber: 1001 +userpassword: {MD5}81NkvICLB5hT3loeND5xWQ== + + +dn: uid=testuser,ou=people,dc=example,dc=org +changetype: add +cn: testuser +gidnumber: 503 +homedirectory: /home/users/testuser +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: testuser +uid: testuser +uidnumber: 1002 +userpassword: {MD5}atFLqZhuNhVCPfyiVtBOPw== + +dn: uid=testadmin,ou=people,dc=example,dc=org +changetype: add +cn: testadmin +gidnumber: 500 +homedirectory: /home/users/testadmin +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: testadmin +uid: testadmin +uidnumber: 1003 +userpassword: {MD5}AZICOnu9cyUFFvBp3xi1AA== diff --git a/postgres-test/pom.xml b/postgres-test/pom.xml index 83ef9cedb..b9f69f818 100644 --- a/postgres-test/pom.xml +++ b/postgres-test/pom.xml @@ -7,13 +7,14 @@ org.opendatakit sync-endpoint-common-dependencies - 2.1.9 + 2.2.0-SNAPSHOT ../sync-endpoint-common-dependencies/pom.xml postgres-test jar + ${toplevel.directory}/src/main/java ${toplevel.directory}/src/test/java @@ -21,6 +22,7 @@ maven-dependency-plugin + org.apache.maven.plugins maven-resources-plugin @@ -52,9 +54,8 @@ odk/db-${project.name} db - - postgres:9.6 + postgres:12.17 SC @@ -199,6 +200,8 @@ localhost john 12345678 + testadmin + admin123 @@ -213,6 +216,8 @@ localhost john 12345678 + testadmin + admin123 diff --git a/postgres-test/postgres/create_db_and_user.sql b/postgres-test/postgres/create_db_and_user.sql index 33c0403f6..670edbad7 100644 --- a/postgres-test/postgres/create_db_and_user.sql +++ b/postgres-test/postgres/create_db_and_user.sql @@ -1,3 +1,3 @@ -CREATE USER "odk" WITH UNENCRYPTED PASSWORD 'odk'; +CREATE USER "odk" WITH PASSWORD 'odk'; CREATE SCHEMA "odk_sync" AUTHORIZATION "odk"; GRANT ALL PRIVILEGES ON SCHEMA "odk_sync" TO "odk"; diff --git a/settings.xml b/settings.xml new file mode 100644 index 000000000..7b2396d3c --- /dev/null +++ b/settings.xml @@ -0,0 +1,36 @@ + + + + github + + + + + github + + + central + https://repo1.maven.org/maven2 + + + github + https://maven.pkg.github.com/odk-x/sync-endpoint + + true + + + + + + + + + github + ${env.GITHUB_USERNAME} + ${env.GITHUB_TOKEN} + + + diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/AbstractServiceTest.java b/src/it/java/org/opendatakit/aggregate/odktables/AbstractServiceTest.java similarity index 57% rename from src/it/java/org/opendatakit/aggregate/odktables/api/AbstractServiceTest.java rename to src/it/java/org/opendatakit/aggregate/odktables/AbstractServiceTest.java index e2ae314c1..c0c8f0845 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/AbstractServiceTest.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/AbstractServiceTest.java @@ -1,218 +1,240 @@ -package org.opendatakit.aggregate.odktables.api; - -import net.lightbody.bmp.BrowserMobProxy; -import net.lightbody.bmp.BrowserMobProxyServer; -import net.lightbody.bmp.proxy.auth.AuthType; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.opendatakit.aggregate.odktables.rest.entity.TableDefinition; -import org.opendatakit.aggregate.odktables.rest.entity.TableResource; -import org.opendatakit.aggregate.odktables.rest.entity.TableResourceList; -import org.springframework.http.*; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.client.SimpleClientHttpRequestFactory; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResponseErrorHandler; -import org.springframework.web.client.RestTemplate; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -public abstract class AbstractServiceTest { - - public static final String TABLE_API = "tables/"; - private static BrowserMobProxy proxy; - private static int proxyPort; - - private String baseUrl; - private String appId = "default"; - private URI baseUri; - protected RestTemplate rt; - protected HttpHeaders reqHeaders; - private String tableDefinitionUri = null; - - @BeforeClass - public static void setupProxy() throws Throwable { - String hostname = System.getProperty("test.server.hostname"); - String username = System.getProperty("test.server.username"); - String password = System.getProperty("test.server.password"); - - try { - proxy = new BrowserMobProxyServer(); - } catch (Throwable t) { - t.printStackTrace(); - throw t; - } - proxy.start(0); - proxyPort = proxy.getPort(); - - proxy.stopAutoAuthorization(hostname); - if (username != null && username.length() != 0) { - proxy.autoAuthorization(hostname, username, password, AuthType.BASIC); - } - } - - @AfterClass - public static void teardownProxy() { - if ( proxy != null ) { - proxy.stop(); - proxy = null; - try { - Thread.sleep(500L); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - // call this from any Before action in derived class - public void abstractServiceSetUp() throws Exception, Throwable { - String hostname = System.getProperty("test.server.hostname"); - baseUrl = System.getProperty("test.server.baseUrl", "/"); - String port = System.getProperty("test.server.port"); - - this.baseUri = URI.create("http://" + hostname + ":" + port + baseUrl + "odktables/" + appId + "/"); - - // RestTemplate - try { - this.rt = new RestTemplate(); - - SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); - InetSocketAddress address = - new InetSocketAddress(proxy.getClientBindAddress().getHostAddress(), proxyPort); - - Proxy proxyRef = new Proxy(Proxy.Type.HTTP, address); - factory.setProxy(proxyRef); - factory.setOutputStreaming(false); - - rt.setRequestFactory(factory); - } catch ( Throwable t ) { - t.printStackTrace(); - throw t; - } - - this.rt.setErrorHandler(new ErrorHandler()); - List> converters = new ArrayList>(); - - converters.add(new MappingJackson2HttpMessageConverter()); - // converters.add(new AllEncompassingFormHttpMessageConverter()); - this.rt.setMessageConverters(converters); - - // HttpHeaders - List acceptableMediaTypes = new ArrayList(); - acceptableMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); - - this.reqHeaders = new HttpHeaders(); - reqHeaders.setAccept(acceptableMediaTypes); - reqHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - } - - protected URI resolveUri(String str) { - return baseUri.resolve(str); - } - - @After - public void abstractServiceTearDown() throws Exception { - try { - if ( tableDefinitionUri != null ) { - URI uri = resolveUri(tableDefinitionUri); - this.rt.delete(uri); - } - } catch (Exception e) { - // ignore - System.out.println(e); - } - } - - protected TableResource createTable() throws Throwable { - URI uri = resolveUri(TABLE_API + T.tableId); - - TableDefinition definition = new TableDefinition(T.tableId, null, T.columns); - HttpEntity entity = entity(definition); - - ResponseEntity resp; - try { - resp = rt.exchange(uri, HttpMethod.PUT, entity, TableResource.class); - } catch ( Throwable t ) { - t.printStackTrace(); - throw t; - } - TableResource rsc = resp.getBody(); - tableDefinitionUri = rsc.getDefinitionUri(); - return rsc; - } - - protected TableResource createAltTable() throws Throwable { - URI uri = resolveUri(TABLE_API + T.tableId); - - TableDefinition definition = new TableDefinition(T.tableId, null, T.altcolumns); - HttpEntity entity = entity(definition); - - ResponseEntity resp; - try { - resp = rt.exchange(uri, HttpMethod.PUT, entity, TableResource.class); - } catch ( Throwable t ) { - t.printStackTrace(); - throw t; - } - TableResource rsc = resp.getBody(); - tableDefinitionUri = rsc.getDefinitionUri(); - return rsc; - } - - protected TableResourceList getTables() throws Throwable { - URI uri = resolveUri(TABLE_API); - - ResponseEntity resp; - try { - resp = rt.exchange(uri, HttpMethod.GET, null, TableResourceList.class); - } catch ( Throwable t ) { - t.printStackTrace(); - throw t; - } - TableResourceList trl = resp.getBody(); - return trl; - } - - protected HttpEntity entity(V entity) { - return new HttpEntity(entity, reqHeaders); - } - - private class ErrorHandler implements ResponseErrorHandler { - @Override - public void handleError(ClientHttpResponse resp) throws IOException { - HttpStatus status = resp.getStatusCode(); - String body = readInput(resp.getBody()); - if (status.value() / 100 == 4) - throw new HttpClientErrorException(status, body); - else if (status.value() / 100 == 5) - throw new HttpServerErrorException(status, body); - } - - @Override - public boolean hasError(ClientHttpResponse resp) throws IOException { - return resp.getStatusCode().value() / 100 != 2; - } - - private String readInput(InputStream is) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - StringBuilder sb = new StringBuilder(); - String line; - while ((line = br.readLine()) != null) { - sb.append(line); - } - return sb.toString(); - } - } -} +package org.opendatakit.aggregate.odktables; + + +import org.junit.After; +import org.opendatakit.aggregate.odktables.rest.entity.TableDefinition; +import org.opendatakit.aggregate.odktables.rest.entity.TableResource; +import org.opendatakit.aggregate.odktables.rest.entity.TableResourceList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.stereotype.Component; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractServiceTest { + + //private static final Logger log = LoggerFactory.getLogger(AbstractServiceTest.class); +/* + @Component + public class LoggingInterceptor implements ClientHttpRequestInterceptor { + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { + + logRequest(request, body); + ClientHttpResponse response = execution.execute(request, body); + logResponse(response); + + return response; + } + + private void logRequest(HttpRequest request, byte[] body) throws IOException { + log.warn("===log request start==="); + log.warn("URI: " + request.getURI()); + log.warn("Method: " + request.getMethod()); + log.warn("Headers: " + request.getHeaders()); + log.warn("Request body: " + new String(body, "UTF-8")); + log.warn("===log request end==="); + + } + + private void logResponse(ClientHttpResponse response) throws IOException { + log.warn("===log response start==="); + log.warn("Status code: " + response.getStatusCode()); + log.warn("Status text: " + response.getStatusText()); + log.warn("Headers: " + response.getHeaders()); + log.warn("Response body: " + StreamUtils.copyToString(response.getBody(), Charset.defaultCharset())); + log.warn("===log response end==="); + + } + } +*/ + public static final String TABLE_API = "tables/"; + + private String baseUrl; + private String appId = "default"; + private URI baseUri; + protected RestTemplate rt; + protected HttpHeaders reqHeaders; + private String tableDefinitionUri = null; + + + // call this from any Before action in derived class + public void abstractServiceSetUp() throws Exception, Throwable { + String hostname = System.getProperty("test.server.hostname"); + baseUrl = System.getProperty("test.server.baseUrl", "/"); + String port = System.getProperty("test.server.port"); + + String username = System.getProperty("test.adminUsername"); + String password = System.getProperty("test.adminPassword"); + + this.baseUri = URI.create("http://" + hostname + ":" + port + baseUrl + "odktables/" + appId + "/"); + + // log.warn("baseUri: " + baseUri); + + // RestTemplate + try { + this.rt = new RestTemplate(); + + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + rt.setRequestFactory(new BufferingClientHttpRequestFactory(factory)); + } catch ( Throwable t ) { + t.printStackTrace(); + throw t; + } + + // this.rt.getInterceptors().add(new LoggingInterceptor()); + this.rt.getInterceptors().add(new BasicAuthenticationInterceptor(username, password)); + + + this.rt.setErrorHandler(new ErrorHandler()); + List> converters = new ArrayList>(); + + converters.add(new MappingJackson2HttpMessageConverter()); + // converters.add(new AllEncompassingFormHttpMessageConverter()); + this.rt.setMessageConverters(converters); + + // HttpHeaders + List acceptableMediaTypes = new ArrayList(); + acceptableMediaTypes.add(MediaType.APPLICATION_JSON); + + this.reqHeaders = new HttpHeaders(); + reqHeaders.setAccept(acceptableMediaTypes); + reqHeaders.setContentType(MediaType.APPLICATION_JSON); + } + + protected URI resolveUri(String str) { + return baseUri.resolve(str); + } + + @After + public void abstractServiceTearDown() throws Exception { + try { + if ( tableDefinitionUri != null ) { + URI uri = resolveUri(tableDefinitionUri); + this.rt.delete(uri); + } + } catch (Exception e) { + // ignore + System.out.println(e); + } + } + + protected TableResource createTable() throws Throwable { + URI uri = resolveUri(TABLE_API + Test1.tableId); + + TableDefinition definition = new TableDefinition(Test1.tableId, null, Test1.columns); + HttpEntity entity = entity(definition); + + ResponseEntity resp; + try { + resp = rt.exchange(uri, HttpMethod.PUT, entity, TableResource.class); + } catch ( Throwable t ) { + t.printStackTrace(); + throw t; + } + TableResource rsc = resp.getBody(); + tableDefinitionUri = rsc.getDefinitionUri(); + return rsc; + } + + protected TableResource createAltTable() throws Throwable { + URI uri = resolveUri(TABLE_API + Test1.tableId); + + TableDefinition definition = new TableDefinition(Test1.tableId, null, Test1.altcolumns); + HttpEntity entity = entity(definition); + + ResponseEntity resp; + try { + resp = rt.exchange(uri, HttpMethod.PUT, entity, TableResource.class); + } catch ( Throwable t ) { + t.printStackTrace(); + throw t; + } + TableResource rsc = resp.getBody(); + tableDefinitionUri = rsc.getDefinitionUri(); + return rsc; + } + + protected TableResourceList getTables(String cursor, String fetchLimit) throws Throwable { + URI uri = resolveUri(TABLE_API); + + UriComponentsBuilder builder = UriComponentsBuilder.fromUri(uri); + builder.queryParam("cursor", cursor); + builder.queryParam("fetchLimit", fetchLimit); + + uri = builder.build().toUri(); + + ResponseEntity resp; + try { + resp = rt.exchange(uri, + HttpMethod.GET, + null, + TableResourceList.class); + } catch ( Throwable t ) { + t.printStackTrace(); + throw t; + } + TableResourceList trl = resp.getBody(); + return trl; + } + + protected HttpEntity entity(V entity) { + return new HttpEntity(entity, reqHeaders); + } + + private class ErrorHandler implements ResponseErrorHandler { + @Override + public void handleError(ClientHttpResponse resp) throws IOException { + HttpStatus status = resp.getStatusCode(); + String body = readInput(resp.getBody()); + if (status.value() / 100 == 4) + throw new HttpClientErrorException(status, body); + else if (status.value() / 100 == 5) + throw new HttpServerErrorException(status, body); + } + + @Override + public boolean hasError(ClientHttpResponse resp) throws IOException { + return resp.getStatusCode().value() / 100 != 2; + } + + private String readInput(InputStream is) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + return sb.toString(); + } + } +} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/AuthFilterTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/AuthFilterTestIT.java index b47a05065..7f58511f7 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/AuthFilterTestIT.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/AuthFilterTestIT.java @@ -16,12 +16,6 @@ package org.opendatakit.aggregate.odktables; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -40,6 +34,12 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + @Ignore public class AuthFilterTestIT { diff --git a/src/it/java/org/opendatakit/aggregate/odktables/DataManagerTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/DataManagerTestIT.java index 7a98ff6dc..feb39ec84 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/DataManagerTestIT.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/DataManagerTestIT.java @@ -16,15 +16,6 @@ package org.opendatakit.aggregate.odktables; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -51,6 +42,15 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + public class DataManagerTestIT { private class MockCurrentUserPermissions implements TablesUserPermissions { diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/DataServiceTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/DataServiceTestIT.java similarity index 61% rename from src/it/java/org/opendatakit/aggregate/odktables/api/DataServiceTestIT.java rename to src/it/java/org/opendatakit/aggregate/odktables/DataServiceTestIT.java index 48ed18202..cfdd84c3a 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/DataServiceTestIT.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/DataServiceTestIT.java @@ -1,63 +1,70 @@ -package org.opendatakit.aggregate.odktables.api; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.opendatakit.aggregate.odktables.rest.SavepointTypeManipulator; -import org.opendatakit.aggregate.odktables.rest.entity.*; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; - -import java.net.URI; -import java.util.ArrayList; - -import static org.junit.Assert.*; - -@RunWith(org.junit.runners.JUnit4.class) -public class DataServiceTestIT extends AbstractServiceTest { - - protected URI resourceUri; - - @Before - public void setUp() throws Exception, Throwable { - super.abstractServiceSetUp(); - super.createTable(); - TableResource resource = rt.getForObject(resolveUri(TABLE_API + T.tableId), TableResource.class); - resourceUri = URI.create(resource.getDataUri()); - } - - @Test - public void testGetRowsNoRows() { - RowResourceList rows = rt.getForObject(resourceUri, RowResourceList.class); - assertTrue(rows.getRows().isEmpty()); - } - - @Test - public void testInsertRow() throws Throwable { - String rowId = T.Data.DYLAN.getId(); - String uri = Util.buildUri(resourceUri.toASCIIString()); - - Row expected = Row.forInsert(rowId, T.form_id_1, T.locale_1, SavepointTypeManipulator.complete(), - T.savepoint_timestamp_1, T.savepoint_creator_1, RowFilterScope.EMPTY_ROW_FILTER, T.Data.DYLAN.getValues()); - - RowList list = new RowList(); - ArrayList rows = new ArrayList(); - rows.add(expected); - list.setRows(rows); - - HttpEntity entity = super.entity(list); - ResponseEntity resp; - try { - resp = rt.exchange(uri, HttpMethod.PUT, entity, RowOutcomeList.class); - } catch (Throwable t) { - t.printStackTrace(); - throw t; - } - RowOutcomeList outcomes = resp.getBody(); - Row actual = outcomes.getRows().get(0); - assertEquals(expected.getRowId(), actual.getRowId()); - assertNotNull(actual.getRowETag()); - } - -} +package org.opendatakit.aggregate.odktables; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opendatakit.aggregate.odktables.rest.SavepointTypeManipulator; +import org.opendatakit.aggregate.odktables.rest.entity.Row; +import org.opendatakit.aggregate.odktables.rest.entity.RowFilterScope; +import org.opendatakit.aggregate.odktables.rest.entity.RowList; +import org.opendatakit.aggregate.odktables.rest.entity.RowOutcomeList; +import org.opendatakit.aggregate.odktables.rest.entity.RowResourceList; +import org.opendatakit.aggregate.odktables.rest.entity.TableResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; + +import java.net.URI; +import java.util.ArrayList; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(org.junit.runners.JUnit4.class) +public class DataServiceTestIT extends AbstractServiceTest { + + protected URI resourceUri; + + @Before + public void setUp() throws Exception, Throwable { + super.abstractServiceSetUp(); + super.createTable(); + TableResource resource = rt.getForObject(resolveUri(TABLE_API + Test1.tableId), TableResource.class); + resourceUri = URI.create(resource.getDataUri()); + } + + @Test + public void testGetRowsNoRows() { + RowResourceList rows = rt.getForObject(resourceUri, RowResourceList.class); + assertTrue(rows.getRows().isEmpty()); + } + + @Test + public void testInsertRow() throws Throwable { + String rowId = Test1.Data.DYLAN.getId(); + String uri = Util.buildUri(resourceUri.toASCIIString()); + + Row expected = Row.forInsert(rowId, Test1.form_id_1, Test1.locale_1, SavepointTypeManipulator.complete(), + Test1.savepoint_timestamp_1, Test1.savepoint_creator_1, RowFilterScope.EMPTY_ROW_FILTER, Test1.Data.DYLAN.getValues()); + + RowList list = new RowList(); + ArrayList rows = new ArrayList(); + rows.add(expected); + list.setRows(rows); + + HttpEntity entity = super.entity(list); + ResponseEntity resp; + try { + resp = rt.exchange(uri, HttpMethod.PUT, entity, RowOutcomeList.class); + } catch (Throwable t) { + t.printStackTrace(); + throw t; + } + RowOutcomeList outcomes = resp.getBody(); + Row actual = outcomes.getRows().get(0); + assertEquals(expected.getRowId(), actual.getRowId()); + assertNotNull(actual.getRowETag()); + } + +} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/HashTableManagerTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/HashTableManagerTestIT.java index 8eb701c53..419090d6f 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/HashTableManagerTestIT.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/HashTableManagerTestIT.java @@ -16,19 +16,19 @@ package org.opendatakit.aggregate.odktables; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.opendatakit.aggregate.odktables.TableManager.WebsafeTables; -import org.opendatakit.aggregate.odktables.api.AbstractServiceTest; +import org.opendatakit.aggregate.odktables.api.OdkTables; +import org.opendatakit.aggregate.odktables.api.RealizedTableService; +import org.opendatakit.aggregate.odktables.api.TableService; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; import org.opendatakit.aggregate.odktables.exception.TableAlreadyExistsException; +import org.opendatakit.aggregate.odktables.relation.DbTableEntry; import org.opendatakit.aggregate.odktables.relation.DbTableFileInfo; +import org.opendatakit.aggregate.odktables.relation.EntityConverter; import org.opendatakit.aggregate.odktables.rest.entity.Column; import org.opendatakit.aggregate.odktables.rest.entity.OdkTablesFileManifest; import org.opendatakit.aggregate.odktables.rest.entity.OdkTablesFileManifestEntry; @@ -38,11 +38,26 @@ import org.opendatakit.aggregate.odktables.rest.entity.TableResourceList; import org.opendatakit.aggregate.odktables.rest.entity.TableRole.TablePermission; import org.opendatakit.aggregate.odktables.security.TablesUserPermissions; +import org.opendatakit.common.ermodel.Entity; +import org.opendatakit.common.ermodel.Query; +import org.opendatakit.common.persistence.CommonFieldsBase; +import org.opendatakit.common.persistence.QueryResumePoint; import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; import org.opendatakit.common.persistence.exception.ODKTaskLockException; +import org.opendatakit.common.utils.WebUtils; import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import org.opendatakit.common.web.constants.BasicConsts; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.core.UriBuilder; +import java.net.MalformedURLException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -137,7 +152,6 @@ public void tearDown() throws Exception { cleanAppLevelFiles(); } - @Test public void testGetTablesEmpty() throws ODKDatastoreException { WebsafeTables result = tm.getTables(null, 2000); @@ -150,7 +164,7 @@ public void testGetTablesWithNoFiles() throws Throwable { verifyFileManifestsAreUsingEmptyMD5(); - TableResourceList trl = getTables(); + TableResourceList trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); List tables = trl.getTables(); @@ -159,7 +173,6 @@ public void testGetTablesWithNoFiles() throws Throwable { } } - @Test public void testAddSingleTableLevelFiles() throws Throwable { // first establish blank table @@ -181,7 +194,7 @@ public void testAddSingleTableLevelFiles() throws Throwable { // verify etags match String table1ManifestETag = FileManifestUtils.getTableLevelManifestETag(tableId, T.appId, cc); - TableResourceList trl = getTables(); + TableResourceList trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); List tables = trl.getTables(); @@ -192,7 +205,6 @@ public void testAddSingleTableLevelFiles() throws Throwable { } - @Test public void testAddNRemoveSingleTableLevelFiles() throws Throwable { // first establish blank table @@ -213,7 +225,7 @@ public void testAddNRemoveSingleTableLevelFiles() throws Throwable { // verify etags match String table1ManifestETag = FileManifestUtils.getTableLevelManifestETag(tableId, T.appId, cc); - TableResourceList trl = getTables(); + TableResourceList trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); List tables = trl.getTables(); @@ -228,7 +240,7 @@ public void testAddNRemoveSingleTableLevelFiles() throws Throwable { table1ManifestETag = FileManifestUtils.getTableLevelManifestETag(tableId, T.appId, cc); assertEquals(EMPTY_MD5_HASH, table1ManifestETag); - trl = getTables(); + trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); tables = trl.getTables(); @@ -264,7 +276,7 @@ public void testAddSameSingleTableLevelFileToBothTables() throws Throwable { String table2ManifestETag = FileManifestUtils.getTableLevelManifestETag(tableId2, T.appId, cc); assertEquals(table1ManifestETag, table2ManifestETag); - TableResourceList trl = getTables(); + TableResourceList trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); List tables = trl.getTables(); @@ -295,7 +307,7 @@ public void testAddTwoTableLevelFiles() throws Throwable { // verify etags match String firstFileManifestEtag = FileManifestUtils.getTableLevelManifestETag(tableId, T.appId, cc); - TableResourceList trl = getTables(); + TableResourceList trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); List tables = trl.getTables(); @@ -314,7 +326,7 @@ public void testAddTwoTableLevelFiles() throws Throwable { String bothFilesManifestETag = FileManifestUtils.getTableLevelManifestETag(tableId, T.appId, cc); assertNotEquals(firstFileManifestEtag, bothFilesManifestETag); - trl = getTables(); + trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); for (TableResource tr : trl.getTables()) { @@ -344,7 +356,7 @@ public void testAddTwoTableLevelFilesRemoveOne() throws Throwable { // verify etags match String firstFileManifestEtag = FileManifestUtils.getTableLevelManifestETag(tableId, T.appId, cc); - TableResourceList trl = getTables(); + TableResourceList trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); List tables = trl.getTables(); @@ -363,7 +375,7 @@ public void testAddTwoTableLevelFilesRemoveOne() throws Throwable { String bothFilesManifestETag = FileManifestUtils.getTableLevelManifestETag(tableId, T.appId, cc); assertNotEquals(firstFileManifestEtag, bothFilesManifestETag); - trl = getTables(); + trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); for (TableResource tr : trl.getTables()) { @@ -378,7 +390,7 @@ public void testAddTwoTableLevelFilesRemoveOne() throws Throwable { assertNotEquals(EMPTY_MD5_HASH, oneRemovedManifestETag); assertEquals(firstFileManifestEtag, oneRemovedManifestETag); - trl = getTables(); + trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); tables = trl.getTables(); @@ -417,7 +429,7 @@ public void testAddDifferentSingleTableLevelFileToBothTables() throws Throwable String table2ManifestETag = FileManifestUtils.getTableLevelManifestETag(tableId2, T.appId, cc); assertNotEquals(table1ManifestETag, table2ManifestETag); - TableResourceList trl = getTables(); + TableResourceList trl = getTables("", "2000"); assertEquals(EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); List tables = trl.getTables(); @@ -430,11 +442,75 @@ public void testAddDifferentSingleTableLevelFileToBothTables() throws Throwable @Test public void testAddSingleAppLevelFiles() throws Throwable { + TableResourceList trl = getTables("", "2000"); + assertEquals("TableResourceList should equal empty APP files", EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); + List tables = trl.getTables(); + assertEquals("Should have no tables", 0, tables.size()); + // first establish blank table createTable1Only(); + // check number of tables in table manager + TableManager tm = new TableManager(T.appId, userPermissions, cc); + TableManager.WebsafeTables wsTables = tm.getTables(null, 2000); + List teList = wsTables.tables; + assertEquals("TM Should have one table", 1, teList.size()); + + WebsafeTables websafeResult = tm.getTables( + QueryResumePoint.fromWebsafeCursor(WebUtils.safeDecode("")), 2000); + teList = websafeResult.tables; + assertEquals("TM Should have one table", 1, teList.size()); + assertEquals("Resources Should have one table", 1, teList.size()); + + websafeResult = tm.getTables( + QueryResumePoint.fromWebsafeCursor(WebUtils.safeDecode(null)), 2000); + teList = websafeResult.tables; + assertEquals("TM Should have one table", 1, teList.size()); + + List filteredList = new ArrayList(); + Query query = DbTableEntry.getRelation(cc).query("HasTableManagerTestIT.testAddSingleAppLevelFiles", cc); + query.addSort(DbTableEntry.getRelation(cc).getDataField(CommonFieldsBase.CREATION_DATE_COLUMN_NAME), + org.opendatakit.common.persistence.Query.Direction.ASCENDING); + // we need the filter to activate the sort... + query.addFilter(DbTableEntry.getRelation(cc).getDataField(CommonFieldsBase.CREATION_DATE_COLUMN_NAME), + org.opendatakit.common.persistence.Query.FilterOperation.GREATER_THAN, BasicConsts.EPOCH); + Query.WebsafeQueryResult result = query.execute(null, 2000); + List results = new ArrayList(); + for (Entity e : result.entities) { + results.add(new DbTableEntry.DbTableEntryEntity(e)); + } + EntityConverter converter = new EntityConverter(); + List tablesEntriesQuery = converter.toTableEntries(results); + for (TableEntry e : tablesEntriesQuery) { + if (userPermissions.hasPermission(T.appId, e.getTableId(), TablePermission.READ_TABLE_ENTRY)) { + filteredList.add(e); + } + } + assertEquals("TableEntries before permission check", 1, tablesEntriesQuery.size()); + assertEquals("PermissionFiltered Should have one table after query", 1, filteredList.size()); + + trl = getTables("", "2000"); + assertEquals("TableResourceList should equal empty APP files", EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); + tables = trl.getTables(); + assertEquals("Should have one table", 1, tables.size()); + for (TableResource tr : tables) { + String eTagValue = FileManifestUtils.getTableLevelManifestETag(tr.getTableId(), T.appId, ODK_CLIENT_VERSION, cc); + + FileManifestManager manifestManager = new FileManifestManager(T.appId, ODK_CLIENT_VERSION, cc); + OdkTablesFileManifest manifest = manifestManager.getManifestForTable(tr.getTableId()); + + String calculatedETagFromManifest = FileManifestUtils.calculateUpdatedETagFromManifest(manifest); + + Thread.sleep(100); + assertEquals("ETag calculated from Manifest should equal from util", eTagValue, calculatedETagFromManifest); + assertEquals("eTagValue from util should equals getTables Etag", eTagValue, tr.getTableLevelManifestETag()); + assertEquals(EMPTY_MD5_HASH, tr.getTableLevelManifestETag()); + } + + // verify no files yet verifyFileManifestsAreUsingEmptyMD5(); + // uses String appManifestETag = FileManifestUtils.getAppLevelManifestETag(T.appId, cc); // add a file byte[] fileContent = TEST_FILE_1.getBytes(StandardCharsets.UTF_8); @@ -445,13 +521,16 @@ public void testAddSingleAppLevelFiles() throws Throwable { ConfigFileChangeDetail outcome = fm.putFile(ODK_CLIENT_VERSION, DbTableFileInfo.NO_TABLE_ID, fi, userPermissions); assertEquals(ConfigFileChangeDetail.FILE_NEWLY_CREATED, outcome); - // verify etags match String appManifestETag = FileManifestUtils.getAppLevelManifestETag(T.appId, cc); + assertNotEquals("appManifest should not equals to empty", EMPTY_MD5_HASH, appManifestETag); - TableResourceList trl = getTables(); + trl = getTables(null, "2000"); + assertNotEquals("TableResourceList should not equals to empty", EMPTY_MD5_HASH, trl.getAppLevelManifestETag()); + + // verify etags match assertEquals(appManifestETag, trl.getAppLevelManifestETag()); - List tables = trl.getTables(); + tables = trl.getTables(); for (TableResource tr : tables) { assertEquals(EMPTY_MD5_HASH, tr.getTableLevelManifestETag()); } @@ -459,6 +538,7 @@ public void testAddSingleAppLevelFiles() throws Throwable { @Test public void testAddDifferentSingleTableLevelFileToBothTablesNAddAppLevel() throws Throwable { + // first establish blank tables createBothTable1N2(); @@ -493,7 +573,7 @@ public void testAddDifferentSingleTableLevelFileToBothTablesNAddAppLevel() throw assertNotEquals(table1ManifestETag, table2ManifestETag); assertEquals(appManifestETag, table1ManifestETag); - TableResourceList trl = getTables(); + TableResourceList trl = getTables("", "2000"); assertEquals(appManifestETag, trl.getAppLevelManifestETag()); List tables = trl.getTables(); @@ -557,4 +637,5 @@ private void cleanAppLevelFiles() throws ODKDatastoreException, ODKTaskLockExcep fm.deleteFile(ODK_CLIENT_VERSION, DbTableFileInfo.NO_TABLE_ID, entry.filename); } } + } diff --git a/src/it/java/org/opendatakit/aggregate/odktables/T.java b/src/it/java/org/opendatakit/aggregate/odktables/T.java index e7aec6bed..74cc562e8 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/T.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/T.java @@ -16,10 +16,6 @@ package org.opendatakit.aggregate.odktables; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Ignore; import org.opendatakit.aggregate.odktables.rest.SavepointTypeManipulator; import org.opendatakit.aggregate.odktables.rest.TableConstants; import org.opendatakit.aggregate.odktables.rest.entity.Column; @@ -27,7 +23,9 @@ import org.opendatakit.aggregate.odktables.rest.entity.Row; import org.opendatakit.aggregate.odktables.rest.entity.RowFilterScope; -@Ignore +import java.util.ArrayList; +import java.util.List; + public class T { public static class Columns { diff --git a/src/it/java/org/opendatakit/aggregate/odktables/TableAclManagerTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/TableAclManagerTestIT.java index 2df65daeb..72e2d3d61 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/TableAclManagerTestIT.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/TableAclManagerTestIT.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -36,6 +33,9 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + public class TableAclManagerTestIT { private CallingContext cc; diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/TableAclServiceTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/TableAclServiceTestIT.java similarity index 81% rename from src/it/java/org/opendatakit/aggregate/odktables/api/TableAclServiceTestIT.java rename to src/it/java/org/opendatakit/aggregate/odktables/TableAclServiceTestIT.java index 41a2b9510..6c508d04e 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/TableAclServiceTestIT.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/TableAclServiceTestIT.java @@ -1,78 +1,83 @@ -package org.opendatakit.aggregate.odktables.api; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.opendatakit.aggregate.odktables.rest.entity.*; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; - -import java.net.URI; - -import static org.junit.Assert.assertEquals; - -@RunWith(org.junit.runners.JUnit4.class) -public class TableAclServiceTestIT extends AbstractServiceTest { - - protected URI resourceUri; - - @Before - public void setUp() throws Exception, Throwable { - super.abstractServiceSetUp(); - super.createTable(); - TableResource resource = rt.getForObject(resolveUri(TABLE_API + T.tableId), TableResource.class); - resourceUri = URI.create(resource.getAclUri()); - } - - @Test - public void testGetAclsOnlyOwner() { - TableAclResourceList acls = rt.getForObject(resourceUri, TableAclResourceList.class); - assertEquals(1, acls.getAcls().size()); - } - - @Test - public void testSetUserAcl() { - Scope.Type type = Scope.Type.USER; - String userId = "someone@somewhere.com"; - String uri = Util.buildUri(resourceUri.toASCIIString(), type.name().toLowerCase(), userId); - TableAcl expected = new TableAcl(TableRole.READER); - - HttpEntity entity = super.entity(expected); - ResponseEntity resp = rt.exchange(uri, HttpMethod.PUT, entity, - TableAclResource.class); - TableAclResource actual = resp.getBody(); - assertEquals(expected.getRole(), actual.getRole()); - assertEquals(new Scope(type, userId), actual.getScope()); - } - - @Test - public void testSetDefaultAcl() { - Scope.Type type = Scope.Type.DEFAULT; - String uri = Util.buildUri(resourceUri.toASCIIString(), type.name().toLowerCase()); - TableAcl expected = new TableAcl(TableRole.READER); - - HttpEntity entity = super.entity(expected); - ResponseEntity resp = rt.exchange(uri, HttpMethod.PUT, entity, - TableAclResource.class); - TableAclResource actual = resp.getBody(); - assertEquals(expected.getRole(), actual.getRole()); - assertEquals(new Scope(Scope.Type.DEFAULT, null), actual.getScope()); - } - - @Test - public void testDeleteDefaultAcl() { - Scope.Type type = Scope.Type.DEFAULT; - String uri = Util.buildUri(resourceUri.toASCIIString(), type.name().toLowerCase()); - rt.delete(uri); - } - - @Test - public void testDeleteNonExistentAcl() { - Scope.Type type = Scope.Type.USER; - String userId = "someone@somewhere.com"; - String uri = Util.buildUri(resourceUri.toASCIIString(), type.name().toLowerCase(), userId); - rt.delete(uri); - } - -} +package org.opendatakit.aggregate.odktables; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opendatakit.aggregate.odktables.rest.entity.Scope; +import org.opendatakit.aggregate.odktables.rest.entity.TableAcl; +import org.opendatakit.aggregate.odktables.rest.entity.TableAclResource; +import org.opendatakit.aggregate.odktables.rest.entity.TableAclResourceList; +import org.opendatakit.aggregate.odktables.rest.entity.TableResource; +import org.opendatakit.aggregate.odktables.rest.entity.TableRole; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; + +import java.net.URI; + +import static org.junit.Assert.assertEquals; + +@RunWith(org.junit.runners.JUnit4.class) +public class TableAclServiceTestIT extends AbstractServiceTest { + + protected URI resourceUri; + + @Before + public void setUp() throws Exception, Throwable { + super.abstractServiceSetUp(); + super.createTable(); + TableResource resource = rt.getForObject(resolveUri(TABLE_API + Test1.tableId), TableResource.class); + resourceUri = URI.create(resource.getAclUri()); + } + + @Test + public void testGetAclsOnlyOwner() { + TableAclResourceList acls = rt.getForObject(resourceUri, TableAclResourceList.class); + assertEquals(1, acls.getAcls().size()); + } + + @Test + public void testSetUserAcl() { + Scope.Type type = Scope.Type.USER; + String userId = "someone@somewhere.com"; + String uri = Util.buildUri(resourceUri.toASCIIString(), type.name().toLowerCase(), userId); + TableAcl expected = new TableAcl(TableRole.READER); + + HttpEntity entity = super.entity(expected); + ResponseEntity resp = rt.exchange(uri, HttpMethod.PUT, entity, + TableAclResource.class); + TableAclResource actual = resp.getBody(); + assertEquals(expected.getRole(), actual.getRole()); + assertEquals(new Scope(type, userId), actual.getScope()); + } + + @Test + public void testSetDefaultAcl() { + Scope.Type type = Scope.Type.DEFAULT; + String uri = Util.buildUri(resourceUri.toASCIIString(), type.name().toLowerCase()); + TableAcl expected = new TableAcl(TableRole.READER); + + HttpEntity entity = super.entity(expected); + ResponseEntity resp = rt.exchange(uri, HttpMethod.PUT, entity, + TableAclResource.class); + TableAclResource actual = resp.getBody(); + assertEquals(expected.getRole(), actual.getRole()); + assertEquals(new Scope(Scope.Type.DEFAULT, null), actual.getScope()); + } + + @Test + public void testDeleteDefaultAcl() { + Scope.Type type = Scope.Type.DEFAULT; + String uri = Util.buildUri(resourceUri.toASCIIString(), type.name().toLowerCase()); + rt.delete(uri); + } + + @Test + public void testDeleteNonExistentAcl() { + Scope.Type type = Scope.Type.USER; + String userId = "someone@somewhere.com"; + String uri = Util.buildUri(resourceUri.toASCIIString(), type.name().toLowerCase(), userId); + rt.delete(uri); + } + +} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/TableManagerTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/TableManagerTestIT.java index b59f7a3d9..9bb7d561b 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/TableManagerTestIT.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/TableManagerTestIT.java @@ -16,13 +16,6 @@ package org.opendatakit.aggregate.odktables; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -44,6 +37,13 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + // TODO: tests here have been updated and if they fail are likely due to config // errors as much as real errors. public class TableManagerTestIT { diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/TableServiceTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/TableServiceTestIT.java similarity index 90% rename from src/it/java/org/opendatakit/aggregate/odktables/api/TableServiceTestIT.java rename to src/it/java/org/opendatakit/aggregate/odktables/TableServiceTestIT.java index 40c4fcbc9..bb8852e5c 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/TableServiceTestIT.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/TableServiceTestIT.java @@ -1,63 +1,64 @@ -package org.opendatakit.aggregate.odktables.api; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.opendatakit.aggregate.odktables.rest.entity.TableResource; -import org.opendatakit.aggregate.odktables.rest.entity.TableResourceList; -import org.springframework.web.client.HttpClientErrorException; - -import java.net.URI; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -@RunWith(org.junit.runners.JUnit4.class) -public class TableServiceTestIT extends AbstractServiceTest { - - protected URI resourceUri; - - @Before - public void setup() throws Exception, Throwable { - super.abstractServiceSetUp(); - } - - @Test - public void testGetTablesEmpty() { - TableResourceList tables = rt.getForObject(resolveUri(TABLE_API), TableResourceList.class); - assertTrue(tables.getTables().isEmpty()); - } - - @Test(expected = HttpClientErrorException.class) - public void testGetTableDoesNotExist() { - URI uri = resolveUri(TABLE_API + "non-existent-table"); - rt.getForObject(uri, TableResource.class); - } - - @Test - public void testCreateTable() throws Throwable { - TableResource resource = createTable(); - assertEquals(T.tableId, resource.getTableId()); - } - - @Test - public void testCreateTableTwice() throws Throwable { - createTable(); - createTable(); - } - - @Test(expected = HttpClientErrorException.class) - public void testCreateTableAlreadyExists() throws Throwable { - createTable(); - createAltTable(); - } - - @Test - public void testGetTable() throws Throwable { - TableResource expected = createTable(); - String uri = expected.getSelfUri(); - TableResource actual = rt.getForObject(uri, TableResource.class); - assertEquals(expected, actual); - } - -} +package org.opendatakit.aggregate.odktables; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opendatakit.aggregate.odktables.rest.entity.TableResource; +import org.opendatakit.aggregate.odktables.rest.entity.TableResourceList; +import org.springframework.web.client.HttpClientErrorException; + +import java.net.URI; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +@RunWith(org.junit.runners.JUnit4.class) +public class TableServiceTestIT extends AbstractServiceTest { + + protected URI resourceUri; + + @Before + public void setup() throws Exception, Throwable { + super.abstractServiceSetUp(); + } + + @Test + public void testGetTablesEmpty() { + TableResourceList tables = rt.getForObject(resolveUri(TABLE_API), TableResourceList.class); + assertTrue(tables.getTables().isEmpty()); + } + + @Test(expected = HttpClientErrorException.class) + public void testGetTableDoesNotExist() { + URI uri = resolveUri(TABLE_API + "non-existent-table"); + rt.getForObject(uri, TableResource.class); + } + + @Test + public void testCreateTable() throws Throwable { + TableResource resource = createTable(); + assertEquals(Test1.tableId, resource.getTableId()); + } + + @Test + public void testCreateTableTwice() throws Throwable { + createTable(); + createTable(); + } + + @Test(expected = HttpClientErrorException.class) + public void testCreateTableAlreadyExists() throws Throwable { + createTable(); + createAltTable(); + } + + @Test + public void testGetTable() throws Throwable { + TableResource expected = createTable(); + String uri = expected.getSelfUri(); + TableResource actual = rt.getForObject(uri, TableResource.class); + assertEquals(expected, actual); + } + +} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/T.java b/src/it/java/org/opendatakit/aggregate/odktables/Test1.java similarity index 78% rename from src/it/java/org/opendatakit/aggregate/odktables/api/T.java rename to src/it/java/org/opendatakit/aggregate/odktables/Test1.java index 0055ebedc..d055898f8 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/T.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/Test1.java @@ -1,112 +1,110 @@ -package org.opendatakit.aggregate.odktables.api; - -import org.junit.Ignore; -import org.opendatakit.aggregate.odktables.rest.SavepointTypeManipulator; -import org.opendatakit.aggregate.odktables.rest.TableConstants; -import org.opendatakit.aggregate.odktables.rest.entity.Column; -import org.opendatakit.aggregate.odktables.rest.entity.DataKeyValue; -import org.opendatakit.aggregate.odktables.rest.entity.Row; -import org.opendatakit.aggregate.odktables.rest.entity.RowFilterScope; - -import java.util.ArrayList; -import java.util.List; - -@Ignore -public class T { - - public static final String tableId = "people"; - public static final String displayName = "\"people\""; - - public static final String savepoint_creator_1 = null; - public static final String form_id_1 = null; - public static final String locale_1 = "default"; - public static final String savepoint_timestamp_1 = TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()-1000); - - public static final String savepoint_creator_2 = "fred"; - public static final String form_id_2 = "ralph"; - public static final String locale_2 = "default"; - public static final String savepoint_timestamp_2 = TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()-2000); - - @SuppressWarnings("serial") - public static final ArrayList columns = new ArrayList() { - { - add(T.Columns.column_name); - add(T.Columns.column_age); - add(T.Columns.column_weight); - } - }; - - @SuppressWarnings("serial") - public static final ArrayList altcolumns = new ArrayList() { - { - add(T.Columns.column_name); - add(T.Columns.column_age); - } - }; - - @SuppressWarnings("serial") - public static final List rows = new ArrayList() { - { - add(Row.forInsert(T.Data.DYLAN.getId(), T.form_id_1, T.locale_1, SavepointTypeManipulator.complete(), - T.savepoint_timestamp_1, T.savepoint_creator_1, RowFilterScope.EMPTY_ROW_FILTER, T.Data.DYLAN.getValues())); - add(Row.forInsert(T.Data.JOHN.getId(), T.form_id_2, T.locale_2, SavepointTypeManipulator.complete(), - T.savepoint_timestamp_2, T.savepoint_creator_2, RowFilterScope.EMPTY_ROW_FILTER, T.Data.JOHN.getValues())); - } - }; - - public static class Columns { - - public static final String tableId = "my_table_id"; - public static final String name = "name"; - public static final String age = "age"; - public static final String weight = "weight"; - public static final Column column_name = new Column(name, name, "string", null); - public static final Column column_age = new Column(age, age, "integer", null); - public static final Column column_weight = new Column(weight, weight, "integer", null); - } - public static enum Data { - DYLAN("1", "dylan", "23", "175"), - JOHN("2", "john", "58", "200"); - private final String id; - private final String name; - private final String age; - private final String weight; - - public ArrayList getValues() { - final ArrayList alist = new ArrayList(); - // in order... - alist.add(new DataKeyValue(Columns.age, age)); - alist.add(new DataKeyValue(Columns.name, name)); - alist.add(new DataKeyValue(Columns.weight, weight)); - return alist; - } - - @SuppressWarnings("all") - private Data(final String id, final String name, final String age, final String weight) { - this.id = id; - this.name = name; - this.age = age; - this.weight = weight; - } - - @SuppressWarnings("all") - public String getId() { - return this.id; - } - - @SuppressWarnings("all") - public String getName() { - return this.name; - } - - @SuppressWarnings("all") - public String getAge() { - return this.age; - } - - @SuppressWarnings("all") - public String getWeight() { - return this.weight; - } - } +package org.opendatakit.aggregate.odktables; + +import org.opendatakit.aggregate.odktables.rest.SavepointTypeManipulator; +import org.opendatakit.aggregate.odktables.rest.TableConstants; +import org.opendatakit.aggregate.odktables.rest.entity.Column; +import org.opendatakit.aggregate.odktables.rest.entity.DataKeyValue; +import org.opendatakit.aggregate.odktables.rest.entity.Row; +import org.opendatakit.aggregate.odktables.rest.entity.RowFilterScope; + +import java.util.ArrayList; +import java.util.List; + +public class Test1 { + + public static final String tableId = "people"; + public static final String displayName = "\"people\""; + + public static final String savepoint_creator_1 = null; + public static final String form_id_1 = null; + public static final String locale_1 = "default"; + public static final String savepoint_timestamp_1 = TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()-1000); + + public static final String savepoint_creator_2 = "fred"; + public static final String form_id_2 = "ralph"; + public static final String locale_2 = "default"; + public static final String savepoint_timestamp_2 = TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()-2000); + + @SuppressWarnings("serial") + public static final ArrayList columns = new ArrayList() { + { + add(Test1.Columns.column_name); + add(Test1.Columns.column_age); + add(Test1.Columns.column_weight); + } + }; + + @SuppressWarnings("serial") + public static final ArrayList altcolumns = new ArrayList() { + { + add(Test1.Columns.column_name); + add(Test1.Columns.column_age); + } + }; + + @SuppressWarnings("serial") + public static final List rows = new ArrayList() { + { + add(Row.forInsert(Test1.Data.DYLAN.getId(), Test1.form_id_1, Test1.locale_1, SavepointTypeManipulator.complete(), + Test1.savepoint_timestamp_1, Test1.savepoint_creator_1, RowFilterScope.EMPTY_ROW_FILTER, Test1.Data.DYLAN.getValues())); + add(Row.forInsert(Test1.Data.JOHN.getId(), Test1.form_id_2, Test1.locale_2, SavepointTypeManipulator.complete(), + Test1.savepoint_timestamp_2, Test1.savepoint_creator_2, RowFilterScope.EMPTY_ROW_FILTER, Test1.Data.JOHN.getValues())); + } + }; + + public static class Columns { + + public static final String tableId = "my_table_id"; + public static final String name = "name"; + public static final String age = "age"; + public static final String weight = "weight"; + public static final Column column_name = new Column(name, name, "string", null); + public static final Column column_age = new Column(age, age, "integer", null); + public static final Column column_weight = new Column(weight, weight, "integer", null); + } + public static enum Data { + DYLAN("1", "dylan", "23", "175"), + JOHN("2", "john", "58", "200"); + private final String id; + private final String name; + private final String age; + private final String weight; + + public ArrayList getValues() { + final ArrayList alist = new ArrayList(); + // in order... + alist.add(new DataKeyValue(Columns.age, age)); + alist.add(new DataKeyValue(Columns.name, name)); + alist.add(new DataKeyValue(Columns.weight, weight)); + return alist; + } + + @SuppressWarnings("all") + private Data(final String id, final String name, final String age, final String weight) { + this.id = id; + this.name = name; + this.age = age; + this.weight = weight; + } + + @SuppressWarnings("all") + public String getId() { + return this.id; + } + + @SuppressWarnings("all") + public String getName() { + return this.name; + } + + @SuppressWarnings("all") + public String getAge() { + return this.age; + } + + @SuppressWarnings("all") + public String getWeight() { + return this.weight; + } + } } \ No newline at end of file diff --git a/src/it/java/org/opendatakit/aggregate/odktables/UserTestIT.java b/src/it/java/org/opendatakit/aggregate/odktables/UserTestIT.java new file mode 100644 index 000000000..37ec5c777 --- /dev/null +++ b/src/it/java/org/opendatakit/aggregate/odktables/UserTestIT.java @@ -0,0 +1,45 @@ +package org.opendatakit.aggregate.odktables; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opendatakit.aggregate.odktables.rest.entity.UserInfoList; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; + +import java.net.URI; + +import static org.junit.Assert.assertEquals; + +@RunWith(org.junit.runners.JUnit4.class) +public class UserTestIT extends AbstractServiceTest { + + @Before + public void setUp() throws Throwable { + super.abstractServiceSetUp(); + } + + @Test + public void testAdminCanGetListOfUsers() throws Throwable { + /* this test assumes the integrated testing system has + prepopulated LDAP with 4 users + anonymous resulting in 5 users*/ + + URI uri = resolveUri("usersInfo"); + + assertEquals("URI: " + uri.toURL(), "http://localhost:8888/odktables/default/usersInfo", uri.toURL().toString()); + + ResponseEntity resp; + try { + resp = rt.exchange(uri, + HttpMethod.GET, + null, + UserInfoList.class); + } catch ( Throwable t ) { + t.printStackTrace(); + throw t; + } + UserInfoList users = resp.getBody(); + assertEquals(5, users.size()); + } + +} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/Util.java b/src/it/java/org/opendatakit/aggregate/odktables/Util.java index 30cce2454..969b902a1 100644 --- a/src/it/java/org/opendatakit/aggregate/odktables/Util.java +++ b/src/it/java/org/opendatakit/aggregate/odktables/Util.java @@ -16,13 +16,14 @@ package org.opendatakit.aggregate.odktables; -import static org.junit.Assert.assertTrue; +import org.apache.commons.lang3.StringUtils; import java.net.URI; import java.util.ArrayList; import java.util.Collection; +import java.util.List; -import org.apache.commons.lang3.StringUtils; +import static org.junit.Assert.assertTrue; public class Util { @@ -44,4 +45,13 @@ public static void assertCollectionSameElements(Collection expected, Coll } assertTrue(expectedCopy.isEmpty()); } + + + public static List list(V... values) { + ArrayList list = new ArrayList(); + for (V value : values) { + list.add(value); + } + return list; + } } diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/ColumnDefinition.java b/src/it/java/org/opendatakit/aggregate/odktables/api/ColumnDefinition.java deleted file mode 100644 index 5d2176b62..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/ColumnDefinition.java +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.opendatakit.aggregate.odktables.rest.ElementDataType; -import org.opendatakit.aggregate.odktables.rest.ElementType; -import org.opendatakit.aggregate.odktables.rest.entity.Column; - -import java.io.IOException; -import java.util.*; - -public class ColumnDefinition implements Comparable { - private static final Log logger = LogFactory.getLog(ColumnDefinition.class); - - public static final ObjectMapper mapper = new ObjectMapper(); - - private static final String TAG = "ColumnDefinition"; - private static final String JSON_SCHEMA_ELEMENT_KEY = "elementKey"; - private static final String JSON_SCHEMA_ELEMENT_TYPE = "elementType"; - private static final String JSON_SCHEMA_PROPERTIES = "properties"; - private static final String JSON_SCHEMA_ITEMS = "items"; - private static final String JSON_SCHEMA_TYPE = "type"; - - private final Column column; - - // public final String elementKey; - // public final String elementName; - // public final String elementType; - private boolean isUnitOfRetention = true; // assumed until revised... - - final ArrayList children = new ArrayList(); - ElementType type = null; - ColumnDefinition parent = null; - - public ColumnDefinition(String elementKey, String elementName, String elementType, - String listChildElementKeys) { - this.column = new Column(elementKey, elementName, elementType, listChildElementKeys); - } - - public String getElementKey() { - return column.getElementKey(); - } - - public String getElementName() { - return column.getElementName(); - } - - public String getElementType() { - return column.getElementType(); - } - - public synchronized ElementType getType() { - if ( type == null ) { - type = ElementType.parseElementType(getElementType(), !getChildren().isEmpty()); - } - return type; - } - - public String getListChildElementKeys() { - return column.getListChildElementKeys(); - } - - private void setParent(ColumnDefinition parent) { - this.parent = parent; - } - - public ColumnDefinition getParent() { - return this.parent; - } - - public void addChild(ColumnDefinition child) { - child.setParent(this); - children.add(child); - } - - public List getChildren() { - return Collections.unmodifiableList(this.children); - } - - public boolean isUnitOfRetention() { - return isUnitOfRetention; - } - - void setNotUnitOfRetention() { - isUnitOfRetention = false; - } - - public String toString() { - return column.toString(); - } - - public int hashCode() { - return column.hashCode(); - } - - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ColumnDefinition)) { - return false; - } - ColumnDefinition o = (ColumnDefinition) obj; - - return column.equals(o.column); - } - - /** - * Binary search using elementKey. The ColumnDefinition list returned by - * ColumnDefinition.buildColumnDefinitions() is ordered. This function makes - * use of that property to quickly retrieve the definition for an elementKey. - * - * @param orderedDefns - * @param elementKey - * @return - * @throws IllegalArgumentException - if elementKey not found - */ - public static ColumnDefinition find(ArrayList orderedDefns, String elementKey) - throws IllegalArgumentException { - if (elementKey == null) { - throw new NullPointerException("elementKey cannot be null in ColumnDefinition::find()"); - } - int iLow = 0; - int iHigh = orderedDefns.size(); - int iGuess = (iLow + iHigh) / 2; - while (iLow != iHigh) { - ColumnDefinition cd = orderedDefns.get(iGuess); - int cmp = elementKey.compareTo(cd.getElementKey()); - if (cmp == 0) { - return cd; - } - if (cmp < 0) { - iHigh = iGuess; - } else { - iLow = iGuess + 1; - } - iGuess = (iLow + iHigh) / 2; - } - - if (iLow >= orderedDefns.size()) { - throw new IllegalArgumentException("could not find elementKey in columns list: " + elementKey); - } - - ColumnDefinition cd = orderedDefns.get(iGuess); - if (cd.getElementKey().equals(elementKey)) { - return cd; - } - throw new IllegalArgumentException("could not find elementKey in columns list: " + elementKey); - } - - /** - * Helper class for building ColumnDefinition objects from Column objects. - * - * @author mitchellsundt@gmail.com - */ - private static class ColumnContainer { - public ColumnDefinition defn = null; - public ArrayList children = null; - }; - - /** - * Construct the rich ColumnDefinition objects for a table from the underlying - * information in the list of Column objects. - * - * @param appName - * @param tableId - * @param columns - * @return - */ - @SuppressWarnings("unchecked") - public static final ArrayList buildColumnDefinitions(String appName, String tableId, List columns) { - - logger.debug("[buildColumnDefinitions] tableId: " + tableId + " size: " + columns.size() + " first column: " + - (columns.isEmpty() ? "" : columns.get(0).getElementKey())); - - Map colDefs = new HashMap(); - List ccList = new ArrayList(); - for (Column col : columns) { - ColumnDefinition cd = new ColumnDefinition(col.getElementKey(), col.getElementName(), - col.getElementType(), col.getListChildElementKeys()); - ColumnContainer cc = new ColumnContainer(); - cc.defn = cd; - String children = col.getListChildElementKeys(); - if (children != null && children.length() != 0) { - ArrayList chi; - try { - chi = mapper.readValue(children, ArrayList.class); - } catch (JsonParseException e) { - e.printStackTrace(); - throw new IllegalArgumentException("Invalid list of children: " + children); - } catch (JsonMappingException e) { - e.printStackTrace(); - throw new IllegalArgumentException("Invalid list of children: " + children); - } catch (IOException e) { - e.printStackTrace(); - throw new IllegalArgumentException("Invalid list of children: " + children); - } - cc.children = chi; - ccList.add(cc); - } - colDefs.put(cd.getElementKey(), cd); - } - for (ColumnContainer cc : ccList) { - ColumnDefinition cparent = cc.defn; - for (String childKey : cc.children) { - ColumnDefinition cchild = colDefs.get(childKey); - if (cchild == null) { - throw new IllegalArgumentException("Child elementkey " + childKey - + " was never defined but referenced in " + cparent.getElementKey() + "!"); - } - // set up bi-directional linkage of child and parent. - cparent.addChild(cchild); - } - } - - // Sanity check: - // (1) all children elementKeys must have been defined in the Columns list. - // (2) arrays must have only one child. - // (3) children must belong to at most one parent - for (ColumnContainer cc : ccList) { - ColumnDefinition defn = cc.defn; - - if (defn.getChildren().size() != cc.children.size()) { - throw new IllegalArgumentException("Not all children of element have been defined! " - + defn.getElementKey()); - } - - ElementType type = defn.getType(); - - if (type.getDataType() == ElementDataType.array) { - if (defn.getChildren().isEmpty()) { - throw new IllegalArgumentException("Column is an array but does not list its children"); - } - if (defn.getChildren().size() != 1) { - throw new IllegalArgumentException("Column is an array but has more than one item entry"); - } - } - - for (ColumnDefinition child : defn.getChildren()) { - if (child.getParent() != defn) { - throw new IllegalArgumentException("Column is enclosed by two or more groupings: " - + defn.getElementKey()); - } - if (!child.getElementKey().equals(defn.getElementKey() + "_" + child.getElementName())) { - throw new IllegalArgumentException( - "Children are expected to have elementKey equal to parent's elementKey-underscore-childElementName"); - } - } - } - markUnitOfRetention(colDefs); - ArrayList defns = new ArrayList(colDefs.values()); - Collections.sort(defns); - - return defns; - } - - /** - * This must match the code in the javascript layer - * - * See databaseUtils.markUnitOfRetention - * - * Sweeps through the collection of ColumnDefinition objects and marks the - * ones that exist in the actual database table. - * - * @param defn - */ - private static void markUnitOfRetention(Map defn) { - // for all arrays, mark all descendants of the array as not-retained - // because they are all folded up into the json representation of the array - for (String startKey : defn.keySet()) { - ColumnDefinition colDefn = defn.get(startKey); - if (!colDefn.isUnitOfRetention()) { - // this has already been processed - continue; - } - if (ElementDataType.array.name().equals(colDefn.getElementType())) { - ArrayList descendantsOfArray = new ArrayList( - colDefn.getChildren()); - ArrayList scratchArray = new ArrayList(); - while (!descendantsOfArray.isEmpty()) { - for (ColumnDefinition subDefn : descendantsOfArray) { - if (!subDefn.isUnitOfRetention()) { - // this has already been processed - continue; - } - subDefn.setNotUnitOfRetention(); - scratchArray.addAll(subDefn.getChildren()); - } - descendantsOfArray = scratchArray; - } - } - } - // and mark any non-arrays with multiple fields as not retained - for (String startKey : defn.keySet()) { - ColumnDefinition colDefn = defn.get(startKey); - if (!colDefn.isUnitOfRetention()) { - // this has already been processed - continue; - } - if (!ElementDataType.array.name().equals(colDefn.getElementType())) { - if (!colDefn.getChildren().isEmpty()) { - colDefn.setNotUnitOfRetention(); - } - } - } - } - - /** - * Convert the ColumnDefinition map to an ordered list of columns for - * transport layer. - * - * @param orderedDefns - * @return ordered list of Column objects - */ - public static ArrayList getColumns(ArrayList orderedDefns) { - ArrayList columns = new ArrayList(); - for (ColumnDefinition col : orderedDefns) { - columns.add(col.column); - } - return columns; - } - - /** - * Get the names of the columns that are written into the underlying database table. - * These are the isUnitOfRetention() columns. - * - * @param orderedDefns - * @return - */ - public static ArrayList getRetentionColumnNames(ArrayList orderedDefns) { - ArrayList writtenColumns = new ArrayList(); - for ( ColumnDefinition cd : orderedDefns ) { - if ( cd.isUnitOfRetention() ) { - writtenColumns.add(cd.getElementKey()); - } - } - return writtenColumns; - } - - /** - * Covert the ColumnDefinition map into a JSON schema. - * - * @param defns - * @return - */ - public static TreeMap getDataModel(List orderedDefns) { - TreeMap model = new TreeMap(); - - for (ColumnDefinition c : orderedDefns) { - if (c.getParent() == null) { - model.put(c.getElementName(), new TreeMap()); - @SuppressWarnings("unchecked") - TreeMap jsonSchema = (TreeMap) model - .get(c.getElementName()); - getDataModelHelper(jsonSchema, c); - } - } - return model; - } - - private static void getDataModelHelper(TreeMap jsonSchema, ColumnDefinition c) { - ElementType type = c.getType(); - ElementDataType dataType = type.getDataType(); - - if (dataType == ElementDataType.array) { - jsonSchema.put(JSON_SCHEMA_TYPE, dataType.name()); - if (!c.getElementType().equals(dataType.name())) { - jsonSchema.put(JSON_SCHEMA_ELEMENT_TYPE, c.getElementType()); - } - jsonSchema.put(JSON_SCHEMA_ELEMENT_KEY, c.getElementKey()); - ColumnDefinition ch = c.getChildren().get(0); - jsonSchema.put(JSON_SCHEMA_ITEMS, new TreeMap()); - @SuppressWarnings("unchecked") - TreeMap itemSchema = (TreeMap) jsonSchema - .get(JSON_SCHEMA_ITEMS); - getDataModelHelper(itemSchema, ch); // recursion... - } else if (dataType == ElementDataType.bool) { - jsonSchema.put(JSON_SCHEMA_TYPE, dataType.name()); - if (!c.getElementType().equals(dataType.name())) { - jsonSchema.put(JSON_SCHEMA_ELEMENT_TYPE, c.getElementType()); - } - jsonSchema.put(JSON_SCHEMA_ELEMENT_KEY, c.getElementKey()); - } else if (dataType == ElementDataType.configpath) { - jsonSchema.put(JSON_SCHEMA_TYPE, ElementDataType.string.name()); - jsonSchema.put(JSON_SCHEMA_ELEMENT_TYPE, c.getElementType()); - jsonSchema.put(JSON_SCHEMA_ELEMENT_KEY, c.getElementKey()); - } else if (dataType == ElementDataType.integer) { - jsonSchema.put(JSON_SCHEMA_TYPE, dataType.name()); - if (!c.getElementType().equals(dataType.name())) { - jsonSchema.put(JSON_SCHEMA_ELEMENT_TYPE, c.getElementType()); - } - jsonSchema.put(JSON_SCHEMA_ELEMENT_KEY, c.getElementKey()); - } else if (dataType == ElementDataType.number) { - jsonSchema.put(JSON_SCHEMA_TYPE, dataType.name()); - if (!c.getElementType().equals(dataType.name())) { - jsonSchema.put(JSON_SCHEMA_ELEMENT_TYPE, c.getElementType()); - } - jsonSchema.put(JSON_SCHEMA_ELEMENT_KEY, c.getElementKey()); - } else if (dataType == ElementDataType.object) { - jsonSchema.put(JSON_SCHEMA_TYPE, dataType.name()); - if (!c.getElementType().equals(dataType.name())) { - jsonSchema.put(JSON_SCHEMA_ELEMENT_TYPE, c.getElementType()); - } - jsonSchema.put(JSON_SCHEMA_ELEMENT_KEY, c.getElementKey()); - jsonSchema.put(JSON_SCHEMA_PROPERTIES, new TreeMap()); - @SuppressWarnings("unchecked") - TreeMap propertiesSchema = (TreeMap) jsonSchema - .get(JSON_SCHEMA_PROPERTIES); - for (ColumnDefinition ch : c.getChildren()) { - propertiesSchema.put(c.getElementName(), new TreeMap()); - @SuppressWarnings("unchecked") - TreeMap itemSchema = (TreeMap) propertiesSchema.get(c - .getElementName()); - getDataModelHelper(itemSchema, ch); // recursion... - } - } else if (dataType == ElementDataType.rowpath) { - jsonSchema.put(JSON_SCHEMA_TYPE, ElementDataType.string.name()); - jsonSchema.put(JSON_SCHEMA_ELEMENT_TYPE, ElementDataType.rowpath.name()); - jsonSchema.put(JSON_SCHEMA_ELEMENT_KEY, c.getElementKey()); - } else if (dataType == ElementDataType.string) { - jsonSchema.put(JSON_SCHEMA_TYPE, ElementDataType.string.name()); - if (!c.getElementType().equals(dataType.name())) { - jsonSchema.put(JSON_SCHEMA_ELEMENT_TYPE, c.getElementType()); - } - jsonSchema.put(JSON_SCHEMA_ELEMENT_KEY, c.getElementKey()); - } else { - throw new IllegalStateException("unexpected alternative ElementDataType"); - } - } - - @Override - public int compareTo(ColumnDefinition another) { - return this.getElementKey().compareTo(another.getElementKey()); - } - -} \ No newline at end of file diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncETagsUtils.java b/src/it/java/org/opendatakit/aggregate/odktables/api/SyncETagsUtils.java deleted file mode 100644 index 7fd58b5d0..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncETagsUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api; - -import java.net.URI; -import java.util.Properties; - -public class SyncETagsUtils { - - private static Properties p = new Properties(); - - /** - * For ease of mocking... - */ - public SyncETagsUtils() { - } - - - public String getManifestSyncETag(String context, String appName, URI url, String tableId) { - - String value = (String) p.get(appName + "|manifest|" + url + "|" + (tableId == null ? "" : tableId) ); - - return value; - } - - public void updateManifestSyncETag(String context, String appName, URI url, String tableId, String etag) { - - p.put(appName + "|manifest|" + url + "|" + (tableId == null ? "" : tableId), etag); - } - - - /** - * @param context - * @param appName - * @param url - * @param tableId - * @param modified - * @return - */ - public String getFileSyncETag(String context, String appName, URI url, String tableId, long modified) { - - String value = (String) p.get(appName + "|file|" + url + "|" + (tableId == null ? "" : tableId) + "|" + Long.toString(modified) ); - - return value; - } - - public void updateFileSyncETag(String context, String appName, URI url, String tableId, long modified, String etag) { - - p.put(appName + "|manifest|" + url + "|" + (tableId == null ? "" : tableId) + "|" + Long.toString(modified) , etag); - } - -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncProgressState.java b/src/it/java/org/opendatakit/aggregate/odktables/api/SyncProgressState.java deleted file mode 100644 index b23c83783..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncProgressState.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api; - - -public enum SyncProgressState { - INIT, STARTING, APP_FILES, TABLE_FILES, ROWS, COMPLETE, ERROR; -} \ No newline at end of file diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRow.java b/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRow.java deleted file mode 100644 index cb95cf377..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRow.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2012 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api; - -import org.opendatakit.aggregate.odktables.rest.entity.DataKeyValue; -import org.opendatakit.aggregate.odktables.rest.entity.RowFilterScope; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * A SyncRow is an in-between class to map rows in the database to rows in the - * cloud. - * - * @author the.dylan.price@gmail.com - * - */ -public class SyncRow { - private static final List emptyUriFragmentsList = Collections.unmodifiableList(new ArrayList()); - - private String rowId; - private String rowETag; - - /** - * Sync status field. - */ - private boolean deleted; - - /** - * OdkTables metadata column. - */ - private String formId; - - /** - * OdkTables metadata column. - */ - private String locale; - - /** - * Filtering field - */ - private RowFilterScope filterScope; - - /** - * The savepoint type of the file. - */ - private String savepointType; - - /** - * OdkTables metadata column. - */ - private String savepointTimestamp; - - /** - * OdkTables metadata column. - */ - private String savepointCreator; - - private ArrayList orderedValues; - - private List uriFragments; - - public SyncRow(final String rowId, final String rowETag, final boolean deleted, - final String formId, final String locale, final String savepointType, - final String savepointTimestamp, final String savepointCreator, final RowFilterScope filterScope, - final ArrayList values, final ArrayList fileAttachmentColumns) { - this.rowId = rowId; - this.rowETag = rowETag; - this.deleted = deleted; - this.formId = formId; - this.locale = locale; - this.savepointType = savepointType; - this.savepointTimestamp = savepointTimestamp; - this.savepointCreator = savepointCreator; - this.filterScope = filterScope; - if (values == null) { - this.orderedValues = new ArrayList(); - } else { - Collections.sort(values, new Comparator() { - - @Override - public int compare(DataKeyValue arg0, DataKeyValue arg1) { - return arg0.column.compareTo(arg1.column); - } - }); - - this.orderedValues = values; - } - // build up the uriFragments value... - // the common case is that this is empty. - // Use the static immutable list for that condition. - if ( !fileAttachmentColumns.isEmpty() ) { - ArrayList uriFragments = new ArrayList(); - // extract the non-null uriFragments here... - int idxAttachment = 0; - String facName = fileAttachmentColumns.get(idxAttachment).getElementKey(); - for ( DataKeyValue dkv : orderedValues) { - if ( dkv.column.equals(facName) ) { - if ( dkv.value != null ) { - uriFragments.add(dkv.value); - } - ++idxAttachment; - if ( idxAttachment >= fileAttachmentColumns.size() ) { - break; - } else { - facName = fileAttachmentColumns.get(idxAttachment).getElementKey(); - } - } - } - if ( uriFragments.isEmpty() ) { - this.uriFragments = emptyUriFragmentsList; - } else { - this.uriFragments = uriFragments; - } - } else { - this.uriFragments = emptyUriFragmentsList; - } - } - - public String getRowId() { - return this.rowId; - } - - public void setRowId(final String rowId) { - this.rowId = rowId; - } - - public String getRowETag() { - return this.rowETag; - } - - public void setRowETag(final String rowETag) { - this.rowETag = rowETag; - } - - public boolean isDeleted() { - return this.deleted; - } - - public void setDeleted(final boolean deleted) { - this.deleted = deleted; - } - - public String getFormId() { - return formId; - } - - public void setFormId(String formId) { - this.formId = formId; - } - - public String getLocale() { - return locale; - } - - public void setLocale(String locale) { - this.locale = locale; - } - - public RowFilterScope getFilterScope() { - return filterScope; - } - - public void setFilterScope(RowFilterScope filterScope) { - this.filterScope = filterScope; - } - - public String getSavepointType() { - return savepointType; - } - - public void setSavepointType(String savepointType) { - this.savepointType = savepointType; - } - - public String getSavepointTimestamp() { - return savepointTimestamp; - } - - public void setSavepointTimestamp(String savepointTimestamp) { - this.savepointTimestamp = savepointTimestamp; - } - - public String getSavepointCreator() { - return savepointCreator; - } - - public void setSavepointCreator(String savepointCreator) { - this.savepointCreator = savepointCreator; - } - - public ArrayList getValues() { - return this.orderedValues; - } - - public void setValues(final ArrayList values) { - if (values == null) { - this.orderedValues = new ArrayList(); - } else { - Collections.sort(values, new Comparator() { - - @Override - public int compare(DataKeyValue arg0, DataKeyValue arg1) { - return arg0.column.compareTo(arg1.column); - } - }); - - this.orderedValues = values; - } - } - - public List getUriFragments() { - return this.uriFragments; - } - - @Override - public boolean equals(final Object o) { - if (o == this) - return true; - if (!(o instanceof SyncRow)) - return false; - final SyncRow other = (SyncRow) o; - if (!other.canEqual((Object) this)) - return false; - // primary key - if (this.getRowId() == null ? other.getRowId() != null : !this.getRowId().equals( - other.getRowId())) - return false; - - // sync status - if (this.getRowETag() == null ? other.getRowETag() != null : !this.getRowETag().equals( - other.getRowETag())) - return false; - if (this.isDeleted() != other.isDeleted()) - return false; - - if (this.getFilterScope() != other.getFilterScope()) - return false; - - // sync'd metadata - if (this.getFormId() == null ? other.getFormId() != null : !this.getFormId().equals( - other.getFormId())) - return false; - if (this.getLocale() == null ? other.getLocale() != null : !this.getLocale().equals( - other.getLocale())) - return false; - if (this.getSavepointType() == null ? other.getSavepointType() != null : !this - .getSavepointType().equals(other.getSavepointType())) - return false; - if (this.getSavepointTimestamp() == null ? other.getSavepointTimestamp() != null : !this - .getSavepointTimestamp().equals(other.getSavepointTimestamp())) - return false; - if (this.getSavepointCreator() == null ? other.getSavepointCreator() != null : !this - .getSavepointCreator().equals(other.getSavepointCreator())) - return false; - - // data - if (this.getValues() == null ? other.getValues() != null : !this.getValues().equals( - (Object) other.getValues())) - return false; - return true; - } - - public boolean canEqual(final Object other) { - return other instanceof SyncRow; - } - - @Override - public int hashCode() { - final int PRIME = 31; - int result = 1; - // primary key - result = result * PRIME + (this.getRowId() == null ? 0 : this.getRowId().hashCode()); - // sync status - result = result * PRIME + (this.getRowETag() == null ? 0 : this.getRowETag().hashCode()); - result = result * PRIME + (this.isDeleted() ? 1231 : 1237); - // sync'd metadata - result = result * PRIME - + (this.getFilterScope() == null ? 0 : this.getFilterScope().hashCode()); - result = result * PRIME + (this.getFormId() == null ? 0 : this.getFormId().hashCode()); - result = result * PRIME + (this.getLocale() == null ? 0 : this.getLocale().hashCode()); - result = result * PRIME - + (this.getSavepointType() == null ? 0 : this.getSavepointType().hashCode()); - result = result * PRIME - + (this.getSavepointTimestamp() == null ? 0 : this.getSavepointTimestamp().hashCode()); - result = result * PRIME - + (this.getSavepointCreator() == null ? 0 : this.getSavepointCreator().hashCode()); - // data - result = result * PRIME + (this.getValues() == null ? 0 : this.getValues().hashCode()); - return result; - } - - @Override - public String toString() { - return "SyncRow[rowId=" + this.getRowId() + ", rowETag=" + this.getRowETag() + ", deleted=" - + this.isDeleted() + ", filterScope=" + this.getFilterScope().toString() + ", formId=" - + this.getFormId() + ", locale=" + this.getLocale() + ", savepointType=" - + this.getSavepointType() + ", savepointTimestamp=" + this.getSavepointTimestamp() - + ", savepointCreator=" + this.getSavepointCreator() + ", values=" + this.getValues() + "["; - } - -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRowDataChanges.java b/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRowDataChanges.java deleted file mode 100644 index 76ebbc4c9..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRowDataChanges.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.opendatakit.aggregate.odktables.api; - -import org.opendatakit.aggregate.odktables.rest.ElementDataType; -import org.opendatakit.aggregate.odktables.rest.entity.DataKeyValue; - -import java.util.ArrayList; - -/** - * Tracks the data values for the local and server row so that we - * can construct the appropriate database insert/update statements. - * - * @author mitchellsundt@gmail.com - * - */ -final class SyncRowDataChanges { - final SyncRow serverRow; - final SyncRow localRow; - boolean isRestPendingFiles; - final int localRowConflictType; - - SyncRowDataChanges(SyncRow serverRow, SyncRow localRow, boolean isRestPendingFiles) { - this.serverRow = serverRow; - this.localRow = localRow; - this.isRestPendingFiles = isRestPendingFiles; - this.localRowConflictType = -1; - } - - SyncRowDataChanges(SyncRow serverRow, SyncRow localRow, boolean isRestPendingFiles, - int localRowConflictType) { - this.serverRow = serverRow; - this.localRow = localRow; - this.isRestPendingFiles = isRestPendingFiles; - this.localRowConflictType = localRowConflictType; - } - - boolean identicalValuesExceptRowETagAndFilterScope(ArrayList orderedDefns) { - if ((serverRow.getSavepointTimestamp() == null) ? (localRow.getSavepointTimestamp() != null) - : !serverRow.getSavepointTimestamp().equals(localRow.getSavepointTimestamp())) { - return false; - } - if ((serverRow.getSavepointCreator() == null) ? (localRow.getSavepointCreator() != null) - : !serverRow.getSavepointCreator().equals(localRow.getSavepointCreator())) { - return false; - } - if ((serverRow.getFormId() == null) ? (localRow.getFormId() != null) : !serverRow.getFormId() - .equals(localRow.getFormId())) { - return false; - } - if ((serverRow.getLocale() == null) ? (localRow.getLocale() != null) : !serverRow.getLocale() - .equals(localRow.getLocale())) { - return false; - } - if ((serverRow.getRowId() == null) ? (localRow.getRowId() != null) : !serverRow.getRowId() - .equals(localRow.getRowId())) { - return false; - } - if ((serverRow.getSavepointType() == null) ? (localRow.getSavepointType() != null) - : !serverRow.getSavepointType().equals(localRow.getSavepointType())) { - return false; - } - ArrayList localValues = localRow.getValues(); - ArrayList serverValues = serverRow.getValues(); - - if (localValues == null && serverValues == null) { - return true; - } else if (localValues == null || serverValues == null) { - return false; - } - - if (localValues.size() != serverValues.size()) { - return false; - } - - for (int i = 0; i < localValues.size(); ++i) { - DataKeyValue local = localValues.get(i); - DataKeyValue server = serverValues.get(i); - if (!local.column.equals(server.column)) { - return false; - } - if (local.value == null && server.value == null) { - continue; - } else if (local.value == null || server.value == null) { - return false; - } else if (local.value.equals(server.value)) { - continue; - } - - // NOT textually identical. - // - // Everything must be textually identical except possibly number fields - // which may have rounding due to different database implementations, - // data representations, and marshaling libraries. - // - ColumnDefinition cd = ColumnDefinition.find(orderedDefns, local.column); - if (cd.getType().getDataType() == ElementDataType.number) { - // !!Important!! Double.valueOf(str) handles NaN and +/-Infinity - Double localNumber = Double.valueOf(local.value); - Double serverNumber = Double.valueOf(server.value); - - if (localNumber.equals(serverNumber)) { - // simple case -- trailing zeros or string representation mix-up - // - continue; - } else if (localNumber.isInfinite() && serverNumber.isInfinite()) { - // if they are both plus or both minus infinity, we have a match - if (Math.signum(localNumber) == Math.signum(serverNumber)) { - continue; - } else { - return false; - } - } else if (localNumber.isNaN() || localNumber.isInfinite() || serverNumber.isNaN() - || serverNumber.isInfinite()) { - // one or the other is special1 - return false; - } else { - double localDbl = localNumber; - double serverDbl = serverNumber; - if (localDbl == serverDbl) { - continue; - } - // OK. We have two values like 9.80 and 9.8 - // consider them equal if they are adjacent to each other. - double localNear = localDbl; - int idist = 0; - int idistMax = 128; - for (idist = 0; idist < idistMax; ++idist) { - localNear = Math.nextAfter(localNear, serverDbl); - if (localNear == serverDbl) { - break; - } - } - if (idist < idistMax) { - continue; - } - return false; - } - } else { - // textual identity is required! - return false; - } - } - if (!localValues.containsAll(serverValues)) { - return false; - } - return true; - } - - boolean identicalValues(ArrayList orderedDefns) { - if ((serverRow.getFilterScope() == null) ? (localRow.getFilterScope() != null) : !serverRow - .getFilterScope().equals(localRow.getFilterScope())) { - return false; - } - if ((serverRow.getRowETag() == null) ? (localRow.getRowETag() != null) : !serverRow - .getRowETag().equals(localRow.getRowETag())) { - return false; - } - return identicalValuesExceptRowETagAndFilterScope(orderedDefns); - } -} \ No newline at end of file diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRowPending.java b/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRowPending.java deleted file mode 100644 index fabea98bb..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/SyncRowPending.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api; - -import java.util.List; - -/** - * Class that holds minimal information necessary for synchronizing instance file attachments. - * This should enable earlier garbage collection of the SyncRow objects. - * - * @author mitchellsundt@gmail.com - * - */ -public class SyncRowPending { - final private String rowId; - final private String rowETag; - final private List uriFragments; - final private boolean getOnly; - final private boolean shouldDeleteFiles; - final private boolean updateState; - - public SyncRowPending(SyncRow syncRow, boolean getOnly, boolean shouldDeleteFiles, boolean updateState) { - this.rowId = syncRow.getRowId(); - this.rowETag = syncRow.getRowETag(); - this.uriFragments = syncRow.getUriFragments(); - this.getOnly = getOnly; - this.shouldDeleteFiles = shouldDeleteFiles; - this.updateState = updateState; - } - - public String getRowId() { - return rowId; - } - - public String getRowETag() { - return rowETag; - } - - public List getUriFragments() { - return uriFragments; - } - - public boolean onlyGetFiles() { - return getOnly; - } - - public boolean shouldDeleteExtraneousLocalFiles() { - return shouldDeleteFiles; - } - - public boolean updateSyncState() { - return updateState; - } -} \ No newline at end of file diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/SynchronizationResult.java b/src/it/java/org/opendatakit/aggregate/odktables/api/SynchronizationResult.java deleted file mode 100644 index eee1a5312..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/SynchronizationResult.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api; - -import java.util.*; - -/** - * An object for measuring the results of a synchronization call. This is - * especially intended to see how to display the results to the user. For - * example, imagine you wanted to synchronize three tables. The object should - * contain three TableResult objects, mapping the dbTableName to the status - * corresponding to outcome. - * - * @author sudar.sam@gmail.com - * - */ -public class SynchronizationResult { - - /** - * Status code used at app and table levels - * - * WORKING should never be returned (the initial value) - */ - public enum Status { - WORKING, SUCCESS, FAILURE, AUTH_EXCEPTION, EXCEPTION, TABLE_DOES_NOT_EXIST_ON_SERVER, TABLE_CONTAINS_CHECKPOINTS, TABLE_CONTAINS_CONFLICTS, TABLE_PENDING_ATTACHMENTS, TABLE_REQUIRES_APP_LEVEL_SYNC; - } - - private Status appLevelStatus = Status.WORKING; - - private final Map mResults = new HashMap(); - - public SynchronizationResult() { - } - - public Status getAppLevelStatus() { - return appLevelStatus; - } - - public void setAppLevelStatus(Status status) { - this.appLevelStatus = status; - } - - /** - * Get all the {@link TableResult} objects in this result. - * - * @return - */ - public List getTableResults() { - List r = new ArrayList(); - r.addAll(this.mResults.values()); - Collections.sort(r, new Comparator() { - @Override - public int compare(TableResult lhs, TableResult rhs) { - return lhs.getTableId().compareTo(rhs.getTableId()); - } - }); - - return r; - } - - public TableResult getTableResult(String tableId) { - TableResult r = mResults.get(tableId); - if (r == null) { - r = new TableResult(tableId); - mResults.put(tableId, r); - } - return r; - } - -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/SynchronizerStatus.java b/src/it/java/org/opendatakit/aggregate/odktables/api/SynchronizerStatus.java deleted file mode 100644 index 69e1ba0a5..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/SynchronizerStatus.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.opendatakit.aggregate.odktables.api; - - -public interface SynchronizerStatus { - /** - * Status of this action. - * - * @param text - * @param progressPercentage - * 0..100 - * @param indeterminateProgress - * true if progressGrains is N/A - */ - void updateNotification(SyncProgressState state, int textResource, Object[] formatArgVals, - Double progressPercentage, boolean indeterminateProgress); -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/TableResult.java b/src/it/java/org/opendatakit/aggregate/odktables/api/TableResult.java deleted file mode 100644 index a7fcf3d8e..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/TableResult.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api; - -import org.opendatakit.aggregate.odktables.api.SynchronizationResult.Status; - -/** - * The mapping of a table to the status of its synchronization. - * - * @author sudar.sam@gmail.com - * - */ -public class TableResult { - - private final String mTableId; - private String mDisplayName; - private Status mStatus = Status.WORKING; - private String mMessage = Status.WORKING.name(); - /** Flag if schema was pulled from the server. */ - private boolean mPulledServerSchema; - /** Flag if properties were pulled from the server. */ - private boolean mPulledServerProps; - /** Flag if data was pulled from the server. */ - private boolean mPulledServerData; - /** Flag if properties were pushed to the server. */ - private boolean mPushedLocalProps; - /** Flag if data was pushed to the server. */ - private boolean mPushedLocalData; - /** Flag if properties had to be pushed to the server. */ - private boolean mHadLocalPropChanges; - /** Flag if local data had to be pushed to the server. */ - private boolean mHadLocalDataChanges; - /** Flag if schema had to be pulled from the server. */ - private boolean mHadServerSchemaChanges; - /** Flag if properties had to be pulled from the server. */ - private boolean mHadServerPropChanges; - /** Flat if data had to be pulled from the server. */ - private boolean mHadServerDataChanges; - - private int mServerNumUpserts = 0; - private int mServerNumDeletes = 0; - private int mLocalNumInserts = 0; - private int mLocalNumUpdates = 0; - private int mLocalNumDeletes = 0; - private int mLocalNumConflicts = 0; - private int mLocalNumAttachmentRetries = 0; - - public void incServerUpserts() { - ++mServerNumUpserts; - } - - public void incServerDeletes() { - ++mServerNumDeletes; - } - - public void incLocalInserts() { - ++mLocalNumInserts; - } - - public void incLocalUpdates() { - ++mLocalNumUpdates; - } - - public void incLocalDeletes() { - ++mLocalNumDeletes; - } - - public void incLocalConflicts() { - ++mLocalNumConflicts; - } - - public void incLocalAttachmentRetries() { - ++mLocalNumAttachmentRetries; - } - - /** - * Create a table result with a status of {@link Status#FAILURE}. This should - * then only be updated in the case of success or exceptions. The boolean - * flags are initialized to false; - * - * @param dbTableName - * @param status - */ - public TableResult(String tableId) { - this.mTableId = tableId; - this.mDisplayName = tableId; - this.mPulledServerData = false; - this.mPulledServerProps = false; - this.mPulledServerSchema = false; - this.mPushedLocalData = false; - this.mPushedLocalData = false; - this.mHadLocalDataChanges = false; - this.mHadLocalPropChanges = false; - this.mHadServerDataChanges = false; - this.mHadServerPropChanges = false; - this.mHadServerSchemaChanges = false; - } - - public String getTableId() { - return this.mTableId; - } - - public void setTableDisplayName(String displayName) { - this.mDisplayName = displayName; - } - - public String getTableDisplayName() { - return this.mDisplayName; - } - - public Status getStatus() { - return this.mStatus; - } - - public boolean pulledServerData() { - return this.mPulledServerData; - } - - public boolean pulledServerProperties() { - return this.mPulledServerProps; - } - - public boolean pulledServerSchema() { - return this.mPulledServerSchema; - } - - public boolean pushedLocalProperties() { - return this.mPushedLocalProps; - } - - public boolean pushedLocalData() { - return this.mPushedLocalData; - } - - public boolean hadLocalDataChanges() { - return this.mHadLocalDataChanges; - } - - public boolean hadLocalPropertiesChanges() { - return this.mHadLocalPropChanges; - } - - public boolean serverHadDataChanges() { - return this.mHadServerDataChanges; - } - - public boolean serverHadPropertiesChanges() { - return this.mHadServerPropChanges; - } - - public boolean serverHadSchemaChanges() { - return this.mHadServerSchemaChanges; - } - - public void setPulledServerData(boolean pulledData) { - this.mPulledServerData = pulledData; - } - - public void setPulledServerProperties(boolean pulledProperties) { - this.mPulledServerProps = pulledProperties; - } - - public void setPulledServerSchema(boolean pulledSchema) { - this.mPulledServerSchema = pulledSchema; - } - - public void setPushedLocalProperties(boolean pushedProperties) { - this.mPushedLocalProps = pushedProperties; - } - - public void setPushedLocalData(boolean pushedData) { - this.mPushedLocalData = pushedData; - } - - public void setHadLocalPropertiesChanges(boolean hadChanges) { - this.mHadLocalPropChanges = hadChanges; - } - - public void setHadLocalDataChanges(boolean hadChanges) { - this.mHadLocalDataChanges = hadChanges; - } - - public void setServerHadSchemaChanges(boolean serverHadChanges) { - this.mHadServerSchemaChanges = serverHadChanges; - } - - public void setServerHadPropertiesChanges(boolean serverHadChanges) { - this.mHadServerPropChanges = serverHadChanges; - } - - public void setServerHadDataChanges(boolean serverHadChanges) { - this.mHadServerDataChanges = serverHadChanges; - } - - /** - * Set a message that might be passed back to the user. Likely a place to pass - * the error message back to the user in case of exceptions. - * - * @param message - */ - public void setMessage(String message) { - this.mMessage = message; - } - - public String getMessage() { - return this.mMessage; - } - - /** - * Update the status of this result. - * - * @param newStatus - * @throws UnsupportedOperationException - * if the satus has been set to {@link Status#EXCEPTION} and the - * newStatus is something other than {@link Status#EXCEPTION}. - */ - public void setStatus(Status newStatus) { - if (this.mStatus == Status.EXCEPTION && newStatus != Status.EXCEPTION) { - throw new UnsupportedOperationException("Tried to set TableResult " + "status" - + " to something other than exception when it had alread been set" + " to exception."); - } - this.mStatus = newStatus; - } - -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/Util.java b/src/it/java/org/opendatakit/aggregate/odktables/api/Util.java deleted file mode 100644 index f47680eea..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/Util.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.opendatakit.aggregate.odktables.api; - -import org.apache.commons.lang3.StringUtils; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import static org.junit.Assert.assertTrue; - -public class Util { - - public static String buildUri(String base, String... path) { - String pathElts = StringUtils.join(path, "/"); - URI uri = URI.create(base + "/" + pathElts).normalize(); - return uri.toASCIIString(); - } - - /** - * V must implement equals. - */ - public static void assertCollectionSameElements(Collection expected, Collection actual) { - Collection expectedCopy = new ArrayList(expected); - Collection actualCopy = new ArrayList(actual); - - for (V item : actualCopy) { - assertTrue(expectedCopy.remove(item)); - } - assertTrue(expectedCopy.isEmpty()); - } - - public static List list(V... values) { - ArrayList list = new ArrayList(); - for (V value : values) { - list.add(value); - } - return list; - } -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/AccessDeniedException.java b/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/AccessDeniedException.java deleted file mode 100644 index 0a521e114..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/AccessDeniedException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api.exceptions; - -import java.io.IOException; - -public class AccessDeniedException extends IOException { - - private static final long serialVersionUID = 1L; - - public AccessDeniedException() { - super(); - } - - /** - * @param detailMessage - */ - public AccessDeniedException(String detailMessage) { - super(detailMessage); - } - -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/InvalidAuthTokenException.java b/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/InvalidAuthTokenException.java deleted file mode 100644 index 1287e79c0..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/InvalidAuthTokenException.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api.exceptions; - -public class InvalidAuthTokenException extends Exception { - - private static final long serialVersionUID = 1L; - - public InvalidAuthTokenException() { - super(); - } - - /** - * @param detailMessage - * @param throwable - */ - public InvalidAuthTokenException(String detailMessage, Throwable throwable) { - super(detailMessage, throwable); - } - - /** - * @param detailMessage - */ - public InvalidAuthTokenException(String detailMessage) { - super(detailMessage); - } - - /** - * @param throwable - */ - public InvalidAuthTokenException(Throwable throwable) { - super(throwable); - } - -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/NoAppNameSpecifiedException.java b/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/NoAppNameSpecifiedException.java deleted file mode 100644 index dd972e218..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/NoAppNameSpecifiedException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api.exceptions; - -import java.io.IOException; - -public class NoAppNameSpecifiedException extends IOException { - - private static final long serialVersionUID = -5359484141172388331L; - - public NoAppNameSpecifiedException() { - super(); - } - - /** - * @param detailMessage - * @param throwable - */ - public NoAppNameSpecifiedException(String detailMessage, Throwable throwable) { - super(detailMessage, throwable); - } - - /** - * @param detailMessage - */ - public NoAppNameSpecifiedException(String detailMessage) { - super(detailMessage); - } - - /** - * @param throwable - */ - public NoAppNameSpecifiedException(Throwable throwable) { - super(throwable); - } - -} \ No newline at end of file diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/RequestFailureException.java b/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/RequestFailureException.java deleted file mode 100644 index 2e37fd66b..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/RequestFailureException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api.exceptions; - -import java.io.IOException; - -public class RequestFailureException extends IOException { - - private static final long serialVersionUID = 1L; - - public RequestFailureException() { - super(); - } - - /** - * @param detailMessage - */ - public RequestFailureException(String detailMessage) { - super(detailMessage); - } - -} diff --git a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/SchemaMismatchException.java b/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/SchemaMismatchException.java deleted file mode 100644 index ceba99108..000000000 --- a/src/it/java/org/opendatakit/aggregate/odktables/api/exceptions/SchemaMismatchException.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.api.exceptions; - -public class SchemaMismatchException extends Exception { - - private static final long serialVersionUID = 1L; - - public SchemaMismatchException() { - super(); - } - - /** - * @param detailMessage - * @param throwable - */ - public SchemaMismatchException(String detailMessage, Throwable throwable) { - super(detailMessage, throwable); - } - - /** - * @param detailMessage - */ - public SchemaMismatchException(String detailMessage) { - super(detailMessage); - } - - /** - * @param throwable - */ - public SchemaMismatchException(Throwable throwable) { - super(throwable); - } - -} diff --git a/src/it/java/org/opendatakit/common/ermodel/BlobRelationSetTestIT.java b/src/it/java/org/opendatakit/common/ermodel/BlobRelationSetTestIT.java index e0f6013c8..dd2bb1b19 100644 --- a/src/it/java/org/opendatakit/common/ermodel/BlobRelationSetTestIT.java +++ b/src/it/java/org/opendatakit/common/ermodel/BlobRelationSetTestIT.java @@ -13,8 +13,6 @@ */ package org.opendatakit.common.ermodel; -import static org.junit.Assert.*; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -22,6 +20,8 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import static org.junit.Assert.assertEquals; + /** * Simple test case for the AbstractBlobRelationSet class. * diff --git a/src/it/java/org/opendatakit/common/ermodel/RelationTestIT.java b/src/it/java/org/opendatakit/common/ermodel/RelationTestIT.java index fa6b75117..b2cfcba0c 100644 --- a/src/it/java/org/opendatakit/common/ermodel/RelationTestIT.java +++ b/src/it/java/org/opendatakit/common/ermodel/RelationTestIT.java @@ -13,27 +13,27 @@ */ package org.opendatakit.common.ermodel; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.Datastore; import org.opendatakit.common.persistence.PersistConsts; -import org.opendatakit.common.persistence.WrappedBigDecimal; import org.opendatakit.common.persistence.Query.FilterOperation; +import org.opendatakit.common.persistence.WrappedBigDecimal; import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + /** * Simple test case of the AbstractRelation class. Also an example of how to use * it. @@ -278,10 +278,10 @@ public void testCase8() throws ODKDatastoreException { if (ds instanceof org.opendatakit.common.persistence.engine.mysql.DatastoreImpl) { // MySQL does not support NaN, Infinity, -Infinity return; - } else if (ds instanceof org.opendatakit.common.persistence.engine.sqlserver.DatastoreImpl) { + } /* else if (ds instanceof org.opendatakit.common.persistence.engine.sqlserver.DatastoreImpl) { // SqlServer does not support NaN, Infinity, -Infinity return; - } + } */ MyRelation rel = new MyRelation(cc); rel = new MyRelation(cc); Entity e = rel.newEntity(cc); diff --git a/src/it/java/org/opendatakit/common/persistence/LargeStringTestIT.java b/src/it/java/org/opendatakit/common/persistence/LargeStringTestIT.java index 26c36e4d7..cdc9d2c42 100644 --- a/src/it/java/org/opendatakit/common/persistence/LargeStringTestIT.java +++ b/src/it/java/org/opendatakit/common/persistence/LargeStringTestIT.java @@ -13,10 +13,6 @@ */ package org.opendatakit.common.persistence; -import static org.junit.Assert.assertEquals; - -import java.util.List; - import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; @@ -29,6 +25,10 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import java.util.List; + +import static org.junit.Assert.assertEquals; + /** * Tests storage of strings up to STR_LENGTH (16384) characters long. * Confirms that if you store longer strings, they get truncated, and diff --git a/src/it/java/org/opendatakit/common/persistence/QueryResultTestIT.java b/src/it/java/org/opendatakit/common/persistence/QueryResultTestIT.java index 47be4f00a..46224d835 100644 --- a/src/it/java/org/opendatakit/common/persistence/QueryResultTestIT.java +++ b/src/it/java/org/opendatakit/common/persistence/QueryResultTestIT.java @@ -13,15 +13,6 @@ */ package org.opendatakit.common.persistence; -import static org.junit.Assert.assertEquals; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; @@ -37,6 +28,15 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + @RunWith(org.junit.runners.JUnit4.class) public class QueryResultTestIT { diff --git a/src/it/java/org/opendatakit/common/persistence/TaskLockTestIT.java b/src/it/java/org/opendatakit/common/persistence/TaskLockTestIT.java index f054f0e21..8a09ee6d6 100644 --- a/src/it/java/org/opendatakit/common/persistence/TaskLockTestIT.java +++ b/src/it/java/org/opendatakit/common/persistence/TaskLockTestIT.java @@ -13,14 +13,6 @@ */ package org.opendatakit.common.persistence; -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.atomic.AtomicBoolean; - import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,6 +24,14 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.TestContextFactory; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.Assert.assertEquals; + /** * Tests the task lock mechanism and reports its performance statistics. * diff --git a/src/it/java/org/opendatakit/common/web/TestContextFactory.java b/src/it/java/org/opendatakit/common/web/TestContextFactory.java index 209f0b0b1..eb3eda94c 100644 --- a/src/it/java/org/opendatakit/common/web/TestContextFactory.java +++ b/src/it/java/org/opendatakit/common/web/TestContextFactory.java @@ -16,8 +16,6 @@ package org.opendatakit.common.web; -import javax.servlet.ServletContext; - import org.apache.commons.dbcp2.BasicDataSource; import org.junit.Ignore; import org.opendatakit.common.persistence.Datastore; @@ -27,6 +25,7 @@ import org.opendatakit.common.security.spring.UserServiceImpl; import org.opendatakit.common.web.constants.BasicConsts; +import javax.servlet.ServletContext; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; diff --git a/src/it/testfiles/forms/MultiWidget.xml b/src/it/testfiles/forms/MultiWidget.xml deleted file mode 100644 index aafec4220..000000000 --- a/src/it/testfiles/forms/MultiWidget.xml +++ /dev/null @@ -1,311 +0,0 @@ - - - - Multiwidgets Form - - - - - i speak english - - - menu button to change languages - - - - - ciào - - - "hello" in italian - - - - - こんにちは。 - - - "hello" in japanese - - - - - Здраво - - - "hello" in macedonian - - - - - - - - - - - - - - - - - - - 18.31 - 2010-06-15 - - Blood Pressure - - - 4 - - - - - n - - test@test.com - - - 123456789 - 3 - - this is a really long string where you can put lots of information to prepare a user for anything you would like. - - 1234567890.1234567890 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - integer not depending upon any of the select values - - - - integer for b - - - - integer for c - - - - integer for d - - - - - - scroll down to see default selection - - - 1 - - - - 2 - - - - 3 - - - - 4 - - - - this will launch the camera - - - - this will launch the camera - - - - this will launch the camera - - - - this will launch the camera - - - - - - - - - - - - - - - this will launch the audio recorder - - - - - push button to acknowledge video interview - - - - - - - - - yes to skip languages, validator, sections - - - y - - - - n - - - - - - email validator - - - - this will get gps location - - - - scans multi-format 1d/2d barcodes - - - this will launch the camera - - - - - - - - - - - - - - - - long hint: there is an upcoming section. - - - - - - - largest integer (9 places) - - - - readonly and long string - - - - - - - - - - - - readonly and long string - - - - - diff --git a/src/it/testfiles/forms/dylan_form.xml b/src/it/testfiles/forms/dylan_form.xml deleted file mode 100644 index 1ab696de4..000000000 --- a/src/it/testfiles/forms/dylan_form.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - Dylan's Form - - - - Record your location. - Take a picture of your location. - What is the name of your location? - Enter a random number from 1 to 5 - Name a thing at your location - Record the location of the thing. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/it/testfiles/forms/landUse.xml b/src/it/testfiles/forms/landUse.xml deleted file mode 100644 index 7070082c6..000000000 --- a/src/it/testfiles/forms/landUse.xml +++ /dev/null @@ -1,339 +0,0 @@ - - - - Land Use - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Barcode scanner hint - - - - This will get location using GPS - - - This will launch the camera. - - - - - - - - - - try entering a number < 1000 - - - - try entering a number < 1000 - - - - - - A - - - - B - - - - C - - - - - - - y - - - - n - - - - - - - - - - - N - - - - P - - - - C - - - - nk - - - - - - - y - - - - n - - - - - try entering a number < 1000 - - - - - - - - - none - - - - clearing - - - - selective - - - - group - - - - strip - - - - other - - - - - - - y - - - - n - - - - - - - - - - - y - - - - n - - - - - try entering a number < 1000 - - - - - - - - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_1/img_1.jpg b/src/it/testfiles/submissions/dylan_form/submission_1/img_1.jpg deleted file mode 100644 index 5bdd8cb3a..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_1/img_1.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_1/submission_1.xml b/src/it/testfiles/submissions/dylan_form/submission_1/submission_1.xml deleted file mode 100644 index 1a8f13cae..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_1/submission_1.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 12345 - - img_1 - Red Square - 1 - - Suzzallo Library - 47.655755 -122.30821 1.0 1.0 - - - Kane Hall - 47.656499 -122.30919 1.0 1.0 - - - Odegaard Library - 47.656427 -122.31036 1.0 1.0 - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_2/img_2.jpg b/src/it/testfiles/submissions/dylan_form/submission_2/img_2.jpg deleted file mode 100644 index 9b975fc22..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_2/img_2.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_2/submission_2.xml b/src/it/testfiles/submissions/dylan_form/submission_2/submission_2.xml deleted file mode 100644 index eb7f4cb96..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_2/submission_2.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 12345 - - img_2 - Eldorado Peak - 2 - - Dorado Needle - 48.5493 -121.1380 1.0 1.0 - - - Klawatti Peak - 48.5541 -121.1037 1.0 1.0 - - - Forbidden Peak - 48.5116 -121.0575 1.0 1.0 - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_3/img_3.jpg b/src/it/testfiles/submissions/dylan_form/submission_3/img_3.jpg deleted file mode 100644 index 12771fb8a..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_3/img_3.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_3/submission_3.xml b/src/it/testfiles/submissions/dylan_form/submission_3/submission_3.xml deleted file mode 100644 index c10ec6500..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_3/submission_3.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 12345 - - img_3 - Robinson Mountain - 3 - - Robinson Mountain - 48.72653 -120.57469 1.0 1.0 - - - Beauty Peak - 48.73117 -120.54534 1.0 1.0 - - - Devil's Peak - 48.73117 -120.54534 1.0 1.0 - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_4/img_4.jpg b/src/it/testfiles/submissions/dylan_form/submission_4/img_4.jpg deleted file mode 100644 index 2781a5f65..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_4/img_4.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_4/submission_4.xml b/src/it/testfiles/submissions/dylan_form/submission_4/submission_4.xml deleted file mode 100644 index 527fd42ae..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_4/submission_4.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - 12345 - - img_4 - Bellingham - 4 - - Western Washington University - 48.7359 -122.4857 1.0 1.0 - - - Bellingham Bay - 48.7568 -122.5619 1.0 1.0 - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_5/img_5.jpg b/src/it/testfiles/submissions/dylan_form/submission_5/img_5.jpg deleted file mode 100644 index 8ad412554..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_5/img_5.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_5/submission_5.xml b/src/it/testfiles/submissions/dylan_form/submission_5/submission_5.xml deleted file mode 100644 index 45f20d3ba..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_5/submission_5.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 12345 - - img_5 - Portland - 5 - - Powell's 1 - 45.52403 -122.68115 1.0 1.0 - - - Powell's 2 - 45.51350 -122.62562 1.0 1.0 - - - Rocky Butte - 45.5429 -122.5652 1.0 1.0 - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_6/img_6.jpg b/src/it/testfiles/submissions/dylan_form/submission_6/img_6.jpg deleted file mode 100644 index ae8c2158a..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_6/img_6.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_6/submission_6.xml b/src/it/testfiles/submissions/dylan_form/submission_6/submission_6.xml deleted file mode 100644 index 93c8b63da..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_6/submission_6.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - 12345 - 47.0403 -122.8994 1.0 1.0 - img_6 - Olympia - 6 - - Capitol Building - - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_7/img_7.jpg b/src/it/testfiles/submissions/dylan_form/submission_7/img_7.jpg deleted file mode 100644 index 8ac2558c8..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_7/img_7.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_7/submission_7.xml b/src/it/testfiles/submissions/dylan_form/submission_7/submission_7.xml deleted file mode 100644 index 0d16cc6cb..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_7/submission_7.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - 12345 - 47.4806 -120.7978 1.0 1.0 - img_7 - Enchantments - 7 - - McClellan Peak - - - - Little Annapurna - - - - Enchantment Peaks - - - - Prusik Peak - - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_8/img_8.jpg b/src/it/testfiles/submissions/dylan_form/submission_8/img_8.jpg deleted file mode 100644 index 401aebdf2..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_8/img_8.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_8/submission_8.xml b/src/it/testfiles/submissions/dylan_form/submission_8/submission_8.xml deleted file mode 100644 index 09df9aca1..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_8/submission_8.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 12345 - 45.6987 -122.6764 1.0 1.0 - img_8 - Columbia River High School - 8 - - School - - - - Parking Lot - - - - Football Field - - - diff --git a/src/it/testfiles/submissions/dylan_form/submission_9/img_9.jpg b/src/it/testfiles/submissions/dylan_form/submission_9/img_9.jpg deleted file mode 100644 index ed99a75a2..000000000 Binary files a/src/it/testfiles/submissions/dylan_form/submission_9/img_9.jpg and /dev/null differ diff --git a/src/it/testfiles/submissions/dylan_form/submission_9/submission_9.xml b/src/it/testfiles/submissions/dylan_form/submission_9/submission_9.xml deleted file mode 100644 index f081abeda..000000000 --- a/src/it/testfiles/submissions/dylan_form/submission_9/submission_9.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 12345 - 47.949 -124.3860 1.0 1.0 - img_9 - Forks - 9 - - Grocery Store - - - - Ranger Station - - - - Twilight Fans - - - diff --git a/src/main/java/org/opendatakit/aggregate/ContextFactory.java b/src/main/java/org/opendatakit/aggregate/ContextFactory.java index 2c981ee1d..975ba36bb 100644 --- a/src/main/java/org/opendatakit/aggregate/ContextFactory.java +++ b/src/main/java/org/opendatakit/aggregate/ContextFactory.java @@ -16,13 +16,6 @@ package org.opendatakit.aggregate; -import java.net.InetAddress; -import java.net.UnknownHostException; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; - import org.opendatakit.aggregate.constants.BeanDefs; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; import org.opendatakit.aggregate.odktables.security.TablesUserPermissions; @@ -41,6 +34,12 @@ import org.opendatakit.common.web.constants.HtmlConsts; import org.springframework.web.context.support.WebApplicationContextUtils; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import java.net.InetAddress; +import java.net.UnknownHostException; + /** * Server Context creates a singleton for application context to prevent * unnecessary construction diff --git a/src/main/java/org/opendatakit/aggregate/datamodel/TopLevelDynamicBase.java b/src/main/java/org/opendatakit/aggregate/datamodel/TopLevelDynamicBase.java index 12541537e..e48187419 100644 --- a/src/main/java/org/opendatakit/aggregate/datamodel/TopLevelDynamicBase.java +++ b/src/main/java/org/opendatakit/aggregate/datamodel/TopLevelDynamicBase.java @@ -13,14 +13,14 @@ */ package org.opendatakit.aggregate.datamodel; -import java.util.Date; - import org.opendatakit.common.datamodel.DynamicCommonFieldsBase; import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.DataField.IndexType; import org.opendatakit.common.security.User; +import java.util.Date; + /** * All instance data for an xform is stored in tables derived from diff --git a/src/main/java/org/opendatakit/aggregate/odktables/DataKeyValueDeepComparator.java b/src/main/java/org/opendatakit/aggregate/odktables/DataKeyValueDeepComparator.java index 1dff3d91d..1aab01dd5 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/DataKeyValueDeepComparator.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/DataKeyValueDeepComparator.java @@ -16,15 +16,15 @@ package org.opendatakit.aggregate.odktables; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; - import org.opendatakit.aggregate.odktables.relation.DbColumnDefinitions.DbColumnDefinitionsEntity; import org.opendatakit.aggregate.odktables.rest.ElementDataType; import org.opendatakit.aggregate.odktables.rest.ElementType; import org.opendatakit.aggregate.odktables.rest.entity.DataKeyValue; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; + public class DataKeyValueDeepComparator implements Comparator { private final HashMap columnMap diff --git a/src/main/java/org/opendatakit/aggregate/odktables/DataManager.java b/src/main/java/org/opendatakit/aggregate/odktables/DataManager.java index 5da26d101..17bf8fcc2 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/DataManager.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/DataManager.java @@ -16,14 +16,6 @@ package org.opendatakit.aggregate.odktables; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.apache.commons.lang3.Validate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -66,6 +58,14 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.constants.BasicConsts; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Manages read, insert, update, and delete operations on the rows of a table. * @@ -126,7 +126,7 @@ public DataManager(String appId, String tableId, TablesUserPermissions userPermi CallingContext cc) throws ODKEntityNotFoundException, ODKDatastoreException { Validate.notEmpty(appId); Validate.notEmpty(tableId); - Validate.notNull(cc); + Validate.notNull(cc, "cc is null"); this.cc = cc; this.userPermissions = userPermissions; this.converter = new EntityConverter(); @@ -907,7 +907,7 @@ public RowOutcomeList insertOrUpdateRows(RowList rows) throws ODKEntityPersistEx long startTime = System.currentTimeMillis(); try { - Validate.notNull(rows); + Validate.notNull(rows, "rows cannot be null"); ArrayList rowOutcomes = new ArrayList(); userPermissions.checkPermission(appId, tableId, TablePermission.WRITE_ROW); @@ -1154,7 +1154,7 @@ public Row insertOrUpdateRow(Row row) throws ODKEntityPersistException, ETagMismatchException, BadColumnNameException, PermissionDeniedException, InconsistentStateException { try { - Validate.notNull(row); + Validate.notNull(row, "row cannot be null"); userPermissions.checkPermission(appId, tableId, TablePermission.WRITE_ROW); @@ -1376,7 +1376,7 @@ public String deleteRow(String rowId, String currentRowETag) throws ODKEntityNot ODKDatastoreException, ODKTaskLockException, PermissionDeniedException, InconsistentStateException, BadColumnNameException, ETagMismatchException { try { - Validate.notNull(rowId); + Validate.notNull(rowId, "rowId cannot be null"); Validate.notBlank(rowId); userPermissions.checkPermission(appId, tableId, TablePermission.DELETE_ROW); diff --git a/src/main/java/org/opendatakit/aggregate/odktables/FileManager.java b/src/main/java/org/opendatakit/aggregate/odktables/FileManager.java index 80040ce7d..8591e596c 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/FileManager.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/FileManager.java @@ -15,9 +15,6 @@ */ package org.opendatakit.aggregate.odktables; -import java.util.List; -import java.util.Locale; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.odktables.exception.FileNotFoundException; @@ -36,6 +33,9 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.constants.BasicConsts; +import java.util.List; +import java.util.Locale; + /** * Implementation of file management APIs. * diff --git a/src/main/java/org/opendatakit/aggregate/odktables/FileManifestManager.java b/src/main/java/org/opendatakit/aggregate/odktables/FileManifestManager.java index 18672806b..a3c35c510 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/FileManifestManager.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/FileManifestManager.java @@ -15,11 +15,6 @@ */ package org.opendatakit.aggregate.odktables; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.apache.commons.lang3.Validate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -35,6 +30,11 @@ import org.opendatakit.common.persistence.exception.ODKTaskLockException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Manages the manifest of files. * diff --git a/src/main/java/org/opendatakit/aggregate/odktables/FileManifestUtils.java b/src/main/java/org/opendatakit/aggregate/odktables/FileManifestUtils.java index ae73ac602..02ac17104 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/FileManifestUtils.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/FileManifestUtils.java @@ -1,10 +1,5 @@ package org.opendatakit.aggregate.odktables; -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - import org.opendatakit.aggregate.odktables.relation.DbManifestETags; import org.opendatakit.aggregate.odktables.rest.entity.OdkTablesFileManifest; import org.opendatakit.aggregate.odktables.rest.entity.OdkTablesFileManifestEntry; @@ -13,6 +8,11 @@ import org.opendatakit.common.persistence.exception.ODKTaskLockException; import org.opendatakit.common.web.CallingContext; +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + public class FileManifestUtils { // TODO: Remove this hardcode when creating breaking changes to the Sync REST interface public static String getAppLevelManifestETag(String appId, CallingContext cc) throws ODKDatastoreException, ODKTaskLockException { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/InstanceFileManager.java b/src/main/java/org/opendatakit/aggregate/odktables/InstanceFileManager.java index 93eaaf9ce..197d3a7a4 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/InstanceFileManager.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/InstanceFileManager.java @@ -15,16 +15,10 @@ */ package org.opendatakit.aggregate.odktables; -import java.io.BufferedInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.ws.rs.core.MultivaluedMap; - -import org.apache.http.HeaderElement; -import org.apache.http.message.BasicHeaderValueParser; -import org.apache.http.message.HeaderValueParser; +import org.apache.hc.core5.http.HeaderElement; +import org.apache.hc.core5.http.message.BasicHeaderValueParser; +import org.apache.hc.core5.http.message.HeaderValueParser; +import org.apache.hc.core5.http.message.ParserCursor; import org.apache.wink.common.model.multipart.InMultiPart; import org.apache.wink.common.model.multipart.InPart; import org.opendatakit.aggregate.odktables.api.InstanceFileService; @@ -44,6 +38,12 @@ import org.opendatakit.common.persistence.exception.ODKTaskLockException; import org.opendatakit.common.web.CallingContext; +import javax.ws.rs.core.MultivaluedMap; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + /** * Implementation of file management APIs for row-level attachments. * @@ -379,7 +379,8 @@ public void postFiles(String tableId, String rowId, InMultiPart inMP, String partialPath = null; { HeaderValueParser parser = new BasicHeaderValueParser(); - HeaderElement[] values = BasicHeaderValueParser.parseElements(disposition, parser); + ParserCursor parseCursor = new ParserCursor(0, disposition.length()); + HeaderElement[] values = parser.parseElements(disposition, parseCursor); for (HeaderElement v : values) { if (v.getName().equalsIgnoreCase("file")) { partialPath = v.getParameterByName("filename").getValue(); diff --git a/src/main/java/org/opendatakit/aggregate/odktables/OdkTablesLockTemplate.java b/src/main/java/org/opendatakit/aggregate/odktables/OdkTablesLockTemplate.java index 8feede825..62b9f7c81 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/OdkTablesLockTemplate.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/OdkTablesLockTemplate.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables; -import java.util.Random; -import java.util.UUID; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.common.persistence.Datastore; @@ -27,6 +24,9 @@ import org.opendatakit.common.security.User; import org.opendatakit.common.web.CallingContext; +import java.util.Random; +import java.util.UUID; + /** * Make datastore locks a little easier. NOT threadsafe. * diff --git a/src/main/java/org/opendatakit/aggregate/odktables/TableAclManager.java b/src/main/java/org/opendatakit/aggregate/odktables/TableAclManager.java index 1a9295091..a9454b1f3 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/TableAclManager.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/TableAclManager.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables; -import java.util.ArrayList; -import java.util.List; - import org.apache.commons.lang3.Validate; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; import org.opendatakit.aggregate.odktables.relation.DbTableAcl; @@ -39,6 +36,9 @@ import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.List; + /** * Manages retrieving and setting access control lists on a table. * @@ -93,7 +93,7 @@ public TableAclManager(String appId, String tableId, TablesUserPermissions userP ODKDatastoreException { Validate.notEmpty(appId); Validate.notEmpty(tableId); - Validate.notNull(cc); + Validate.notNull(cc, "cc is null"); this.cc = cc; this.appId = appId; @@ -158,7 +158,7 @@ public WebsafeAcls getAcls(QueryResumePoint startCursor, int fetchLimit) throws * @throws PermissionDeniedException */ public WebsafeAcls getAcls(Scope.Type type, QueryResumePoint startCursor, int fetchLimit) throws ODKDatastoreException, PermissionDeniedException { - Validate.notNull(type); + Validate.notNull(type, "type is null"); userPermissions.checkPermission(appId, tableId, TablePermission.READ_ACL); WebsafeQueryResult result = DbTableAcl.queryTableIdScopeTypeAcls(tableId, type.name(), startCursor, fetchLimit, cc); @@ -184,8 +184,8 @@ public WebsafeAcls getAcls(Scope.Type type, QueryResumePoint startCursor, int fe * @throws PermissionDeniedException */ public TableAcl getAcl(Scope scope) throws ODKDatastoreException, PermissionDeniedException { - Validate.notNull(scope); - Validate.notNull(scope.getType()); + Validate.notNull(scope, "scope is null"); + Validate.notNull(scope.getType(), "scope type is null"); userPermissions.checkPermission(appId, tableId, TablePermission.READ_ACL); DbTableAclEntity aclEntity = DbTableAcl.queryTableIdScopeTypeValueAcl(tableId, scope.getType() @@ -205,8 +205,8 @@ public TableAcl getAcl(Scope scope) throws ODKDatastoreException, PermissionDeni * @throws ODKDatastoreException */ public TableAcl getAclForTablesUserPermissions(Scope scope) throws ODKDatastoreException { - Validate.notNull(scope); - Validate.notNull(scope.getType()); + Validate.notNull(scope, "scope is null"); + Validate.notNull(scope.getType(),"scope type is null"); DbTableAclEntity aclEntity = DbTableAcl.queryTableIdScopeTypeValueAcl(tableId, scope.getType() .name(), scope.getValue(), cc); @@ -229,9 +229,9 @@ public TableAcl getAclForTablesUserPermissions(Scope scope) throws ODKDatastoreE * @throws PermissionDeniedException */ public TableAcl setAcl(Scope scope, TableRole role) throws ODKDatastoreException, PermissionDeniedException { - Validate.notNull(scope); - Validate.notNull(scope.getType()); - Validate.notNull(role); + Validate.notNull(scope, "scope is null"); + Validate.notNull(scope.getType(), "scope type is null"); + Validate.notNull(role, "role is null"); userPermissions.checkPermission(appId, tableId, TablePermission.WRITE_ACL); DbTableAclEntity acl = DbTableAcl.queryTableIdScopeTypeValueAcl(tableId, @@ -255,8 +255,8 @@ public TableAcl setAcl(Scope scope, TableRole role) throws ODKDatastoreException * @throws PermissionDeniedException */ public void deleteAcl(Scope scope) throws ODKDatastoreException, PermissionDeniedException { - Validate.notNull(scope); - Validate.notNull(scope.getType()); + Validate.notNull(scope, "scope is null"); + Validate.notNull(scope.getType(), "scope type is null"); userPermissions.checkPermission(appId, tableId, TablePermission.DELETE_ACL); DbTableAclEntity acl = DbTableAcl.queryTableIdScopeTypeValueAcl(tableId, diff --git a/src/main/java/org/opendatakit/aggregate/odktables/TableManager.java b/src/main/java/org/opendatakit/aggregate/odktables/TableManager.java index ea2318c21..c6eba82a4 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/TableManager.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/TableManager.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables; -import java.util.ArrayList; -import java.util.List; - import org.apache.commons.lang3.Validate; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; import org.opendatakit.aggregate.odktables.exception.TableAlreadyExistsException; @@ -65,6 +62,9 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.constants.BasicConsts; +import java.util.ArrayList; +import java.util.List; + /** * Manages creating, deleting, and getting tables. * @@ -196,7 +196,7 @@ public TableEntry getTable(String tableId) throws ODKDatastoreException, PermissionDeniedException { userPermissions.checkPermission(appId, tableId, TablePermission.READ_TABLE_ENTRY); - Validate.notNull(tableId); + Validate.notNull(tableId, "tableId cannot be null"); Validate.notEmpty(tableId); // get table entry @@ -273,7 +273,7 @@ public TableDefinition getTableDefinition(String tableId) throws ODKDatastoreExc */ public TableEntry getTableNullSafe(String tableId) throws ODKEntityNotFoundException, ODKDatastoreException, PermissionDeniedException { - Validate.notNull(tableId); + Validate.notNull(tableId, "tableId cannot be null"); Validate.notEmpty(tableId); userPermissions.checkPermission(appId, tableId, TablePermission.READ_TABLE_ENTRY); // get table entry entity @@ -305,7 +305,7 @@ public TableEntry getTableNullSafe(String tableId) throws ODKEntityNotFoundExcep public TableEntry createTable(String tableId, List columns) throws ODKEntityPersistException, ODKDatastoreException, TableAlreadyExistsException, PermissionDeniedException, ODKTaskLockException { - Validate.notNull(tableId); + Validate.notNull(tableId, "tableId cannot be null"); Validate.notEmpty(tableId); Validate.noNullElements(columns); @@ -632,7 +632,7 @@ public static void deleteVersionedTable(DbTableEntryEntity tableEntry, boolean d */ public void deleteTable(String tableId) throws ODKEntityNotFoundException, ODKDatastoreException, ODKTaskLockException, PermissionDeniedException { - Validate.notNull(tableId); + Validate.notNull(tableId, "tableId cannot be null"); Validate.notEmpty(tableId); userPermissions.checkPermission(appId, tableId, TablePermission.DELETE_TABLE); diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/DataService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/DataService.java index 0a07d86cd..67cc9a371 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/DataService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/DataService.java @@ -16,16 +16,6 @@ package org.opendatakit.aggregate.odktables.api; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - import org.opendatakit.aggregate.odktables.exception.BadColumnNameException; import org.opendatakit.aggregate.odktables.exception.InconsistentStateException; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; @@ -38,6 +28,16 @@ import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKTaskLockException; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + public interface DataService { public static final String QUERY_ROW_ETAG = "row_etag"; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/DiffService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/DiffService.java index a2af7c8f2..1a7ed985e 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/DiffService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/DiffService.java @@ -16,14 +16,6 @@ package org.opendatakit.aggregate.odktables.api; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - import org.opendatakit.aggregate.odktables.exception.BadColumnNameException; import org.opendatakit.aggregate.odktables.exception.InconsistentStateException; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; @@ -32,6 +24,14 @@ import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKTaskLockException; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + public interface DiffService { public static final String QUERY_ACTIVE_ONLY = "active_only"; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/FileManifestService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/FileManifestService.java index d88980ba1..7057f79b3 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/FileManifestService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/FileManifestService.java @@ -15,6 +15,14 @@ */ package org.opendatakit.aggregate.odktables.api; +import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import org.opendatakit.aggregate.odktables.rest.entity.OdkTablesFileManifest; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; +import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; +import org.opendatakit.common.persistence.exception.ODKOverQuotaException; +import org.opendatakit.common.persistence.exception.ODKTaskLockException; + import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -24,14 +32,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; -import org.opendatakit.aggregate.odktables.rest.ApiConstants; -import org.opendatakit.aggregate.odktables.rest.entity.OdkTablesFileManifest; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; -import org.opendatakit.common.persistence.exception.ODKOverQuotaException; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; - /** * Servlet for downloading a manifest of files to the phone for the correct app * and the correct table. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/FileService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/FileService.java index a8d987e33..a05ea5da6 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/FileService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/FileService.java @@ -15,8 +15,12 @@ */ package org.opendatakit.aggregate.odktables.api; -import java.io.IOException; -import java.util.List; +import org.opendatakit.aggregate.odktables.exception.FileNotFoundException; +import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; +import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; +import org.opendatakit.common.persistence.exception.ODKOverQuotaException; +import org.opendatakit.common.persistence.exception.ODKTaskLockException; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -30,13 +34,8 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.Response; - -import org.opendatakit.aggregate.odktables.exception.FileNotFoundException; -import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; -import org.opendatakit.common.persistence.exception.ODKOverQuotaException; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; +import java.io.IOException; +import java.util.List; /** * Servlet for handling the uploading and downloading of files from the phone. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/InstanceFileService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/InstanceFileService.java index 23ed2a75f..6659e303a 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/InstanceFileService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/InstanceFileService.java @@ -15,8 +15,13 @@ */ package org.opendatakit.aggregate.odktables.api; -import java.io.IOException; -import java.util.List; +import org.apache.wink.common.model.multipart.InMultiPart; +import org.opendatakit.aggregate.odktables.exception.ODKTablesException; +import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import org.opendatakit.aggregate.odktables.rest.entity.OdkTablesFileManifest; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; +import org.opendatakit.common.persistence.exception.ODKTaskLockException; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; @@ -31,14 +36,8 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.Response; - -import org.apache.wink.common.model.multipart.InMultiPart; -import org.opendatakit.aggregate.odktables.exception.ODKTablesException; -import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; -import org.opendatakit.aggregate.odktables.rest.ApiConstants; -import org.opendatakit.aggregate.odktables.rest.entity.OdkTablesFileManifest; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; +import java.io.IOException; +import java.util.List; /** * Servlet for handling the uploading and downloading of instance data files diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/OdkTables.java b/src/main/java/org/opendatakit/aggregate/odktables/api/OdkTables.java index aed3bc9ee..7abaf4776 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/OdkTables.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/OdkTables.java @@ -1,5 +1,14 @@ package org.opendatakit.aggregate.odktables.api; +import org.opendatakit.aggregate.odktables.exception.AppNameMismatchException; +import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; +import org.opendatakit.aggregate.odktables.impl.api.FileManifestServiceImpl; +import org.opendatakit.aggregate.odktables.impl.api.FileServiceImpl; +import org.opendatakit.aggregate.odktables.impl.api.TableServiceImpl; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; +import org.opendatakit.common.persistence.exception.ODKTaskLockException; + import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; @@ -15,15 +24,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import org.opendatakit.aggregate.odktables.exception.AppNameMismatchException; -import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; -import org.opendatakit.aggregate.odktables.impl.api.FileManifestServiceImpl; -import org.opendatakit.aggregate.odktables.impl.api.FileServiceImpl; -import org.opendatakit.aggregate.odktables.impl.api.TableServiceImpl; -import org.opendatakit.aggregate.odktables.rest.ApiConstants; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; - public interface OdkTables { public static final String CURSOR_PARAMETER = "cursor"; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/QueryService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/QueryService.java index 765260e6f..e89dec6d5 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/QueryService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/QueryService.java @@ -16,15 +16,6 @@ package org.opendatakit.aggregate.odktables.api; -import java.text.ParseException; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - import org.opendatakit.aggregate.odktables.exception.BadColumnNameException; import org.opendatakit.aggregate.odktables.exception.InconsistentStateException; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; @@ -33,6 +24,14 @@ import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKTaskLockException; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.text.ParseException; + public interface QueryService { public static final String QUERY_DATA_ETAG = "data_etag"; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/RealizedTableService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/RealizedTableService.java index d146a6084..4dab77fc1 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/RealizedTableService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/RealizedTableService.java @@ -16,6 +16,15 @@ package org.opendatakit.aggregate.odktables.api; +import org.opendatakit.aggregate.odktables.exception.AppNameMismatchException; +import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; +import org.opendatakit.aggregate.odktables.exception.SchemaETagMismatchException; +import org.opendatakit.aggregate.odktables.exception.TableNotFoundException; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import org.opendatakit.aggregate.odktables.rest.entity.TableDefinitionResource; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; +import org.opendatakit.common.persistence.exception.ODKTaskLockException; + import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -26,15 +35,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.opendatakit.aggregate.odktables.exception.AppNameMismatchException; -import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; -import org.opendatakit.aggregate.odktables.exception.SchemaETagMismatchException; -import org.opendatakit.aggregate.odktables.exception.TableNotFoundException; -import org.opendatakit.aggregate.odktables.rest.ApiConstants; -import org.opendatakit.aggregate.odktables.rest.entity.TableDefinitionResource; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; - /** * Realized tables are identified by the tuple (appId, tableId, schemaETag) * Whenever a table is dropped and recreated, the new table has a new, diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/TableAclService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/TableAclService.java index 52f9e2eb8..d49607d59 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/TableAclService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/TableAclService.java @@ -16,6 +16,13 @@ package org.opendatakit.aggregate.odktables.api; +import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import org.opendatakit.aggregate.odktables.rest.entity.TableAcl; +import org.opendatakit.aggregate.odktables.rest.entity.TableAclResource; +import org.opendatakit.aggregate.odktables.rest.entity.TableAclResourceList; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; + import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -27,13 +34,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; -import org.opendatakit.aggregate.odktables.rest.ApiConstants; -import org.opendatakit.aggregate.odktables.rest.entity.TableAcl; -import org.opendatakit.aggregate.odktables.rest.entity.TableAclResource; -import org.opendatakit.aggregate.odktables.rest.entity.TableAclResourceList; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; - public interface TableAclService { public static final String CURSOR_PARAMETER = "cursor"; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/api/TableService.java b/src/main/java/org/opendatakit/aggregate/odktables/api/TableService.java index f9d948b19..10ae7dfd5 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/api/TableService.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/api/TableService.java @@ -16,20 +16,6 @@ package org.opendatakit.aggregate.odktables.api; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Map; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - import org.opendatakit.aggregate.odktables.exception.AppNameMismatchException; import org.opendatakit.aggregate.odktables.exception.FileNotFoundException; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; @@ -44,6 +30,19 @@ import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKTaskLockException; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Map; + public interface TableService { public static final String CURSOR_PARAMETER = "cursor"; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/NotModifiedHandler.java b/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/NotModifiedHandler.java index 3340fd86f..041ee5b88 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/NotModifiedHandler.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/NotModifiedHandler.java @@ -1,5 +1,16 @@ package org.opendatakit.aggregate.odktables.entity.serialization; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.wink.server.handlers.HandlersChain; +import org.apache.wink.server.handlers.MessageContext; +import org.apache.wink.server.handlers.ResponseHandler; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.math.BigInteger; @@ -9,19 +20,6 @@ import java.util.List; import java.util.Properties; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; - -import org.apache.http.HttpStatus; -import org.apache.wink.server.handlers.HandlersChain; -import org.apache.wink.server.handlers.MessageContext; -import org.apache.wink.server.handlers.ResponseHandler; -import org.opendatakit.aggregate.odktables.rest.ApiConstants; - -import com.fasterxml.jackson.databind.ObjectMapper; - public class NotModifiedHandler implements ResponseHandler { public static final String jsonBufferKey = NotModifiedHandler.class.getCanonicalName() diff --git a/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleHTMLMessageWriter.java b/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleHTMLMessageWriter.java index d62d88544..37c5177f5 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleHTMLMessageWriter.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleHTMLMessageWriter.java @@ -16,13 +16,8 @@ package org.opendatakit.aggregate.odktables.entity.serialization; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.nio.charset.Charset; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; @@ -30,10 +25,13 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; - -import org.opendatakit.aggregate.odktables.rest.ApiConstants; - -import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.charset.Charset; @Produces({ "text/*" }) @Provider diff --git a/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleJSONMessageReaderWriter.java b/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleJSONMessageReaderWriter.java index f6e40780c..8091f40dc 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleJSONMessageReaderWriter.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleJSONMessageReaderWriter.java @@ -16,15 +16,8 @@ package org.opendatakit.aggregate.odktables.entity.serialization; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.nio.charset.Charset; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; import javax.servlet.ServletContext; import javax.ws.rs.Consumes; @@ -36,10 +29,15 @@ import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; - -import org.opendatakit.aggregate.odktables.rest.ApiConstants; - -import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.charset.Charset; @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) diff --git a/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleXMLMessageReaderWriter.java b/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleXMLMessageReaderWriter.java index e12f7b6f6..c4745db35 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleXMLMessageReaderWriter.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/entity/serialization/SimpleXMLMessageReaderWriter.java @@ -16,15 +16,8 @@ package org.opendatakit.aggregate.odktables.entity.serialization; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.nio.charset.Charset; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; @@ -34,10 +27,15 @@ import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; - -import org.opendatakit.aggregate.odktables.rest.ApiConstants; - -import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.charset.Charset; @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML }) @Consumes({ MediaType.TEXT_XML, MediaType.APPLICATION_XML }) diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/DataServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/DataServiceImpl.java index 850967c34..ee6f75d7f 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/DataServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/DataServiceImpl.java @@ -16,17 +16,6 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.net.MalformedURLException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.opendatakit.aggregate.odktables.DataManager; import org.opendatakit.aggregate.odktables.DataManager.WebsafeRows; import org.opendatakit.aggregate.odktables.api.DataService; @@ -51,6 +40,16 @@ import org.opendatakit.common.utils.WebUtils; import org.opendatakit.common.web.CallingContext; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + public class DataServiceImpl implements DataService { private final String schemaETag; private final DataManager dm; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/DiffServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/DiffServiceImpl.java index c9f2b0e6e..ad5960c2e 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/DiffServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/DiffServiceImpl.java @@ -16,16 +16,6 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.net.MalformedURLException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.opendatakit.aggregate.odktables.DataManager; import org.opendatakit.aggregate.odktables.DataManager.WebsafeRows; import org.opendatakit.aggregate.odktables.api.DataService; @@ -49,6 +39,15 @@ import org.opendatakit.common.utils.WebUtils; import org.opendatakit.common.web.CallingContext; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + public class DiffServiceImpl implements DiffService { private final String schemaETag; private final DataManager dm; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/FileManifestServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/FileManifestServiceImpl.java index bcc87e089..3c8201f87 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/FileManifestServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/FileManifestServiceImpl.java @@ -15,17 +15,6 @@ */ package org.opendatakit.aggregate.odktables.impl.api; -import java.net.MalformedURLException; -import java.net.URI; -import java.util.List; - -import javax.ws.rs.PathParam; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.ContextFactory; @@ -46,6 +35,16 @@ import org.opendatakit.common.persistence.exception.ODKTaskLockException; import org.opendatakit.common.web.CallingContext; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.List; + /** * The implementation of the file manifest service. Handles the actual requests * and spits back out the manifests. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/FileServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/FileServiceImpl.java index 4cbb3f31b..5b89a81a3 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/FileServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/FileServiceImpl.java @@ -15,24 +15,6 @@ */ package org.opendatakit.aggregate.odktables.impl.api; -import java.io.IOException; -import java.net.URI; -import java.util.List; -import java.util.TreeSet; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.PathSegment; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.ContextFactory; import org.opendatakit.aggregate.odktables.ConfigFileChangeDetail; @@ -56,6 +38,23 @@ import org.opendatakit.common.web.constants.BasicConsts; import org.opendatakit.common.web.constants.HtmlConsts; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.PathSegment; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.TreeSet; + public class FileServiceImpl implements FileService { private final ServletContext sc; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionApplicationXmlMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionApplicationXmlMapper.java index 47fac1f49..2c37d3ae2 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionApplicationXmlMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionApplicationXmlMapper.java @@ -16,13 +16,12 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.io.IOException; - import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; +import java.io.IOException; @Produces({ MediaType.APPLICATION_XML }) @Provider diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionJsonMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionJsonMapper.java index 8ecea6d84..510228a77 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionJsonMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionJsonMapper.java @@ -16,13 +16,12 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.io.IOException; - import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; +import java.io.IOException; @Produces({ MediaType.APPLICATION_JSON }) @Provider diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionMapper.java index 1ef20d352..6149726ae 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionMapper.java @@ -16,16 +16,15 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.io.IOException; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import org.opendatakit.aggregate.odktables.rest.entity.Error; +import org.opendatakit.aggregate.odktables.rest.entity.Error.ErrorType; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.ExceptionMapper; - -import org.opendatakit.aggregate.odktables.rest.ApiConstants; -import org.opendatakit.aggregate.odktables.rest.entity.Error; -import org.opendatakit.aggregate.odktables.rest.entity.Error.ErrorType; +import java.io.IOException; public class IOExceptionMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionTextXmlMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionTextXmlMapper.java index d57eb734a..1fce9ed5b 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionTextXmlMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/IOExceptionTextXmlMapper.java @@ -16,13 +16,12 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.io.IOException; - import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; +import java.io.IOException; @Produces({ MediaType.TEXT_XML }) @Provider diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/InstanceFileServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/InstanceFileServiceImpl.java index 8a9360291..0dcb0c45d 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/InstanceFileServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/InstanceFileServiceImpl.java @@ -15,26 +15,6 @@ */ package org.opendatakit.aggregate.odktables.impl.api; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.PathSegment; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.wink.common.model.multipart.BufferedOutMultiPart; @@ -65,6 +45,25 @@ import org.opendatakit.common.web.constants.BasicConsts; import org.opendatakit.common.web.constants.HtmlConsts; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.PathSegment; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; + public class InstanceFileServiceImpl implements InstanceFileService { /** diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionApplicationXmlMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionApplicationXmlMapper.java index 7f9506292..371a692ec 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionApplicationXmlMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionApplicationXmlMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; - @Produces({ MediaType.APPLICATION_XML }) @Provider public class ODKDatastoreExceptionApplicationXmlMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionJsonMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionJsonMapper.java index 773d09aa0..0e62ace05 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionJsonMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionJsonMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; - @Produces({ MediaType.APPLICATION_JSON }) @Provider public class ODKDatastoreExceptionJsonMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionMapper.java index b4020152e..ae41033c4 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionMapper.java @@ -16,11 +16,6 @@ package org.opendatakit.aggregate.odktables.impl.api; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.ext.ExceptionMapper; - import org.opendatakit.aggregate.odktables.rest.ApiConstants; import org.opendatakit.aggregate.odktables.rest.entity.Error; import org.opendatakit.aggregate.odktables.rest.entity.Error.ErrorType; @@ -29,6 +24,11 @@ import org.opendatakit.common.persistence.exception.ODKEntityPersistException; import org.opendatakit.common.persistence.exception.ODKOverQuotaException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; + public class ODKDatastoreExceptionMapper implements ExceptionMapper { private final MediaType type; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionTextXmlMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionTextXmlMapper.java index 92325eb18..b777f42b0 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionTextXmlMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKDatastoreExceptionTextXmlMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; - @Produces({ MediaType.TEXT_XML }) @Provider public class ODKDatastoreExceptionTextXmlMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesAPIApplication.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesAPIApplication.java index 61077df63..88728e5a1 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesAPIApplication.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesAPIApplication.java @@ -16,11 +16,6 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.util.HashSet; -import java.util.Set; - -import javax.ws.rs.core.Application; - import org.apache.wink.common.internal.providers.entity.ByteArrayProvider; import org.apache.wink.common.internal.providers.entity.FileProvider; import org.apache.wink.common.internal.providers.multipart.BufferedInMultiPartProvider; @@ -29,6 +24,10 @@ import org.opendatakit.aggregate.odktables.entity.serialization.SimpleJSONMessageReaderWriter; import org.opendatakit.aggregate.odktables.entity.serialization.SimpleXMLMessageReaderWriter; +import javax.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Set; + public class ODKTablesAPIApplication extends Application { @Override diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionApplicationXmlMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionApplicationXmlMapper.java index a0bd4d0fd..4ecb99a36 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionApplicationXmlMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionApplicationXmlMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.aggregate.odktables.exception.ODKTablesException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.aggregate.odktables.exception.ODKTablesException; - @Produces({ MediaType.APPLICATION_XML }) @Provider public class ODKTablesExceptionApplicationXmlMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionJsonMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionJsonMapper.java index 04573222d..149f142e9 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionJsonMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionJsonMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.aggregate.odktables.exception.ODKTablesException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.aggregate.odktables.exception.ODKTablesException; - @Produces({ MediaType.APPLICATION_JSON }) @Provider public class ODKTablesExceptionJsonMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionMapper.java index b20e26c58..223c286a7 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionMapper.java @@ -16,12 +16,6 @@ package org.opendatakit.aggregate.odktables.impl.api; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.ext.ExceptionMapper; - import org.opendatakit.aggregate.odktables.exception.AppNameMismatchException; import org.opendatakit.aggregate.odktables.exception.BadColumnNameException; import org.opendatakit.aggregate.odktables.exception.ETagMismatchException; @@ -39,6 +33,12 @@ import org.opendatakit.aggregate.odktables.rest.entity.Error; import org.opendatakit.aggregate.odktables.rest.entity.Error.ErrorType; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; + public class ODKTablesExceptionMapper implements ExceptionMapper { MediaType type; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionTextXmlMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionTextXmlMapper.java index 7f7ba0825..d3ac5f087 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionTextXmlMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTablesExceptionTextXmlMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.aggregate.odktables.exception.ODKTablesException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.aggregate.odktables.exception.ODKTablesException; - @Produces({ MediaType.TEXT_XML }) @Provider public class ODKTablesExceptionTextXmlMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionApplicationXmlMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionApplicationXmlMapper.java index d9918d65e..7d27880fd 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionApplicationXmlMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionApplicationXmlMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.common.persistence.exception.ODKTaskLockException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; - @Produces({ MediaType.APPLICATION_XML }) @Provider public class ODKTaskLockExceptionApplicationXmlMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionJsonMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionJsonMapper.java index 686419929..adfc2d8da 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionJsonMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionJsonMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.common.persistence.exception.ODKTaskLockException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; - @Produces({ MediaType.APPLICATION_JSON }) @Provider public class ODKTaskLockExceptionJsonMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionMapper.java index dd93b96c0..e45be2a85 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionMapper.java @@ -16,16 +16,16 @@ package org.opendatakit.aggregate.odktables.impl.api; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.ext.ExceptionMapper; - import org.opendatakit.aggregate.odktables.rest.ApiConstants; import org.opendatakit.aggregate.odktables.rest.entity.Error; import org.opendatakit.aggregate.odktables.rest.entity.Error.ErrorType; import org.opendatakit.common.persistence.exception.ODKTaskLockException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; + public class ODKTaskLockExceptionMapper implements ExceptionMapper { private final MediaType type; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionTextXmlMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionTextXmlMapper.java index 8bb9be4da..79b4eb8ec 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionTextXmlMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ODKTaskLockExceptionTextXmlMapper.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.common.persistence.exception.ODKTaskLockException; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; - @Produces({ MediaType.TEXT_XML }) @Provider public class ODKTaskLockExceptionTextXmlMapper implements ExceptionMapper { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/OdkTablesImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/OdkTablesImpl.java index 67c554bbd..bb059897e 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/OdkTablesImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/OdkTablesImpl.java @@ -1,21 +1,6 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.ContextFactory; @@ -39,7 +24,20 @@ import org.opendatakit.common.security.server.SecurityServiceUtil; import org.opendatakit.common.web.CallingContext; -import com.fasterxml.jackson.databind.ObjectMapper; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; @Path("") public class OdkTablesImpl implements OdkTables { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/QueryServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/QueryServiceImpl.java index aa85f50e0..a32c99fef 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/QueryServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/QueryServiceImpl.java @@ -16,17 +16,6 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.net.MalformedURLException; -import java.net.URI; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.opendatakit.aggregate.odktables.DataManager; import org.opendatakit.aggregate.odktables.DataManager.WebsafeRows; import org.opendatakit.aggregate.odktables.api.DataService; @@ -49,6 +38,16 @@ import org.opendatakit.common.utils.WebUtils; import org.opendatakit.common.web.CallingContext; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.net.MalformedURLException; +import java.net.URI; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + public class QueryServiceImpl implements QueryService { private final String schemaETag; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/RealizedTableServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/RealizedTableServiceImpl.java index 97c0e9dd1..c0e20911a 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/RealizedTableServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/RealizedTableServiceImpl.java @@ -16,18 +16,7 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.net.MalformedURLException; -import java.net.URI; -import java.util.TreeSet; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.PathParam; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.odktables.TableManager; @@ -54,7 +43,16 @@ import org.opendatakit.common.security.server.SecurityServiceUtil; import org.opendatakit.common.web.CallingContext; -import com.fasterxml.jackson.databind.ObjectMapper; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.TreeSet; public class RealizedTableServiceImpl implements RealizedTableService { private static final Log logger = LogFactory.getLog(RealizedTableServiceImpl.class); diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/RuntimeExceptionMapper.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/RuntimeExceptionMapper.java index d11d1049a..8fada6f07 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/RuntimeExceptionMapper.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/RuntimeExceptionMapper.java @@ -16,15 +16,15 @@ package org.opendatakit.aggregate.odktables.impl.api; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import org.opendatakit.aggregate.odktables.rest.entity.Error; +import org.opendatakit.aggregate.odktables.rest.entity.Error.ErrorType; + import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.ExceptionMapper; -import org.opendatakit.aggregate.odktables.rest.ApiConstants; -import org.opendatakit.aggregate.odktables.rest.entity.Error; -import org.opendatakit.aggregate.odktables.rest.entity.Error.ErrorType; - public class RuntimeExceptionMapper implements ExceptionMapper { private final MediaType type; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ServiceUtils.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ServiceUtils.java index f5c1ed299..2fcda101e 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ServiceUtils.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/ServiceUtils.java @@ -15,16 +15,15 @@ */ package org.opendatakit.aggregate.odktables.impl.api; -import java.util.Enumeration; -import java.util.List; +import org.opendatakit.aggregate.odktables.rest.ApiConstants; import javax.servlet.ServletContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MultivaluedMap; - -import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import java.util.Enumeration; +import java.util.List; /** * Class to extract and format the request information coming in from ODK Tables diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/TableAclServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/TableAclServiceImpl.java index 3b14acc6b..99e14c16f 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/TableAclServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/TableAclServiceImpl.java @@ -16,17 +16,6 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.net.MalformedURLException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.TreeSet; - -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.opendatakit.aggregate.odktables.TableAclManager; import org.opendatakit.aggregate.odktables.TableAclManager.WebsafeAcls; import org.opendatakit.aggregate.odktables.api.OdkTables; @@ -47,6 +36,16 @@ import org.opendatakit.common.utils.WebUtils; import org.opendatakit.common.web.CallingContext; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + public class TableAclServiceImpl implements TableAclService { private final TableAclManager am; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/TableServiceImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/TableServiceImpl.java index f32e15528..69482ce97 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/TableServiceImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/TableServiceImpl.java @@ -16,34 +16,10 @@ package org.opendatakit.aggregate.odktables.impl.api; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.net.MalformedURLException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeSet; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - -import com.nimbusds.jose.util.StandardCharset; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.odktables.ConfigFileChangeDetail; @@ -87,10 +63,32 @@ import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.constants.HtmlConsts; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.net.MalformedURLException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; public class TableServiceImpl implements TableService { private static final Log logger = LogFactory.getLog(TableServiceImpl.class); @@ -339,7 +337,7 @@ public Response getTableProperties(@PathParam("odkClientVersion") String odkClie RFC4180CsvReader csvReader = null; ArrayList properties = new ArrayList(); try { - rdr = new InputStreamReader(bas, StandardCharset.UTF_8); + rdr = new InputStreamReader(bas, StandardCharsets.UTF_8); csvReader = new RFC4180CsvReader(rdr); String[] entries = csvReader.readNext(); @@ -587,7 +585,7 @@ public Response putInternalTableProperties(String odkClientVersion, PropertyEntr RFC4180CsvWriter csvWtr = null; try { - wtr = new OutputStreamWriter(bas, StandardCharset.UTF_8); + wtr = new OutputStreamWriter(bas, StandardCharsets.UTF_8); csvWtr = new RFC4180CsvWriter(wtr); String[] entry = new String[5]; entry[0] = "_partition"; diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/AppEngineHandlersFactory.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/AppEngineHandlersFactory.java index 5b7459946..a01cdb3fc 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/AppEngineHandlersFactory.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/AppEngineHandlersFactory.java @@ -16,13 +16,13 @@ package org.opendatakit.aggregate.odktables.impl.api.wink; -import java.util.ArrayList; -import java.util.List; - import org.apache.wink.server.handlers.HandlersFactory; import org.apache.wink.server.handlers.ResponseHandler; import org.opendatakit.aggregate.odktables.entity.serialization.NotModifiedHandler; +import java.util.ArrayList; +import java.util.List; + public class AppEngineHandlersFactory extends HandlersFactory { public AppEngineHandlersFactory() { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/ContentEncodingResponseFilter.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/ContentEncodingResponseFilter.java index 96756d7fe..7b8ba9580 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/ContentEncodingResponseFilter.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/ContentEncodingResponseFilter.java @@ -36,13 +36,11 @@ */ package org.opendatakit.aggregate.odktables.impl.api.wink; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Enumeration; -import java.util.List; -import java.util.zip.DeflaterOutputStream; -import java.util.zip.GZIPOutputStream; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.wink.common.internal.http.AcceptEncoding; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -58,12 +56,13 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.ext.RuntimeDelegate; import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.wink.common.internal.http.AcceptEncoding; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.GZIPOutputStream; /** * Copied mostly verbatim from org.apache.wink.server.internal.servlet.contentencode diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/GaeAwareContentEncodingRequestFilter.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/GaeAwareContentEncodingRequestFilter.java deleted file mode 100644 index b82118bcd..000000000 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/GaeAwareContentEncodingRequestFilter.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.impl.api.wink; - -import java.io.IOException; - -import javax.servlet.FilterChain; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.wink.server.internal.servlet.contentencode.ContentEncodingRequestFilter; -import org.opendatakit.aggregate.ContextFactory; -import org.opendatakit.common.security.Realm; -import org.opendatakit.common.security.UserService; -import org.opendatakit.common.web.CallingContext; - -public class GaeAwareContentEncodingRequestFilter extends ContentEncodingRequestFilter { - - private static final Log logger = LogFactory.getLog(GaeAwareContentEncodingRequestFilter.class); - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain chain) throws IOException, ServletException { - - if (servletRequest instanceof HttpServletRequest) { - - HttpServletRequest req = (HttpServletRequest) servletRequest; - ServletContext sc = req.getSession().getServletContext(); - CallingContext cc = ContextFactory.getCallingContext(sc, req); - String server = sc.getServerInfo(); - - /* - * AppEngine leaves the GZIP header even though it unzips the content - * before delivering it to the app. - */ - boolean isGaeDevelopmentEnvironment = server.contains("Development"); - boolean isGaeEnvironment = false; - try { - UserService us = cc.getUserService(); - if (us != null) { - Realm realm = us.getCurrentRealm(); - if (realm != null) { - Boolean outcome = realm.getIsGaeEnvironment(); - if (outcome != null) { - isGaeEnvironment = outcome; - } - } - } - } catch (Exception e) { - // ignore... - } - - if (isGaeEnvironment && !isGaeDevelopmentEnvironment) { - // don't try to process anything -- GAE does but does not remove headers - logger.info("Gae environment -- ignoring Content-Encoding header"); - chain.doFilter(servletRequest, servletResponse); - } else { - // perhaps wrap response with GZIP - logger.info("not Gae environment -- processing Content-Encoding header"); - super.doFilter(servletRequest, servletResponse, chain); - } - } - } -} diff --git a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/GaeAwareContentEncodingResponseFilter.java b/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/GaeAwareContentEncodingResponseFilter.java deleted file mode 100644 index 263668a99..000000000 --- a/src/main/java/org/opendatakit/aggregate/odktables/impl/api/wink/GaeAwareContentEncodingResponseFilter.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2014 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.aggregate.odktables.impl.api.wink; - -import java.io.IOException; - -import javax.servlet.FilterChain; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.opendatakit.aggregate.ContextFactory; -import org.opendatakit.common.security.Realm; -import org.opendatakit.common.security.UserService; -import org.opendatakit.common.web.CallingContext; - -public class GaeAwareContentEncodingResponseFilter extends ContentEncodingResponseFilter { - - private static final Log logger = LogFactory.getLog(GaeAwareContentEncodingResponseFilter.class); - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain chain) throws IOException, ServletException { - - if (servletRequest instanceof HttpServletRequest) { - - HttpServletRequest req = (HttpServletRequest) servletRequest; - ServletContext sc = req.getSession().getServletContext(); - CallingContext cc = ContextFactory.getCallingContext(sc, req); - String server = sc.getServerInfo(); - - /* - * AppEngine leaves the GZIP header even though it unzips the content - * before delivering it to the app. - */ - boolean isGaeDevelopmentEnvironment = server.contains("Development"); - boolean isGaeEnvironment = false; - try { - UserService us = cc.getUserService(); - if (us != null) { - Realm realm = us.getCurrentRealm(); - if (realm != null) { - Boolean outcome = realm.getIsGaeEnvironment(); - if (outcome != null) { - isGaeEnvironment = outcome; - } - } - } - } catch (Exception e) { - // ignore... - } - - if (isGaeEnvironment && !isGaeDevelopmentEnvironment) { - // don't try to process anything -- GAE does but does not remove headers - logger.info("Gae environment -- ignoring Accept-Encoding header"); - chain.doFilter(servletRequest, servletResponse); - } else { - // perhaps wrap response with GZIP - logger.info("not Gae environment -- processing Accept-Encoding header"); - super.doFilter(servletRequest, servletResponse, chain); - } - } - } -} diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbColumnDefinitions.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbColumnDefinitions.java index ebfe14cdb..9fe195a06 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbColumnDefinitions.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbColumnDefinitions.java @@ -16,13 +16,10 @@ package org.opendatakit.aggregate.odktables.relation; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.opendatakit.aggregate.odktables.rest.ElementDataType; import org.opendatakit.aggregate.odktables.rest.ElementType; import org.opendatakit.common.ermodel.Entity; @@ -37,10 +34,12 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * This defines the columns in a given schemaETag storage representation of that diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbInstallationInteractionLog.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbInstallationInteractionLog.java index db734b1f9..d5018d116 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbInstallationInteractionLog.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbInstallationInteractionLog.java @@ -16,10 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - import org.opendatakit.common.ermodel.Entity; import org.opendatakit.common.ermodel.Query; import org.opendatakit.common.ermodel.Relation; @@ -31,6 +27,10 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + /** * Tracks the client installations and authenticated users that are * modifying the server configuration. Also records the client's data diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbLogTable.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbLogTable.java index 77d92c1da..6a7227a5a 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbLogTable.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbLogTable.java @@ -16,10 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.opendatakit.aggregate.odktables.relation.DbColumnDefinitions.DbColumnDefinitionsEntity; import org.opendatakit.aggregate.odktables.relation.DbTableDefinitions.DbTableDefinitionsEntity; import org.opendatakit.aggregate.odktables.rest.TableConstants; @@ -31,6 +27,10 @@ import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public class DbLogTable extends Relation { private DbLogTable(String namespace, String tableName, List fields, CallingContext cc) diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbManifestETags.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbManifestETags.java index e35ac88de..6825fb16c 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbManifestETags.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbManifestETags.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.List; - import org.opendatakit.common.ermodel.Entity; import org.opendatakit.common.ermodel.Relation; import org.opendatakit.common.persistence.DataField; @@ -29,6 +26,9 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.List; + /** * Tracks the ETags of the manifests associated with a given TableId. Appl-level manifests * have a TableId of APP_LEVEL ("APP LEVEL"); the space ensures it could never collide with diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTable.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTable.java index 38b41c6e9..9652aceda 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTable.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTable.java @@ -16,10 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.apache.commons.lang3.Validate; import org.opendatakit.aggregate.odktables.relation.DbColumnDefinitions.DbColumnDefinitionsEntity; import org.opendatakit.aggregate.odktables.relation.DbTableDefinitions.DbTableDefinitionsEntity; @@ -35,6 +31,10 @@ import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * Represents the schema for a user-defined (data, security, shortcut) table in * the database. @@ -164,9 +164,9 @@ public static List getStaticFields() { */ public static List query(DbTable table, List rowIds, CallingContext cc) throws ODKEntityNotFoundException, ODKDatastoreException { - Validate.notNull(table); + Validate.notNull(table, "table is null"); Validate.noNullElements(rowIds); - Validate.notNull(cc); + Validate.notNull(cc, "cc is null"); Query query = table.query("DbTable.query", cc); query.include(PersistConsts.URI_COLUMN_NAME, rowIds); diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableAcl.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableAcl.java index 98ff75fb1..f21a647d5 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableAcl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableAcl.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.List; - import org.opendatakit.common.ermodel.Entity; import org.opendatakit.common.ermodel.Query; import org.opendatakit.common.ermodel.Query.WebsafeQueryResult; @@ -33,6 +30,9 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.List; + /** * Unlike the other tables, this is not updated atomically through the use of * the propertiesETag. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableDefinitions.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableDefinitions.java index 61be05294..e554e3fa6 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableDefinitions.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableDefinitions.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.List; - import org.apache.commons.logging.LogFactory; import org.opendatakit.common.ermodel.Entity; import org.opendatakit.common.ermodel.Query; @@ -32,6 +29,9 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.List; + /** * This provides a concrete mapping of (tableId,schemaETag) to a database table * name. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableEntry.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableEntry.java index 4ff39c869..1b7606f27 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableEntry.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableEntry.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.List; - import org.opendatakit.common.ermodel.Entity; import org.opendatakit.common.ermodel.Query; import org.opendatakit.common.ermodel.Relation; @@ -30,6 +27,9 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.List; + /** * Tracks the ETags associated with a given TableId. The TableId is the PK for * this table. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableFileInfo.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableFileInfo.java index e15063e16..c928d0724 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableFileInfo.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableFileInfo.java @@ -16,10 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.opendatakit.aggregate.odktables.rest.TableConstants; import org.opendatakit.common.ermodel.BlobEntitySet; import org.opendatakit.common.ermodel.Entity; @@ -35,6 +31,10 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * This is the table in the database that holds information about the files that * have been uploaded to be associated with certain ODKTables tables. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableInstanceFiles.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableInstanceFiles.java index c4f58efa8..ba66081b4 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableInstanceFiles.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableInstanceFiles.java @@ -16,12 +16,12 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.Locale; - import org.opendatakit.common.ermodel.AbstractBlobRelationSet; import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.web.CallingContext; +import java.util.Locale; + /** * This represents the datastore table that holds files for the instance data * of a table. There is one of these for each table in order to simplify diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableInstanceManifestETags.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableInstanceManifestETags.java index 57fc2ceb4..18c573936 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableInstanceManifestETags.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/DbTableInstanceManifestETags.java @@ -16,10 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - import org.opendatakit.common.ermodel.Entity; import org.opendatakit.common.ermodel.Relation; import org.opendatakit.common.persistence.DataField; @@ -30,6 +26,10 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + /** * Tracks the per-row attachment manifest ETags of a row. * diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/EntityConverter.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/EntityConverter.java index a697dee30..5825cde8b 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/EntityConverter.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/EntityConverter.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.List; - import org.opendatakit.aggregate.odktables.relation.DbColumnDefinitions.DbColumnDefinitionsEntity; import org.opendatakit.aggregate.odktables.relation.DbTableAcl.DbTableAclEntity; import org.opendatakit.aggregate.odktables.relation.DbTableDefinitions.DbTableDefinitionsEntity; @@ -39,6 +36,9 @@ import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.DataField.DataType; +import java.util.ArrayList; +import java.util.List; + /** * Converts between datastore {@link Entity} objects and domain objects in * org.opendatakit.aggregate.odktables.entity. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/relation/EntityCreator.java b/src/main/java/org/opendatakit/aggregate/odktables/relation/EntityCreator.java index a4bfd30a4..1ae597dd2 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/relation/EntityCreator.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/relation/EntityCreator.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.odktables.relation; -import java.util.ArrayList; -import java.util.List; - import org.apache.commons.lang3.Validate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -40,6 +37,9 @@ import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.List; + /** * Creates and updates new Entity objects for relations. *

@@ -76,10 +76,10 @@ public class EntityCreator { */ public DbTableEntryEntity newTableEntryEntity(String tableId, String pendingSchemaETag, String aprioriDataSequenceValue, CallingContext cc) throws ODKDatastoreException { - Validate.notNull(cc); - Validate.notNull(tableId); - Validate.notNull(pendingSchemaETag); - Validate.notNull(aprioriDataSequenceValue); + Validate.notNull(cc, "cc cannot be null"); + Validate.notNull(tableId, "tableId cannot be null"); + Validate.notNull(pendingSchemaETag, "pendingSchemaETag cannot be null"); + Validate.notNull(aprioriDataSequenceValue, "aprioriDataSequenceValue cannot be null"); DbTableEntryEntity entity = DbTableEntry.createNewEntity(tableId, cc); entity.setPendingSchemaETag(pendingSchemaETag); @@ -102,8 +102,8 @@ public DbColumnDefinitionsEntity newColumnEntity(String tableId, String schemaET Column column, CallingContext cc) throws ODKDatastoreException { Validate.notEmpty(tableId); Validate.notEmpty(schemaETag); - Validate.notNull(column); - Validate.notNull(cc); + Validate.notNull(column, "column cannot be null"); + Validate.notNull(cc, "cc cannot be null"); DbColumnDefinitionsEntity entity = DbColumnDefinitions.createNewEntity(cc); entity.setTableId(tableId); @@ -165,7 +165,7 @@ public DbTableDefinitionsEntity newTableDefinitionEntity(String tableId, String Validate.notEmpty(tableId); Validate.notEmpty(schemaETag); Validate.notEmpty(dbTableName); - Validate.notNull(cc); + Validate.notNull(cc, "cc cannot be null"); DbTableDefinitionsEntity definition = DbTableDefinitions.createNewEntity(cc); definition.setTableId(tableId); definition.setSchemaETag(schemaETag); @@ -189,11 +189,11 @@ public DbTableDefinitionsEntity newTableDefinitionEntity(String tableId, String public DbTableAclEntity newTableAclEntity(String tableId, Scope scope, TableRole role, CallingContext cc) throws ODKDatastoreException { Validate.notEmpty(tableId); - Validate.notNull(scope); + Validate.notNull(scope, "scope cannot be null"); // can't have an empty scope type in an acl entity - Validate.notNull(scope.getType()); - Validate.notNull(role); - Validate.notNull(cc); + Validate.notNull(scope.getType(), "scope type cannot be null"); + Validate.notNull(role, "role cannot be null"); + Validate.notNull(cc, "cc cannot be null"); DbTableAclEntity tableAcl = DbTableAcl.createNewEntity(cc); tableAcl.setTableId(tableId); @@ -303,11 +303,11 @@ public Entity newLogEntity(DbLogTable logTable, String dataETagAtModification, String previousRowETag, Entity row, List columns, Sequencer sequencer, CallingContext cc) throws ODKDatastoreException { - Validate.notNull(logTable); + Validate.notNull(logTable, "logTable cannot be null"); Validate.notEmpty(dataETagAtModification); - Validate.notNull(row); + Validate.notNull(row, "row cannot be null"); Validate.noNullElements(columns); - Validate.notNull(cc); + Validate.notNull(cc, "cc cannot be null"); Entity entity = logTable.newEntity(row.getString(DbTable.ROW_ETAG), cc); entity.set(DbLogTable.ROW_ID, row.getId()); diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/RFC4180CsvReader.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/RFC4180CsvReader.java index db8cd25ee..78cde6583 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/RFC4180CsvReader.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/RFC4180CsvReader.java @@ -63,12 +63,6 @@ enum ParseState { * * @param reader * the reader to an underlying CSV source. - * @param separator - * the delimiter to use for separating entries - * @param quotechar - * the character to use for quoted elements - * @param escape - * the character to use for escaping a separator or quote */ public RFC4180CsvReader(Reader reader) { @@ -270,11 +264,11 @@ public String[] readNext() throws IOException { // Excel for Mac silliness br.reset(); } - b.append((char) cr); - b.append((char) lf); + b.append(cr); + b.append(lf); } else if ( ch == lf ) { - b.append((char) cr); - b.append((char) lf); + b.append(cr); + b.append(lf); } else { b.append((char) ch); } diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/TableConstants.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/TableConstants.java index 3e8a39e33..17a511ec2 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/TableConstants.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/TableConstants.java @@ -18,7 +18,13 @@ import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.SimpleTimeZone; /** * Contains various things that are constant in tables and must be known and diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/AppNameList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/AppNameList.java index 584600129..704e4d410 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/AppNameList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/AppNameList.java @@ -16,11 +16,11 @@ package org.opendatakit.aggregate.odktables.rest.entity; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + import java.util.ArrayList; import java.util.List; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; - /** * This holds a list of appNames. * diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/ChangeSetList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/ChangeSetList.java index 5536857ab..f28a7d61b 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/ChangeSetList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/ChangeSetList.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; -import java.util.Collections; - import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.Collections; + /** * This holds a list of dataETag (changeSet) values. * It also supplies a sequenceValue that can be used diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/ClientVersionList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/ClientVersionList.java index 8e5c6e429..a857b277b 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/ClientVersionList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/ClientVersionList.java @@ -16,11 +16,11 @@ package org.opendatakit.aggregate.odktables.rest.entity; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + import java.util.ArrayList; import java.util.List; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; - /** * This holds the list of odkClientVersion values available on the server. * diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Column.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Column.java index ac7b7f0e8..4399fcc42 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Column.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Column.java @@ -16,10 +16,10 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.io.Serializable; - import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + /** * The XML document that represents a column. This is the XML representation of * a column definition as stored in the (keep this fully qualified!) diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/OdkTablesFileManifest.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/OdkTablesFileManifest.java index 3def8e748..c441958d6 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/OdkTablesFileManifest.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/OdkTablesFileManifest.java @@ -16,13 +16,13 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; -import java.util.Collections; - import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.Collections; + /** * This holds a list of {@link OdkTablesFileManifestEntry}. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/PrivilegesInfo.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/PrivilegesInfo.java index 7d6d82252..aac1a8486 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/PrivilegesInfo.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/PrivilegesInfo.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; -import java.util.Collections; - import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.Collections; + /** * This contains the default group of the user and the list of * groups and roles to which the currently authenticated user is diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/PropertyEntryXmlList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/PropertyEntryXmlList.java index d17d2acbb..e0a519967 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/PropertyEntryXmlList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/PropertyEntryXmlList.java @@ -16,15 +16,15 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; -import java.util.Collections; - import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.Collections; + /** * This holds a list of {@link PropertyEntryXml}. * Proper XML documents can contain only one root node. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Row.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Row.java index 228cd2e7f..54b7df530 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Row.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/Row.java @@ -16,6 +16,11 @@ package org.opendatakit.aggregate.odktables.rest.entity; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -23,11 +28,6 @@ import java.util.HashMap; import java.util.Map; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; - public class Row { /** diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowList.java index 3d35e9d18..50afeb781 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowList.java @@ -16,13 +16,13 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; - import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; + /** * This holds a list of {@link Row}. * Proper XML documents can contain only one root node. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowOutcomeList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowOutcomeList.java index da24c02f7..77c229653 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowOutcomeList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowOutcomeList.java @@ -16,13 +16,13 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; - import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; + /** * This holds a list of {@link Row}. * Proper XML documents can contain only one root node. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowResourceList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowResourceList.java index 39059ca53..49641f772 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowResourceList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/RowResourceList.java @@ -16,13 +16,13 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; - import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; + /** * This holds a list of {@link RowResource}. * Proper XML documents can contain only one root node. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableAclResourceList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableAclResourceList.java index 59216231e..dbf3668d2 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableAclResourceList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableAclResourceList.java @@ -16,15 +16,15 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + /** * This holds a list of {@link TableAclResource}. * Proper XML documents can contain only one root node. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableDefinition.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableDefinition.java index ec4902704..b145ec94e 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableDefinition.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableDefinition.java @@ -16,16 +16,16 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + /** * Represents the XML format of a table definition. This is essentially all the * necessary information for a table to be defined on the server in a way taht diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableDefinitionResource.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableDefinitionResource.java index 6af3e0090..ea3c2a085 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableDefinitionResource.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableDefinitionResource.java @@ -16,10 +16,10 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; - import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; + @JacksonXmlRootElement(localName="tableDefinitionResource") public class TableDefinitionResource extends TableDefinition { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableResourceList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableResourceList.java index 403f3bef3..4984d9ff4 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableResourceList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableResourceList.java @@ -16,15 +16,15 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * This holds a list of {@link TableResource}. Proper XML documents can contain * only one root node. This wrapping class provides that root node. diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableRole.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableRole.java index 7c73254a1..9158e4307 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableRole.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/TableRole.java @@ -16,12 +16,12 @@ package org.opendatakit.aggregate.odktables.rest.entity; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + import java.util.ArrayList; import java.util.Collections; import java.util.List; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - public enum TableRole { NONE("No permissions. Can not see that the table exists."), diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/UserInfo.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/UserInfo.java index fde0a9c69..11adc4d5d 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/UserInfo.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/UserInfo.java @@ -16,14 +16,14 @@ package org.opendatakit.aggregate.odktables.rest.entity; -import java.util.ArrayList; -import java.util.Collections; - import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.Collections; + /** * Describes a user who can manipulate odkTables appName content. * This user may not have synchronize permissions on the server diff --git a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/UserInfoList.java b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/UserInfoList.java index 29d11af55..774918da8 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/UserInfoList.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/rest/entity/UserInfoList.java @@ -16,11 +16,11 @@ package org.opendatakit.aggregate.odktables.rest.entity; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + import java.util.ArrayList; import java.util.List; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; - /** * This holds the list of UserInfo structures describing * the users that can manipulate odkTables appName data. This may diff --git a/src/main/java/org/opendatakit/aggregate/odktables/security/AuthFilter.java b/src/main/java/org/opendatakit/aggregate/odktables/security/AuthFilter.java index 3ef43673f..9c18c9612 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/security/AuthFilter.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/security/AuthFilter.java @@ -16,10 +16,6 @@ package org.opendatakit.aggregate.odktables.security; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.apache.commons.lang3.Validate; import org.opendatakit.aggregate.odktables.TableAclManager; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; @@ -30,6 +26,10 @@ import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; import org.opendatakit.common.web.CallingContext; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + public class AuthFilter { private CallingContext cc; @@ -104,8 +104,8 @@ public boolean hasPermission(TablePermission permission) throws ODKDatastoreExce */ public boolean hasFilterScope(TablePermission permission, String rowId, Scope filter) throws ODKDatastoreException { - Validate.notNull(permission); - Validate.notNull(rowId); + Validate.notNull(permission, "permission is null"); + Validate.notNull(rowId, "rowId is null"); // if (!permissions.contains(permission)) { // if (filter == null || filter.equals(Scope.EMPTY_SCOPE)) { diff --git a/src/main/java/org/opendatakit/aggregate/odktables/security/TablesUserPermissionsImpl.java b/src/main/java/org/opendatakit/aggregate/odktables/security/TablesUserPermissionsImpl.java index 7a75cfb11..362e4a346 100644 --- a/src/main/java/org/opendatakit/aggregate/odktables/security/TablesUserPermissionsImpl.java +++ b/src/main/java/org/opendatakit/aggregate/odktables/security/TablesUserPermissionsImpl.java @@ -16,12 +16,6 @@ package org.opendatakit.aggregate.odktables.security; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; import org.opendatakit.aggregate.odktables.rest.entity.Scope; import org.opendatakit.aggregate.odktables.rest.entity.Scope.Type; @@ -32,6 +26,12 @@ import org.opendatakit.common.web.CallingContext; import org.springframework.security.core.GrantedAuthority; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + public class TablesUserPermissionsImpl implements TablesUserPermissions { private final CallingContext cc; diff --git a/src/main/java/org/opendatakit/aggregate/parser/MultiPartFormData.java b/src/main/java/org/opendatakit/aggregate/parser/MultiPartFormData.java index ee0e92000..8638e319b 100644 --- a/src/main/java/org/opendatakit/aggregate/parser/MultiPartFormData.java +++ b/src/main/java/org/opendatakit/aggregate/parser/MultiPartFormData.java @@ -17,6 +17,14 @@ package org.opendatakit.aggregate.parser; +import org.apache.commons.fileupload.FileItemIterator; +import org.apache.commons.fileupload.FileItemStream; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.opendatakit.aggregate.constants.ParserConsts; + +import javax.servlet.http.HttpServletRequest; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -27,15 +35,6 @@ import java.util.Map; import java.util.Set; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.fileupload.FileItemIterator; -import org.apache.commons.fileupload.FileItemStream; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.opendatakit.aggregate.constants.ParserConsts; - /** * Parses a multi part form request into a set of multiPartFormItems. The * information stored in items are indexed by either the field name or the file diff --git a/src/main/java/org/opendatakit/aggregate/parser/NamingSet.java b/src/main/java/org/opendatakit/aggregate/parser/NamingSet.java index 059c28ccc..eb42eac3d 100644 --- a/src/main/java/org/opendatakit/aggregate/parser/NamingSet.java +++ b/src/main/java/org/opendatakit/aggregate/parser/NamingSet.java @@ -13,6 +13,13 @@ */ package org.opendatakit.aggregate.parser; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.opendatakit.common.persistence.Datastore; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; +import org.opendatakit.common.security.User; +import org.opendatakit.common.web.CallingContext; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -21,13 +28,6 @@ import java.util.TreeSet; import java.util.UUID; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.opendatakit.common.persistence.Datastore; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.security.User; -import org.opendatakit.common.web.CallingContext; - /** * When a form is uploaded, the names for the columns and tables representing * the form need to be determined. This is done in a three-step process. First, diff --git a/src/main/java/org/opendatakit/aggregate/server/ServerPreferencesProperties.java b/src/main/java/org/opendatakit/aggregate/server/ServerPreferencesProperties.java index 66cae6c6c..982316acb 100644 --- a/src/main/java/org/opendatakit/aggregate/server/ServerPreferencesProperties.java +++ b/src/main/java/org/opendatakit/aggregate/server/ServerPreferencesProperties.java @@ -16,9 +16,6 @@ package org.opendatakit.aggregate.server; -import java.util.Date; -import java.util.List; - import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.Datastore; @@ -31,6 +28,9 @@ import org.opendatakit.common.utils.WebUtils; import org.opendatakit.common.web.CallingContext; +import java.util.Date; +import java.util.List; + public class ServerPreferencesProperties extends CommonFieldsBase { private static final String TABLE_NAME = "_server_preferences_properties"; diff --git a/src/main/java/org/opendatakit/aggregate/server/SitePreferencesBean.java b/src/main/java/org/opendatakit/aggregate/server/SitePreferencesBean.java index 257bf6ec4..b80dc32ae 100644 --- a/src/main/java/org/opendatakit/aggregate/server/SitePreferencesBean.java +++ b/src/main/java/org/opendatakit/aggregate/server/SitePreferencesBean.java @@ -15,8 +15,6 @@ */ package org.opendatakit.aggregate.server; -import javax.servlet.ServletContext; - import org.opendatakit.common.persistence.Datastore; import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; import org.opendatakit.common.persistence.exception.ODKOverQuotaException; @@ -25,6 +23,8 @@ import org.opendatakit.common.web.CallingContext; import org.springframework.beans.factory.InitializingBean; +import javax.servlet.ServletContext; + /** * Simple class to retrieve the site key from ServerPreferencesProperties during * start-up. diff --git a/src/main/java/org/opendatakit/aggregate/server/UITrans.java b/src/main/java/org/opendatakit/aggregate/server/UITrans.java index 615528aa7..b85e7930c 100644 --- a/src/main/java/org/opendatakit/aggregate/server/UITrans.java +++ b/src/main/java/org/opendatakit/aggregate/server/UITrans.java @@ -16,13 +16,13 @@ package org.opendatakit.aggregate.server; -import java.util.HashMap; -import java.util.Map; - import org.opendatakit.aggregate.constants.common.FilterOperation; import org.opendatakit.aggregate.constants.common.Visibility; import org.opendatakit.common.persistence.Query; +import java.util.HashMap; +import java.util.Map; + /** * Translate enumerations between the UI layer and the rest of Aggregate * diff --git a/src/main/java/org/opendatakit/aggregate/servlet/AggregateHtmlServlet.java b/src/main/java/org/opendatakit/aggregate/servlet/AggregateHtmlServlet.java index 10b3029ff..e0a9603be 100644 --- a/src/main/java/org/opendatakit/aggregate/servlet/AggregateHtmlServlet.java +++ b/src/main/java/org/opendatakit/aggregate/servlet/AggregateHtmlServlet.java @@ -16,14 +16,6 @@ package org.opendatakit.aggregate.servlet; -import java.io.IOException; -import java.io.PrintWriter; -import java.net.URL; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.ContextFactory; @@ -35,6 +27,13 @@ import org.opendatakit.common.web.constants.BasicConsts; import org.opendatakit.common.web.constants.HtmlConsts; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URL; + /** * Stupid class to wrap the Aggregate.html page that GWT uses for all its UI * presentation. Needed so that access to the page can be managed by Spring diff --git a/src/main/java/org/opendatakit/aggregate/servlet/ServletUtilBase.java b/src/main/java/org/opendatakit/aggregate/servlet/ServletUtilBase.java index 487375c6b..c688af3d6 100644 --- a/src/main/java/org/opendatakit/aggregate/servlet/ServletUtilBase.java +++ b/src/main/java/org/opendatakit/aggregate/servlet/ServletUtilBase.java @@ -17,24 +17,22 @@ package org.opendatakit.aggregate.servlet; -import java.io.IOException; -import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.opendatakit.aggregate.constants.ErrorConsts; import org.opendatakit.aggregate.constants.ServletConsts; import org.opendatakit.aggregate.odktables.rest.ApiConstants; +import org.opendatakit.common.utils.HtmlUtil; import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.constants.HtmlConsts; import org.opendatakit.common.web.servlet.CommonServletBase; -import org.opendatakit.common.utils.HtmlUtil; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; /** * Base class for Servlets that contain useful utilities diff --git a/src/main/java/org/opendatakit/aggregate/task/WatchdogWorkerImpl.java b/src/main/java/org/opendatakit/aggregate/task/WatchdogWorkerImpl.java index 22ac4474e..4af4b6106 100644 --- a/src/main/java/org/opendatakit/aggregate/task/WatchdogWorkerImpl.java +++ b/src/main/java/org/opendatakit/aggregate/task/WatchdogWorkerImpl.java @@ -15,28 +15,18 @@ */ package org.opendatakit.aggregate.task; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.constants.BeanDefs; -import org.opendatakit.aggregate.constants.common.ExternalServiceType; -import org.opendatakit.aggregate.constants.common.OperationalStatus; -import org.opendatakit.aggregate.constants.common.UIConsts; -import org.opendatakit.aggregate.datamodel.TopLevelDynamicBase; import org.opendatakit.aggregate.exception.ODKExternalServiceException; import org.opendatakit.aggregate.exception.ODKFormNotFoundException; import org.opendatakit.aggregate.exception.ODKIncompleteSubmissionData; import org.opendatakit.aggregate.util.BackendActionsTable; -import org.opendatakit.common.persistence.PersistConsts; -import org.opendatakit.common.persistence.QueryResumePoint; import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.utils.WebUtils; import org.opendatakit.common.web.CallingContext; +import java.util.Date; + /** * Common worker implementation for restarting stalled tasks. * diff --git a/src/main/java/org/opendatakit/aggregate/task/tomcat/AggregrateThreadExecutor.java b/src/main/java/org/opendatakit/aggregate/task/tomcat/AggregrateThreadExecutor.java index b47bb0bad..a504fc0d5 100644 --- a/src/main/java/org/opendatakit/aggregate/task/tomcat/AggregrateThreadExecutor.java +++ b/src/main/java/org/opendatakit/aggregate/task/tomcat/AggregrateThreadExecutor.java @@ -15,11 +15,11 @@ */ package org.opendatakit.aggregate.task.tomcat; +import org.springframework.scheduling.TaskScheduler; + import java.util.Date; import java.util.concurrent.ScheduledFuture; -import org.springframework.scheduling.TaskScheduler; - /** * * @author wbrunette@gmail.com diff --git a/src/main/java/org/opendatakit/aggregate/task/tomcat/WatchdogImpl.java b/src/main/java/org/opendatakit/aggregate/task/tomcat/WatchdogImpl.java index 0e0a20916..257477285 100644 --- a/src/main/java/org/opendatakit/aggregate/task/tomcat/WatchdogImpl.java +++ b/src/main/java/org/opendatakit/aggregate/task/tomcat/WatchdogImpl.java @@ -15,12 +15,6 @@ */ package org.opendatakit.aggregate.task.tomcat; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.concurrent.ScheduledFuture; - -import javax.servlet.ServletContext; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.constants.BeanDefs; @@ -44,6 +38,11 @@ import org.springframework.scheduling.TaskScheduler; import org.springframework.web.context.ServletContextAware; +import javax.servlet.ServletContext; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.concurrent.ScheduledFuture; + /** * Tomcat implementation of the watchdog -- as an executor * diff --git a/src/main/java/org/opendatakit/aggregate/util/BackendActionsTable.java b/src/main/java/org/opendatakit/aggregate/util/BackendActionsTable.java index 8a2ec6392..7729a1438 100644 --- a/src/main/java/org/opendatakit/aggregate/util/BackendActionsTable.java +++ b/src/main/java/org/opendatakit/aggregate/util/BackendActionsTable.java @@ -15,10 +15,6 @@ */ package org.opendatakit.aggregate.util; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.constants.BeanDefs; @@ -34,6 +30,10 @@ import org.opendatakit.common.security.User; import org.opendatakit.common.web.CallingContext; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + /** * Implements the mechanisms used in GAE to launch Watchdog during periods of * website activity ( triggerWatchdog ) and from within the Watchdog diff --git a/src/main/java/org/opendatakit/common/datamodel/BinaryContentManipulator.java b/src/main/java/org/opendatakit/common/datamodel/BinaryContentManipulator.java index 03a976898..6915b5ab7 100644 --- a/src/main/java/org/opendatakit/common/datamodel/BinaryContentManipulator.java +++ b/src/main/java/org/opendatakit/common/datamodel/BinaryContentManipulator.java @@ -13,14 +13,6 @@ */ package org.opendatakit.common.datamodel; -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.Datastore; import org.opendatakit.common.persistence.EntityKey; @@ -33,6 +25,14 @@ import org.opendatakit.common.security.User; import org.opendatakit.common.web.CallingContext; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Manipulator class for handling binary attachments. To use, create an instance * of the manipulator class specifying the URI of the entity having the @@ -454,7 +454,7 @@ public BinaryContentManipulator.BlobSubmissionOutcome setValueFromByteArray(byte if (matchedBc == null) { // create the record... - matchedBc = (BinaryContent) ds.createEntityUsingRelation(ctntRelation, user); + matchedBc = ds.createEntityUsingRelation(ctntRelation, user); matchedBc.setTopLevelAuri(topLevelKey); matchedBc.setParentAuri(parentKey); matchedBc.setOrdinalNumber(internalGetAttachmentCount() + 1L); @@ -491,7 +491,7 @@ public BinaryContentManipulator.BlobSubmissionOutcome setValueFromByteArray(byte if (newBc) { // Step (0) // create the record... - matchedBc = (BinaryContent) ds.createEntityUsingRelation(ctntRelation, user); + matchedBc = ds.createEntityUsingRelation(ctntRelation, user); matchedBc.setTopLevelAuri(topLevelKey); matchedBc.setParentAuri(parentKey); matchedBc.setOrdinalNumber(internalGetAttachmentCount() + 1L); diff --git a/src/main/java/org/opendatakit/common/datamodel/DeleteHelper.java b/src/main/java/org/opendatakit/common/datamodel/DeleteHelper.java index c7f7cd702..5531c7794 100644 --- a/src/main/java/org/opendatakit/common/datamodel/DeleteHelper.java +++ b/src/main/java/org/opendatakit/common/datamodel/DeleteHelper.java @@ -15,12 +15,6 @@ */ package org.opendatakit.common.datamodel; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.aggregate.datamodel.TopLevelDynamicBase; @@ -32,6 +26,12 @@ import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; import org.opendatakit.common.web.CallingContext; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + public class DeleteHelper { private DeleteHelper() { diff --git a/src/main/java/org/opendatakit/common/datamodel/DynamicCommonFieldsBase.java b/src/main/java/org/opendatakit/common/datamodel/DynamicCommonFieldsBase.java index 5f3633df9..61ffe5260 100644 --- a/src/main/java/org/opendatakit/common/datamodel/DynamicCommonFieldsBase.java +++ b/src/main/java/org/opendatakit/common/datamodel/DynamicCommonFieldsBase.java @@ -15,12 +15,12 @@ */ package org.opendatakit.common.datamodel; -import java.util.Comparator; - import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.security.User; +import java.util.Comparator; + /** * Common abstract class that unifies all TopLevelDynamic and Dynamic classes. * Primarily so that Submission can derive from SubmissionSet. Useful for diff --git a/src/main/java/org/opendatakit/common/ermodel/AbstractBlobRelationSet.java b/src/main/java/org/opendatakit/common/ermodel/AbstractBlobRelationSet.java index b36ec11be..795100e87 100644 --- a/src/main/java/org/opendatakit/common/ermodel/AbstractBlobRelationSet.java +++ b/src/main/java/org/opendatakit/common/ermodel/AbstractBlobRelationSet.java @@ -13,9 +13,6 @@ */ package org.opendatakit.common.ermodel; -import java.util.Date; -import java.util.List; - import org.opendatakit.common.datamodel.BinaryContent; import org.opendatakit.common.datamodel.BinaryContentManipulator; import org.opendatakit.common.datamodel.BinaryContentManipulator.BlobSubmissionOutcome; @@ -30,6 +27,9 @@ import org.opendatakit.common.security.User; import org.opendatakit.common.web.CallingContext; +import java.util.Date; +import java.util.List; + /** * Base class for manipulating blob sets. The constructors assume that the base * name of the table is UPPER_CASE only. diff --git a/src/main/java/org/opendatakit/common/ermodel/BlobEntitySet.java b/src/main/java/org/opendatakit/common/ermodel/BlobEntitySet.java index 617364244..cd2592d36 100644 --- a/src/main/java/org/opendatakit/common/ermodel/BlobEntitySet.java +++ b/src/main/java/org/opendatakit/common/ermodel/BlobEntitySet.java @@ -13,14 +13,14 @@ */ package org.opendatakit.common.ermodel; -import java.util.Date; - import org.opendatakit.common.datamodel.BinaryContentManipulator.BlobSubmissionOutcome; import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKEntityPersistException; import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.Date; + /** * API for manipulating sets of blobs. Blobs themselves are stored using * multiple entities (rows) across 3 linked relations (tables). The details of diff --git a/src/main/java/org/opendatakit/common/ermodel/BlobRelationSet.java b/src/main/java/org/opendatakit/common/ermodel/BlobRelationSet.java index 91043dea1..59f9d344e 100644 --- a/src/main/java/org/opendatakit/common/ermodel/BlobRelationSet.java +++ b/src/main/java/org/opendatakit/common/ermodel/BlobRelationSet.java @@ -13,13 +13,13 @@ */ package org.opendatakit.common.ermodel; -import java.util.List; - import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKEntityPersistException; import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.List; + /** * API for the manipulation of a Blob set (e.g., the set of 3 tables used to * represent an artibrarily large binary object) in the datastore. See diff --git a/src/main/java/org/opendatakit/common/ermodel/Entity.java b/src/main/java/org/opendatakit/common/ermodel/Entity.java index 1c1418183..f4f13523c 100644 --- a/src/main/java/org/opendatakit/common/ermodel/Entity.java +++ b/src/main/java/org/opendatakit/common/ermodel/Entity.java @@ -16,8 +16,6 @@ package org.opendatakit.common.ermodel; -import java.util.Date; - import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.WrappedBigDecimal; import org.opendatakit.common.persistence.exception.ODKDatastoreException; @@ -25,6 +23,8 @@ import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.web.CallingContext; +import java.util.Date; + public interface Entity { /** diff --git a/src/main/java/org/opendatakit/common/ermodel/Query.java b/src/main/java/org/opendatakit/common/ermodel/Query.java index 4a9230a6f..04569f0f0 100644 --- a/src/main/java/org/opendatakit/common/ermodel/Query.java +++ b/src/main/java/org/opendatakit/common/ermodel/Query.java @@ -16,11 +16,6 @@ package org.opendatakit.common.ermodel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - import org.apache.commons.lang3.Validate; import org.opendatakit.common.ermodel.Relation.RelationImpl; import org.opendatakit.common.persistence.CommonFieldsBase; @@ -31,6 +26,11 @@ import org.opendatakit.common.persistence.QueryResumePoint; import org.opendatakit.common.persistence.exception.ODKDatastoreException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + /** * Query is a query over a Relation. * @@ -69,8 +69,7 @@ public WebsafeQueryResult(List entities, private org.opendatakit.common.persistence.Query query; protected Query(Relation relation, org.opendatakit.common.persistence.Query query) { - Validate.notNull(relation); - + Validate.notNull(relation, "relation cannot be null"); this.relation = relation; this.query = query; } @@ -258,7 +257,7 @@ public Query lessThanOrEqual(String fieldName, Object value) { */ public Query addFilter(String fieldName, FilterOperation op, Object value) { Validate.notEmpty(fieldName); - Validate.notNull(op); + Validate.notNull(op, "op cannot be null"); DataField field = relation.getDataField(fieldName); query.addFilter(field, op, value); return this; @@ -278,8 +277,8 @@ public Query addFilter(String fieldName, FilterOperation op, Object value) { * @return this Query, with the given filter added. */ public Query addFilter(DataField field, FilterOperation op, Object value) { - Validate.notNull(field); - Validate.notNull(op); + Validate.notNull(field, "field cannot be null"); + Validate.notNull(op, "op cannot be null"); query.addFilter(relation.verify(field), op, value); return this; @@ -345,8 +344,8 @@ public Query sortDescending(String fieldName) { * @return this Query, with the given sort added. */ public Query addSort(DataField field, Direction direction) { - Validate.notNull(field); - Validate.notNull(direction); + Validate.notNull(field, "field cannot be null"); + Validate.notNull(direction, "direction cannot be null"); query.addSort(relation.verify(field), direction); return this; } @@ -364,7 +363,7 @@ public Query addSort(DataField field, Direction direction) { */ public Query addSort(String fieldName, Direction direction) { Validate.notEmpty(fieldName); - Validate.notNull(direction); + Validate.notNull(direction, "direction cannot be null"); DataField field = relation.getDataField(fieldName); query.addSort(field, direction); return this; @@ -385,7 +384,7 @@ public Query addSort(String fieldName, Direction direction) { * not in values will be excluded from the query. */ public Query include(DataField field, Collection values) { - Validate.notNull(field); + Validate.notNull(field, "field cannot be null"); Validate.noNullElements(values); query.addValueSetFilter(relation.verify(field), values); return this; @@ -507,7 +506,7 @@ public WebsafeQueryResult execute(QueryResumePoint startCursor, int fetchLimit) * existing filter and sort criteria. */ public List getDistinct(DataField field) { - Validate.notNull(field); + Validate.notNull(field,"field cannot be null"); try { return query.executeDistinctValueForDataField(relation.verify(field)); } catch (ODKDatastoreException e) { diff --git a/src/main/java/org/opendatakit/common/ermodel/Relation.java b/src/main/java/org/opendatakit/common/ermodel/Relation.java index d375ecc7a..3be5747c4 100644 --- a/src/main/java/org/opendatakit/common/ermodel/Relation.java +++ b/src/main/java/org/opendatakit/common/ermodel/Relation.java @@ -13,15 +13,6 @@ */ package org.opendatakit.common.ermodel; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.Datastore; @@ -35,6 +26,15 @@ import org.opendatakit.common.utils.WebUtils; import org.opendatakit.common.web.CallingContext; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Base class for user-defined relations. The constructors assume that the name * of the table is UPPER_CASE only, as are the names of the DataFields in the diff --git a/src/main/java/org/opendatakit/common/persistence/CommonFieldsBase.java b/src/main/java/org/opendatakit/common/persistence/CommonFieldsBase.java index 877ab11c5..7e4a53fc3 100644 --- a/src/main/java/org/opendatakit/common/persistence/CommonFieldsBase.java +++ b/src/main/java/org/opendatakit/common/persistence/CommonFieldsBase.java @@ -13,9 +13,13 @@ */ package org.opendatakit.common.persistence; +import org.opendatakit.common.persistence.DataField.DataType; +import org.opendatakit.common.persistence.DataField.IndexType; +import org.opendatakit.common.security.User; + import java.io.UnsupportedEncodingException; -import java.math.BigDecimal; import java.math.BigInteger; +import java.math.RoundingMode; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; @@ -26,10 +30,6 @@ import java.util.Map; import java.util.UUID; -import org.opendatakit.common.persistence.DataField.DataType; -import org.opendatakit.common.persistence.DataField.IndexType; -import org.opendatakit.common.security.User; - /** * Base class defining the audit fields for a table. * @@ -298,7 +298,7 @@ public final void setNumericField(DataField f, WrappedBigDecimal value) { } if ( !f.isDoublePrecision() && !value.isSpecialValue() ) { // enforce scaling here... - fieldValueMap.put(f, value.setScale(f.getNumericScale(), BigDecimal.ROUND_HALF_UP)); + fieldValueMap.put(f, value.setScale(f.getNumericScale(), RoundingMode.HALF_UP)); } else { fieldValueMap.put(f, value); } diff --git a/src/main/java/org/opendatakit/common/persistence/Datastore.java b/src/main/java/org/opendatakit/common/persistence/Datastore.java index 6d01bcc1a..4e4ed9a70 100644 --- a/src/main/java/org/opendatakit/common/persistence/Datastore.java +++ b/src/main/java/org/opendatakit/common/persistence/Datastore.java @@ -13,15 +13,15 @@ */ package org.opendatakit.common.persistence; -import java.util.Collection; -import java.util.List; - import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; import org.opendatakit.common.persistence.exception.ODKEntityPersistException; import org.opendatakit.common.persistence.exception.ODKOverQuotaException; import org.opendatakit.common.security.User; +import java.util.Collection; +import java.util.List; + /** * The Datastore interface defines how to store, retrieve, and query data in ODK * Aggregate. It is designed to be the sole point of interaction for code above diff --git a/src/main/java/org/opendatakit/common/persistence/Query.java b/src/main/java/org/opendatakit/common/persistence/Query.java index 186bb4532..ca6de5b65 100644 --- a/src/main/java/org/opendatakit/common/persistence/Query.java +++ b/src/main/java/org/opendatakit/common/persistence/Query.java @@ -13,13 +13,13 @@ */ package org.opendatakit.common.persistence; +import org.opendatakit.common.persistence.exception.ODKDatastoreException; +import org.opendatakit.common.persistence.exception.ODKOverQuotaException; + import java.util.Collection; import java.util.List; import java.util.Set; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.persistence.exception.ODKOverQuotaException; - /** * The Query interface defines how persistence implementations should create query functionality. * diff --git a/src/main/java/org/opendatakit/common/persistence/WrappedBigDecimal.java b/src/main/java/org/opendatakit/common/persistence/WrappedBigDecimal.java index fdb1c48d9..7c742836a 100644 --- a/src/main/java/org/opendatakit/common/persistence/WrappedBigDecimal.java +++ b/src/main/java/org/opendatakit/common/persistence/WrappedBigDecimal.java @@ -17,6 +17,7 @@ package org.opendatakit.common.persistence; import java.math.BigDecimal; +import java.math.RoundingMode; /** * Wrapper to encapsulate and pass through the special double values of NaN, @@ -79,7 +80,7 @@ public boolean isSpecialValue() { return (d != null); } - public WrappedBigDecimal setScale(int scale, int roundingMode) { + public WrappedBigDecimal setScale(int scale, RoundingMode roundingMode) { if (isSpecialValue()) { // immutable return this; diff --git a/src/main/java/org/opendatakit/common/persistence/engine/DatastoreAccessMetrics.java b/src/main/java/org/opendatakit/common/persistence/engine/DatastoreAccessMetrics.java index efb5097b0..3e06823db 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/DatastoreAccessMetrics.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/DatastoreAccessMetrics.java @@ -13,15 +13,15 @@ */ package org.opendatakit.common.persistence.engine; -import java.util.Map; -import java.util.TreeMap; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.EntityKey; import org.opendatakit.common.utils.WebUtils; +import java.util.Map; +import java.util.TreeMap; + /** * Tracks the access patterns for the datastore layer. Useful for identifying * inefficient datastore access patterns and minimizing excessive read/write diff --git a/src/main/java/org/opendatakit/common/persistence/engine/EngineUtils.java b/src/main/java/org/opendatakit/common/persistence/engine/EngineUtils.java index 1c0ce0970..48efc45da 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/EngineUtils.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/EngineUtils.java @@ -13,14 +13,14 @@ */ package org.opendatakit.common.persistence.engine; -import java.math.BigDecimal; -import java.util.Date; - import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.WrappedBigDecimal; import org.opendatakit.common.utils.WebUtils; +import java.math.RoundingMode; +import java.util.Date; + public class EngineUtils { public static final Object getDominantSortAttributeValue( CommonFieldsBase odkEntity, DataField dominantAttr) { @@ -174,7 +174,7 @@ public static final String getAttributeValueAsString(Object o, DataField dominan value = null; } else { if ( !dominantAttr.isDoublePrecision() && !bd.isSpecialValue() ) { - bd = bd.setScale(dominantAttr.getNumericScale(), BigDecimal.ROUND_HALF_UP); + bd = bd.setScale(dominantAttr.getNumericScale(), RoundingMode.HALF_UP); } value = bd.toString(); } @@ -228,7 +228,7 @@ public static final Object getDominantSortAttributeValueFromString(String v, Dat } else { WrappedBigDecimal bd = new WrappedBigDecimal(v); if ( !dominantAttr.isDoublePrecision() && !bd.isSpecialValue() ) { - bd = bd.setScale(dominantAttr.getNumericScale(), BigDecimal.ROUND_HALF_UP); + bd = bd.setScale(dominantAttr.getNumericScale(), RoundingMode.HALF_UP); } value = bd; } diff --git a/src/main/java/org/opendatakit/common/persistence/engine/mysql/DatastoreImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/mysql/DatastoreImpl.java index e3955e312..28b937414 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/mysql/DatastoreImpl.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/mysql/DatastoreImpl.java @@ -13,18 +13,6 @@ */ package org.opendatakit.common.persistence.engine.mysql; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.sql.DataSource; - import org.apache.commons.logging.LogFactory; import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; @@ -52,6 +40,17 @@ import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; +import javax.sql.DataSource; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * * @author wbrunette@gmail.com @@ -85,12 +84,6 @@ public void setDataSource(DataSource dataSource) { // ignore this but log a brief info message LogFactory.getLog(DatastoreImpl.class).info("Failed to load com.mysql.jdbc.Driver (did you download and install/copy MySQL Connector/J ?) Exception: " + e.toString()); } - try { - Class.forName("com.mysql.jdbc.GoogleDriver"); - } catch ( Exception e ) { - // ignore this but log a brief info message - LogFactory.getLog(DatastoreImpl.class).info("Failed to load com.mysql.jdbc.GoogleDriver Exception: " + e.toString()); - } this.tm = new DataSourceTransactionManager(dataSource); } diff --git a/src/main/java/org/opendatakit/common/persistence/engine/mysql/QueryImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/mysql/QueryImpl.java index b9566bd8c..f0bfbf697 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/mysql/QueryImpl.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/mysql/QueryImpl.java @@ -13,16 +13,6 @@ */ package org.opendatakit.common.persistence.engine.mysql; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.common.persistence.CommonFieldsBase; @@ -37,6 +27,16 @@ import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.RowMapper; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * * @author wbrunette@gmail.com @@ -264,7 +264,7 @@ public List executeQuery() throws ODKDatastoreExcept try { queryStringLogger.debug(query); List l = dataStoreImpl.getJdbcConnection().query(query, - bindValues.toArray(), rowMapper); + rowMapper, bindValues.toArray()); dataStoreImpl.recordQueryUsage(relation, l.size()); return l; } catch (Exception e) { @@ -282,8 +282,7 @@ public List executeDistinctValueForDataField(DataField dataField) throws ODKD List keys = null; try { - keys = dataStoreImpl.getJdbcConnection().queryForList(query, bindValues.toArray(), - String.class); + keys = dataStoreImpl.getJdbcConnection().queryForList(query, String.class,bindValues.toArray()); dataStoreImpl.recordQueryUsage(relation, keys.size()); } catch (Exception e) { dataStoreImpl.recordQueryUsage(relation, 0); @@ -421,7 +420,7 @@ public QueryResult executeQuery(QueryResumePoint startCursor, int fetchLimit) CoreResult r; try { queryStringLogger.debug(query); - r = dataStoreImpl.getJdbcConnection().query(query, values.toArray(), rse); + r = dataStoreImpl.getJdbcConnection().query(query, rse, values.toArray()); } finally { dataStoreImpl.recordQueryUsage(relation, rse.getReadCount()); } diff --git a/src/main/java/org/opendatakit/common/persistence/engine/mysql/RelationRowMapper.java b/src/main/java/org/opendatakit/common/persistence/engine/mysql/RelationRowMapper.java index 1a6e5fcff..9e1e127e7 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/mysql/RelationRowMapper.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/mysql/RelationRowMapper.java @@ -13,16 +13,16 @@ */ package org.opendatakit.common.persistence.engine.mysql; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Date; - import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.WrappedBigDecimal; import org.opendatakit.common.security.User; import org.springframework.jdbc.core.RowMapper; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Date; + /** * * @author wbrunette@gmail.com diff --git a/src/main/java/org/opendatakit/common/persistence/engine/mysql/TaskLockImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/mysql/TaskLockImpl.java index b134210a4..036293ffe 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/mysql/TaskLockImpl.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/mysql/TaskLockImpl.java @@ -15,14 +15,6 @@ */ package org.opendatakit.common.persistence.engine.mysql; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - import org.apache.commons.logging.LogFactory; import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; @@ -39,6 +31,14 @@ import org.springframework.jdbc.core.ConnectionCallback; import org.springframework.jdbc.core.JdbcTemplate; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + /** * * @author wbrunette@gmail.com @@ -338,7 +338,7 @@ public Object doInConnection(Connection conn) throws SQLException, DataAccessExc conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); String lastResult = null; for (String s : stmts) { - Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); + Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); if ( s.startsWith("SELECT") ) { ResultSet rs = stmt.executeQuery(s); if ( rs.first() ) { @@ -375,7 +375,7 @@ public Object doInConnection(Connection conn) throws SQLException, DataAccessExc throw new ODKTaskLockException(PERSISTENCE_LAYER_PROBLEM, e); } if ( success ) { - return (TaskLockTable) datastore.getEntity(relation, uri, user); + return datastore.getEntity(relation, uri, user); } else { throw new ODKEntityNotFoundException(); } diff --git a/src/main/java/org/opendatakit/common/persistence/engine/pgres/DatastoreImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/pgres/DatastoreImpl.java index 571d1d114..f919d40b5 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/pgres/DatastoreImpl.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/pgres/DatastoreImpl.java @@ -13,19 +13,6 @@ */ package org.opendatakit.common.persistence.engine.pgres; -import java.math.BigDecimal; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.sql.DataSource; - import org.apache.commons.logging.LogFactory; import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; @@ -52,6 +39,19 @@ import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * * @author wbrunette@gmail.com @@ -406,7 +406,7 @@ private final boolean updateRelation(JdbcTemplate jc, CommonFieldsBase relation, String qs = TableDefinition.TABLE_DEF_QUERY; List columns; columns = jc.query(qs, new Object[] { relation.getSchemaName(), relation.getTableName() }, - tableDef); + new int[]{ Types.VARCHAR, Types.VARCHAR }, tableDef); dam.recordQueryUsage(TableDefinition.INFORMATION_SCHEMA_COLUMNS, columns.size()); if (columns.size() > 0) { @@ -703,7 +703,7 @@ public boolean hasRelation(String schema, String tableName, User user) { dam.recordQueryUsage(TableDefinition.INFORMATION_SCHEMA_COLUMNS, 1); String qs = TableDefinition.TABLE_EXISTS_QUERY; Integer columnCount = getJdbcConnection().queryForObject(qs, new Object[] { schema, tableName }, - Integer.class); + new int[]{ Types.VARCHAR, Types.VARCHAR }, Integer.class); return (columnCount != null && columnCount != 0); } diff --git a/src/main/java/org/opendatakit/common/persistence/engine/pgres/QueryImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/pgres/QueryImpl.java index c24946199..edcf5d542 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/pgres/QueryImpl.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/pgres/QueryImpl.java @@ -13,16 +13,6 @@ */ package org.opendatakit.common.persistence.engine.pgres; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendatakit.common.persistence.CommonFieldsBase; @@ -37,6 +27,16 @@ import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.RowMapper; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * * @author wbrunette@gmail.com @@ -264,7 +264,7 @@ public List executeQuery() throws ODKDatastoreExcept try { queryStringLogger.debug(query); List l = dataStoreImpl.getJdbcConnection().query(query, - bindValues.toArray(), rowMapper); + rowMapper, bindValues.toArray()); dataStoreImpl.recordQueryUsage(relation, l.size()); return l; } catch (Exception e) { @@ -282,8 +282,7 @@ public List executeDistinctValueForDataField(DataField dataField) throws ODKD List keys = null; try { - keys = dataStoreImpl.getJdbcConnection().queryForList(query, bindValues.toArray(), - String.class); + keys = dataStoreImpl.getJdbcConnection().queryForList(query, String.class, bindValues.toArray()); dataStoreImpl.recordQueryUsage(relation, keys.size()); } catch (Exception e) { dataStoreImpl.recordQueryUsage(relation, 0); @@ -421,7 +420,7 @@ public QueryResult executeQuery(QueryResumePoint startCursor, int fetchLimit) CoreResult r; try { queryStringLogger.debug(query); - r = dataStoreImpl.getJdbcConnection().query(query, values.toArray(), rse); + r = dataStoreImpl.getJdbcConnection().query(query, rse, values.toArray()); } finally { dataStoreImpl.recordQueryUsage(relation, rse.getReadCount()); } diff --git a/src/main/java/org/opendatakit/common/persistence/engine/pgres/RelationRowMapper.java b/src/main/java/org/opendatakit/common/persistence/engine/pgres/RelationRowMapper.java index 0658602da..fcfe20e83 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/pgres/RelationRowMapper.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/pgres/RelationRowMapper.java @@ -13,16 +13,16 @@ */ package org.opendatakit.common.persistence.engine.pgres; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Date; - import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.WrappedBigDecimal; import org.opendatakit.common.security.User; import org.springframework.jdbc.core.RowMapper; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Date; + /** * * @author wbrunette@gmail.com diff --git a/src/main/java/org/opendatakit/common/persistence/engine/pgres/TaskLockImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/pgres/TaskLockImpl.java index 831a780b1..85226ece0 100644 --- a/src/main/java/org/opendatakit/common/persistence/engine/pgres/TaskLockImpl.java +++ b/src/main/java/org/opendatakit/common/persistence/engine/pgres/TaskLockImpl.java @@ -15,13 +15,6 @@ */ package org.opendatakit.common.persistence.engine.pgres; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - import org.apache.commons.logging.LogFactory; import org.opendatakit.common.persistence.CommonFieldsBase; import org.opendatakit.common.persistence.DataField; @@ -38,6 +31,13 @@ import org.springframework.jdbc.core.ConnectionCallback; import org.springframework.jdbc.core.JdbcTemplate; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + /** * * @author wbrunette@gmail.com @@ -256,7 +256,7 @@ public Object doInConnection(Connection conn) throws SQLException, DataAccessExc } catch (Exception e) { throw new ODKTaskLockException(PERSISTENCE_LAYER_PROBLEM, e); } - return (TaskLockTable) datastore.getEntity(relation, entity.getUri(), user); + return datastore.getEntity(relation, entity.getUri(), user); } @Override diff --git a/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/DatastoreImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/DatastoreImpl.java deleted file mode 100644 index b91a21b89..000000000 --- a/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/DatastoreImpl.java +++ /dev/null @@ -1,1298 +0,0 @@ -/** - * Copyright (C) 2010 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.common.persistence.engine.sqlserver; - -import java.math.BigDecimal; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; - -import javax.sql.DataSource; - -import org.apache.commons.logging.LogFactory; -import org.opendatakit.common.persistence.CommonFieldsBase; -import org.opendatakit.common.persistence.DataField; -import org.opendatakit.common.persistence.DataField.DataType; -import org.opendatakit.common.persistence.DataField.IndexType; -import org.opendatakit.common.persistence.Datastore; -import org.opendatakit.common.persistence.EntityKey; -import org.opendatakit.common.persistence.PersistConsts; -import org.opendatakit.common.persistence.Query; -import org.opendatakit.common.persistence.Query.FilterOperation; -import org.opendatakit.common.persistence.TaskLock; -import org.opendatakit.common.persistence.WrappedBigDecimal; -import org.opendatakit.common.persistence.engine.DatastoreAccessMetrics; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; -import org.opendatakit.common.persistence.exception.ODKEntityPersistException; -import org.opendatakit.common.security.User; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.jdbc.core.BatchPreparedStatementSetter; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.PreparedStatementSetter; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.SqlParameterValue; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.DefaultTransactionDefinition; - -/** - * - * @author wbrunette@gmail.com - * @author mitchellsundt@gmail.com - * - */ -public class DatastoreImpl implements Datastore, InitializingBean { - - private static final boolean logBindDetails = false; - - // SQL Server has a 116-character limit in column names. - // limit to two for future uses - private static final int MAX_COLUMN_NAME_LEN = 114; - // and the same limit applies to table names. - private static final int MAX_TABLE_NAME_LEN = 112; // reserve 4 char for idx - // name - - static final long MAX_IN_ROW_NVARCHAR = 4000L; - - // limit on SqlServer capacity (minus about 100 for where clause filters) - private static final int MAX_BIND_PARAMS = 2000; - - static final String PATTERN_ISO8601_NO_ZONE = "yyyy-MM-dd'T'HH:mm:ss.SSS"; - - // limit to 256MB blob size; don't know the impact of this... - private static final Long MAX_BLOB_SIZE = 65536 * 4096L; - - private final DatastoreAccessMetrics dam = new DatastoreAccessMetrics(); - private DataSource dataSource = null; - private DataSourceTransactionManager tm = null; - - private String schemaName = null; - - public DatastoreImpl() throws ODKDatastoreException { - } - - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - this.tm = new DataSourceTransactionManager(dataSource); - } - - public void setSchemaName(String schemaName) { - this.schemaName = schemaName; - } - - @Override - public void afterPropertiesSet() throws Exception { - if (dataSource == null) { - throw new IllegalStateException("dataSource property must be set!"); - } - if (schemaName == null) { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - List databaseNames = jdbcTemplate.queryForList("SELECT current_database()", String.class); - schemaName = (String) databaseNames.get(0); - } - } - - public static final String K_CREATE_TABLE = "CREATE TABLE "; - public static final String K_DROP_TABLE = "DROP TABLE "; - - public static final String K_OPEN_PAREN = " ( "; - public static final String K_CLOSE_PAREN = " ) "; - public static final String K_SELECT = "SELECT "; - public static final String K_SELECT_DISTINCT = "SELECT DISTINCT "; - public static final String K_CS = ", "; - public static final String K_COLON = ";"; - public static final String K_BQ = "\""; - public static final String K_FROM = " FROM "; - public static final String K_WHERE = " WHERE "; - public static final String K_AND = " AND "; - public static final String K_IS_NULL = " IS NULL"; - public static final String K_EQ_NULL = " = NULL"; - private static final String K_NULL = " NULL "; - private static final String K_NOT_NULL = " NOT NULL "; - public static final String K_EQ = " = "; - public static final String K_BIND_VALUE = "?"; - public static final String K_CREATE_CLUSTERED_INDEX = "CREATE CLUSTERED INDEX "; - public static final String K_CREATE_NONCLUSTERED_INDEX = "CREATE NONCLUSTERED INDEX "; - public static final String K_ON = " ON "; - public static final String K_INSERT_INTO = "INSERT INTO "; - public static final String K_VALUES = " VALUES "; - public static final String K_UPDATE = "UPDATE "; - public static final String K_SET = " SET "; - public static final String K_DELETE_FROM = "DELETE FROM "; - - public static final Integer DEFAULT_DBL_NUMERIC_SCALE = 10; - public static final Integer DEFAULT_DBL_NUMERIC_PRECISION = 38; - public static final Integer DEFAULT_INT_NUMERIC_PRECISION = 9; - - private static final class TableDefinition { - - public DataField.DataType getDataType() { - return dataType; - } - - public void setDataType(DataField.DataType dataType) { - this.dataType = dataType; - } - - public String getColumnName() { - return columnName; - } - - public boolean isNullable() { - return isNullable; - } - - public Long getMaxCharLen() { - return maxCharLen; - } - - public Integer getNumericScale() { - return numericScale; - } - - public Integer getNumericPrecision() { - return numericPrecision; - } - - public boolean isDoublePrecision() { - return isDoublePrecision; - } - - public static final String COLUMN_NAME = "column_name"; - public static final String CHARACTER_MAXIMUM_LENGTH = "character_maximum_length"; - public static final String NUMERIC_PRECISION = "numeric_precision"; - public static final String NUMERIC_SCALE = "numeric_scale"; - public static final String DATA_TYPE = "data_type"; - public static final String IS_NULLABLE = "is_nullable"; - public static final String INFORMATION_SCHEMA_COLUMNS = "sys.columns_join_for_table_def_query"; - - public static final String TABLE_DEF_FROM_WHERE_CLAUSE = " from sys.columns c, sys.types t, sys.tables tn, sys.schemas s where " - + "c.object_id = tn.object_id and tn.schema_id = s.schema_id and " - + "c.system_type_id = t.system_type_id and c.user_type_id = t.user_type_id and " - + " s.name = " + K_BIND_VALUE + " and tn.name = " + K_BIND_VALUE; - - public static final String TABLE_DEF_QUERY = "select s.name as \"schema_name\", tn.name as table_name, c.name as column_name, " - + "c.is_nullable, c.max_length as \"character_maximum_length\", " - + "c.precision as \"numeric_precision\", c.scale as \"numeric_scale\", t.name as \"data_type\" " - + TABLE_DEF_FROM_WHERE_CLAUSE; - - public static final String TABLE_EXISTS_QUERY = "select count(1) " - + TABLE_DEF_FROM_WHERE_CLAUSE; - - private static final String BIT = "bit"; - - private static final String VARBINARY = "varbinary"; - - private static final String TEXT = "text"; // lower case! - private static final String CHAR = "char"; - - private static final String DATE = "date"; - private static final String TIME = "time"; - - private static final String INT = "int"; - private static final String FLOAT = "float"; - - private String columnName; - private boolean isNullable; - private Long maxCharLen = null; - private Integer numericScale = null; - private Integer numericPrecision = null; - private boolean isDoublePrecision = false; - private DataField.DataType dataType; - - TableDefinition(ResultSet rs) throws SQLException { - columnName = rs.getString(COLUMN_NAME); - int i = rs.getInt(IS_NULLABLE); - isNullable = (i == 1); - isDoublePrecision = false; - - String type = rs.getString(DATA_TYPE); - BigDecimal num = rs.getBigDecimal(CHARACTER_MAXIMUM_LENGTH); - - if (type.equalsIgnoreCase(BIT)) { - // bit -- boolean - dataType = DataField.DataType.BOOLEAN; - - } else if (type.equalsIgnoreCase(VARBINARY)) { - // blob - dataType = DataField.DataType.BINARY; - maxCharLen = num.longValueExact(); - // limit to a smaller size than 2GB - if (maxCharLen < 0L || maxCharLen > MAX_BLOB_SIZE) { - maxCharLen = MAX_BLOB_SIZE; - } - - } else if (type.contains(TEXT) || type.contains(CHAR)) { - // some sort of text field - maxCharLen = num.longValueExact(); - // limit to a smaller size than 2GB - if (maxCharLen < 0L || maxCharLen > MAX_BLOB_SIZE) { - maxCharLen = MAX_BLOB_SIZE; - } - - if (type.startsWith("n")) { - // actual number of UTF-8 chars is one half storage size - maxCharLen = maxCharLen / 2L; - } - - if (maxCharLen.compareTo(MAX_IN_ROW_NVARCHAR) <= 0) { - dataType = DataField.DataType.STRING; - } else { - dataType = DataField.DataType.LONG_STRING; - } - - } else if (type.contains(DATE) || type.contains(TIME)) { - // holds a timestamp - dataType = DataField.DataType.DATETIME; - - } else if (type.contains(INT)) { - // some form of integer - dataType = DataField.DataType.INTEGER; - numericScale = 0; - numericPrecision = rs.getBigDecimal(NUMERIC_PRECISION).intValueExact(); - - } else { - // must be numeric... - if (type.contains(FLOAT)) { - - dataType = DataField.DataType.DECIMAL; - numericScale = null; - num = rs.getBigDecimal(NUMERIC_PRECISION); - numericPrecision = num.intValueExact(); - isDoublePrecision = true; - - } else { - - num = rs.getBigDecimal(NUMERIC_SCALE); - if (num == null) { - throw new IllegalArgumentException("unrecognized data type in schema: " + type); - } else { - // discriminate between decimal and integer by looking at value... - // We assume that nobody is going crazy with the scale here... - if (BigDecimal.ZERO.equals(num)) { - dataType = DataField.DataType.INTEGER; - numericScale = 0; - } else { - numericScale = num.intValueExact(); - dataType = DataField.DataType.DECIMAL; - } - num = rs.getBigDecimal(NUMERIC_PRECISION); - numericPrecision = num.intValueExact(); - } - } - } - } - } - - private static RowMapper tableDef = new RowMapper() { - @Override - public TableDefinition mapRow(ResultSet rs, int rowNum) throws SQLException { - return new TableDefinition(rs); - } - }; - - static SqlParameterValue getBindValue(DataField f, Object value) { - switch (f.getDataType()) { - case BOOLEAN: - if ( value == null ) { - return new SqlParameterValue(java.sql.Types.BIT, null); - } else if ( value instanceof Boolean ) { - return new SqlParameterValue(java.sql.Types.BIT, (((Boolean) value) ? 1 : 0)); - } else { - Boolean b = Boolean.valueOf(value.toString()); - return new SqlParameterValue(java.sql.Types.BIT, (b ? 1 : 0)); - } - case STRING: - case URI: - if ( value == null ) { - return new SqlParameterValue(java.sql.Types.NVARCHAR, null); - } else { - return new SqlParameterValue(java.sql.Types.NVARCHAR, value.toString()); - } - case INTEGER: - if ( value == null ) { - return new SqlParameterValue(java.sql.Types.BIGINT, null); - } else if ( value instanceof Long ) { - return new SqlParameterValue(java.sql.Types.BIGINT, (Long) value); - } else { - Long l = Long.valueOf(value.toString()); - return new SqlParameterValue(java.sql.Types.BIGINT, l); - } - case DECIMAL: { - if ( value == null ) { - // nulls may not go through as DECIMAL -- assert they are strings - return new SqlParameterValue(java.sql.Types.NVARCHAR, null); - } else { - WrappedBigDecimal wbd; - if ( value instanceof WrappedBigDecimal ) { - wbd = (WrappedBigDecimal) value; - } else { - wbd = new WrappedBigDecimal(value.toString()); - } - if ( wbd.isSpecialValue() ) { - return new SqlParameterValue(java.sql.Types.DOUBLE, wbd.d); - } else { - return new SqlParameterValue(java.sql.Types.DECIMAL, wbd.bd); - } - } - } - case DATETIME: { - // This doesn't like TIMESTAMP data type - if ( value == null ) { - return new SqlParameterValue(java.sql.Types.TIMESTAMP, null); - } else if ( value instanceof Date ) { - // This doesn't like TIMESTAMP data type - Date v = (Date) value; - String dateTime = null; - if (v != null) { - SimpleDateFormat asGMTiso8601 = new SimpleDateFormat(DatastoreImpl.PATTERN_ISO8601_NO_ZONE); - asGMTiso8601.setTimeZone(TimeZone.getTimeZone("GMT")); - dateTime = asGMTiso8601.format(v); - } - return new SqlParameterValue(java.sql.Types.TIMESTAMP, dateTime); - } else { - throw new IllegalArgumentException("expected Date for DATETIME bind parameter"); - } - } - case BINARY: - if ( value == null ) { - return new SqlParameterValue(java.sql.Types.LONGVARBINARY, null); - } else if ( value instanceof byte[] ) { - return new SqlParameterValue(java.sql.Types.LONGVARBINARY, value); - } else { - throw new IllegalArgumentException("expected byte[] for BINARY bind parameter"); - } - case LONG_STRING: - if ( value == null ) { - return new SqlParameterValue(java.sql.Types.LONGNVARCHAR, null); - } else { - return new SqlParameterValue(java.sql.Types.LONGNVARCHAR, value.toString()); - } - - default: - throw new IllegalStateException("Unexpected data type"); - } - } - - public static void buildArgumentList(List pv, CommonFieldsBase entity, - DataField f) { - switch (f.getDataType()) { - case BOOLEAN: - pv.add(getBindValue(f, entity.getBooleanField(f))); - break; - case STRING: - case URI: - pv.add(getBindValue(f, entity.getStringField(f))); - break; - case INTEGER: - pv.add(getBindValue(f, entity.getLongField(f))); - break; - case DECIMAL: - pv.add(getBindValue(f, entity.getNumericField(f))); - break; - case DATETIME: - pv.add(getBindValue(f, entity.getDateField(f))); - break; - case BINARY: - pv.add(getBindValue(f, entity.getBlobField(f))); - break; - case LONG_STRING: - pv.add(getBindValue(f, entity.getStringField(f))); - break; - - default: - throw new IllegalStateException("Unexpected data type"); - } - } - - void recordQueryUsage(CommonFieldsBase relation, int recCount) { - dam.recordQueryUsage(relation, recCount); - } - - @Override - public String getDefaultSchemaName() { - return schemaName; - } - - JdbcTemplate getJdbcConnection() { - return new JdbcTemplate(dataSource); - } - - @Override - public int getMaxLenColumnName() { - return MAX_COLUMN_NAME_LEN; - } - - @Override - public int getMaxLenTableName() { - return MAX_TABLE_NAME_LEN; - } - - private final boolean updateRelation(JdbcTemplate jc, CommonFieldsBase relation, - String originalStatement) { - - String qs = TableDefinition.TABLE_DEF_QUERY; - List columns; - columns = jc.query(qs, new Object[] { relation.getSchemaName(), relation.getTableName() }, - tableDef); - dam.recordQueryUsage(TableDefinition.INFORMATION_SCHEMA_COLUMNS, columns.size()); - - if (columns.size() > 0) { - Map map = new HashMap(); - for (Object o : columns) { - TableDefinition t = (TableDefinition) o; - map.put(t.getColumnName(), t); - } - - // we may have gotten some results into columns -- go through the fields - // and - // assemble the results... we don't care about additional columns in the - // map... - for (DataField f : relation.getFieldList()) { - TableDefinition d = map.get(f.getName()); - if (d == null) { - StringBuilder b = new StringBuilder(); - if (originalStatement == null) { - b.append(" Retrieving expected definition ("); - boolean first = true; - for (DataField field : relation.getFieldList()) { - if (!first) { - b.append(K_CS); - } - first = false; - b.append(field.getName()); - } - b.append(")"); - } else { - b.append(" Created with: "); - b.append(originalStatement); - } - throw new IllegalStateException( - "did not find expected column " + f.getName() + " in table " - + relation.getSchemaName() + "." + relation.getTableName() + b.toString()); - } - if (f.getDataType() == DataField.DataType.BOOLEAN - && d.getDataType() == DataField.DataType.STRING) { - d.setDataType(DataField.DataType.BOOLEAN); - // don't care about size... - } - - if (d.getDataType() == DataField.DataType.STRING && f.getMaxCharLen() != null - && f.getMaxCharLen().compareTo(d.getMaxCharLen()) > 0) { - throw new IllegalStateException("column " + f.getName() + " in table " - + relation.getSchemaName() + "." + relation.getTableName() - + " stores string-valued keys but is shorter than required by Aggregate " - + d.getMaxCharLen().toString() + " < " + f.getMaxCharLen().toString()); - } - - if (f.getDataType() == DataField.DataType.URI) { - if (d.getDataType() != DataField.DataType.STRING) { - throw new IllegalStateException( - "column " + f.getName() + " in table " + relation.getSchemaName() + "." - + relation.getTableName() + " stores URIs but is not a string field"); - } - d.setDataType(DataField.DataType.URI); - } - - if ((d.getDataType() == DataField.DataType.LONG_STRING) - && (f.getDataType() == DataField.DataType.STRING)) { - // we have an overly-large string that needed to be - // stored as a nvarchar(max) string. This is OK - } else if (d.getDataType() != f.getDataType()) { - throw new IllegalStateException("column " + f.getName() + " in table " - + relation.getSchemaName() + "." + relation.getTableName() - + " is not of the expected type " + f.getDataType().toString()); - } - - // it is OK for the data model to be more strict than the data store. - if (!d.isNullable() && f.getNullable()) { - throw new IllegalStateException("column " + f.getName() + " in table " - + relation.getSchemaName() + "." + relation.getTableName() - + " is defined as NOT NULL but the data model requires NULL"); - } - f.setMaxCharLen(d.getMaxCharLen()); - f.setNumericPrecision(d.getNumericPrecision()); - f.setNumericScale(d.getNumericScale()); - f.asDoublePrecision(d.isDoublePrecision()); - } - return true; - } else { - return false; - } - } - - /** - * Relation manipulation APIs - */ - @Override - public void assertRelation(CommonFieldsBase relation, User user) throws ODKDatastoreException { - JdbcTemplate jc = getJdbcConnection(); - TransactionStatus status = null; - try { - DefaultTransactionDefinition paramTransactionDefinition = new DefaultTransactionDefinition(); - - // do serializable read on the information schema... - paramTransactionDefinition - .setIsolationLevel(DefaultTransactionDefinition.ISOLATION_SERIALIZABLE); - paramTransactionDefinition.setReadOnly(true); - status = tm.getTransaction(paramTransactionDefinition); - - // see if relation already is defined and update it with dimensions... - if (updateRelation(jc, relation, null)) { - // it exists -- we're done! - tm.commit(status); - status = null; - return; - } else { - tm.commit(status); - // Try a new transaction to create the table - paramTransactionDefinition - .setIsolationLevel(DefaultTransactionDefinition.ISOLATION_SERIALIZABLE); - paramTransactionDefinition.setReadOnly(false); - status = tm.getTransaction(paramTransactionDefinition); - - // total number of columns must be less than MAX_BIND_PARAMS - int countColumns = 0; - // need to create the table... - StringBuilder b = new StringBuilder(); - b.append(K_CREATE_TABLE); - b.append(K_BQ); - b.append(relation.getSchemaName()); - b.append(K_BQ); - b.append("."); - b.append(K_BQ); - b.append(relation.getTableName()); - b.append(K_BQ); - b.append(K_OPEN_PAREN); - boolean firstTime = true; - for (DataField f : relation.getFieldList()) { - if (!firstTime) { - b.append(K_CS); - } - ++countColumns; - firstTime = false; - String nullClause; - if (f.getNullable()) { - nullClause = K_NULL; - } else { - nullClause = K_NOT_NULL; - } - - b.append(K_BQ); - b.append(f.getName()); - b.append(K_BQ); - DataField.DataType type = f.getDataType(); - switch (type) { - case BINARY: - b.append(" varbinary(max)").append(nullClause); - break; - case LONG_STRING: - b.append(" nvarchar(max)").append(nullClause); - break; - case STRING: - b.append(" nvarchar("); - Long len = f.getMaxCharLen(); - if (len == null) { - len = PersistConsts.DEFAULT_MAX_STRING_LENGTH; - } - if (len > MAX_IN_ROW_NVARCHAR) { - // store value out-of-row - b.append("max"); - } else { - b.append(len.toString()); - } - b.append(K_CLOSE_PAREN).append(nullClause); - break; - case BOOLEAN: - b.append(" bit").append(nullClause); - break; - case INTEGER: - Integer int_digits = f.getNumericPrecision(); - if (int_digits == null) { - int_digits = DEFAULT_INT_NUMERIC_PRECISION; - } - - if (int_digits.compareTo(9) > 0) { - b.append(" bigint").append(nullClause); - } else { - b.append(" integer").append(nullClause); - } - break; - case DECIMAL: - if (f == relation.primaryKey) { - throw new IllegalStateException("cannot use decimal columns as primary keys"); - } - - if (f.isDoublePrecision()) { - b.append(" float(53) ").append(nullClause); - } else { - Integer dbl_digits = f.getNumericPrecision(); - Integer dbl_fract = f.getNumericScale(); - if (dbl_digits == null) { - dbl_digits = DEFAULT_DBL_NUMERIC_PRECISION; - } - if (dbl_fract == null) { - dbl_fract = DEFAULT_DBL_NUMERIC_SCALE; - } - b.append(" decimal("); - b.append(dbl_digits.toString()); - b.append(K_CS); - b.append(dbl_fract.toString()); - b.append(K_CLOSE_PAREN).append(nullClause); - } - break; - case DATETIME: - b.append(" datetime2(7)").append(nullClause); - break; - case URI: - b.append(" nvarchar("); - len = f.getMaxCharLen(); - if (len == null) { - len = PersistConsts.URI_STRING_LEN; - } - b.append(len.toString()); - b.append(")").append(nullClause); - break; - } - - if (f == relation.primaryKey) { - b.append(" PRIMARY KEY NONCLUSTERED "); - } - } - b.append(K_CLOSE_PAREN); - - if ( countColumns > MAX_BIND_PARAMS ) { - throw new IllegalArgumentException("Table size exceeds bind parameter limit"); - } - - String createTableStmt = b.toString(); - LogFactory.getLog(DatastoreImpl.class).info("Attempting: " + createTableStmt); - - jc.execute(createTableStmt); - LogFactory.getLog(DatastoreImpl.class) - .info("create table success (before updateRelation): " + relation.getTableName()); - - boolean alreadyClustered = false; - String idx; - // create other indicies - for (DataField f : relation.getFieldList()) { - if ((f.getIndexable() != IndexType.NONE) && (f != relation.primaryKey)) { - idx = relation.getTableName() + "_" + shortPrefix(f.getName()); - alreadyClustered = createIndex(jc, relation, idx, f, alreadyClustered); - } - } - - // and update the relation with actual dimensions... - updateRelation(jc, relation, createTableStmt); - tm.commit(status); - } - } catch (Exception e) { - if (status != null) { - tm.rollback(status); - } - throw new ODKDatastoreException(e); - } - } - - /** - * Construct a 3-character or more prefix for use in the index name. - * - * @param name - * @return - */ - private String shortPrefix(String name) { - StringBuilder b = new StringBuilder(); - String[] splits = name.split("_"); - for (int i = 0; i < splits.length; ++i) { - if (splits[i].length() > 0) { - b.append(splits[i].charAt(0)); - } - } - if (b.length() < 3) { - b.append(Integer.toString(name.length() % 10)); - } - return b.toString().toLowerCase(); - } - - private boolean createIndex(JdbcTemplate jc, CommonFieldsBase tbl, String idxName, DataField field, boolean alreadyClustered) { - StringBuilder b = new StringBuilder(); - - if ( field.getDataType() == DataType.DECIMAL ) { - // don't allow this. It will conflict with our handling of special values. - throw new IllegalStateException("Cannot index decimal fields"); - } - // the options are non-clustered or clustered. - // there can only be one clustered index per table. - if (field.getIndexable() == IndexType.HASH || alreadyClustered) { - b.append(K_CREATE_NONCLUSTERED_INDEX); - } else { - b.append(K_CREATE_CLUSTERED_INDEX); - alreadyClustered = true; - } - b.append(K_BQ); - b.append(idxName); - b.append(K_BQ); - b.append(K_ON); - b.append(K_BQ); - b.append(tbl.getSchemaName()); - b.append(K_BQ); - b.append("."); - b.append(K_BQ); - b.append(tbl.getTableName()); - b.append(K_BQ); - b.append(" ("); - b.append(K_BQ); - b.append(field.getName()); - b.append(K_BQ); - b.append(" )"); - - jc.execute(b.toString()); - return alreadyClustered; - } - - @Override - public boolean hasRelation(String schema, String tableName, User user) { - dam.recordQueryUsage(TableDefinition.INFORMATION_SCHEMA_COLUMNS, 1); - String qs = TableDefinition.TABLE_EXISTS_QUERY; - Integer columnCount = getJdbcConnection().queryForObject(qs, new Object[] { schema, tableName }, - Integer.class); - return (columnCount != null && columnCount != 0); - } - - @Override - public void dropRelation(CommonFieldsBase relation, User user) throws ODKDatastoreException { - try { - StringBuilder b = new StringBuilder(); - b.append(K_DROP_TABLE); - b.append(K_BQ); - b.append(relation.getSchemaName()); - b.append(K_BQ); - b.append("."); - b.append(K_BQ); - b.append(relation.getTableName()); - b.append(K_BQ); - - LogFactory.getLog(DatastoreImpl.class) - .info("Executing " + b.toString() + " by user " + user.getUriUser()); - getJdbcConnection().execute(b.toString()); - } catch (Exception e) { - LogFactory.getLog(DatastoreImpl.class) - .warn(relation.getTableName() + " exception: " + e.toString()); - throw new ODKDatastoreException(e); - } - } - - /*************************************************************************** - * Entity manipulation APIs - * - */ - - @SuppressWarnings("unchecked") - @Override - public T createEntityUsingRelation(T relation, User user) { - - // we are generating our own PK, so we don't need to interact with DB - // yet... - T row; - try { - row = (T) relation.getEmptyRow(user); - } catch (Exception e) { - throw new IllegalArgumentException("failed to create empty row", e); - } - return row; - } - - @SuppressWarnings("unchecked") - @Override - public T getEntity(T relation, String uri, User user) - throws ODKEntityNotFoundException { - Query query = new QueryImpl(relation, "getEntity", this, user); - query.addFilter(relation.primaryKey, FilterOperation.EQUAL, uri); - dam.recordGetUsage(relation); - try { - List results = query.executeQuery(); - if (results == null || results.size() != 1) { - throw new ODKEntityNotFoundException("Unable to retrieve " + relation.getSchemaName() + "." - + relation.getTableName() + " key: " + uri); - } - return (T) results.get(0); - } catch (ODKDatastoreException e) { - throw new ODKEntityNotFoundException("Unable to retrieve " + relation.getSchemaName() + "." - + relation.getTableName() + " key: " + uri, e); - } - } - - @Override - public Query createQuery(CommonFieldsBase relation, String loggingContextTag, User user) { - Query query = new QueryImpl(relation, loggingContextTag, this, user); - return query; - } - - private static class ReusableStatementSetter implements PreparedStatementSetter { - - String sql = null; - List argList = null; - - ReusableStatementSetter() { - }; - - ReusableStatementSetter(String sql, List args) { - this.sql = sql; - this.argList = args; - } - - public void setArgList(String sql, List args) { - this.sql = sql; - this.argList = args; - } - - private void createLogContent(StringBuilder b, int i, SqlParameterValue arg) { - b.append("\nbinding[").append(i).append("]: type: "); - switch ( arg.getSqlType() ) { - case java.sql.Types.BIT: - b.append("BIT"); - break; - case java.sql.Types.BIGINT: - b.append("BIGINT"); - break; - case java.sql.Types.DECIMAL: - b.append("DECIMAL"); - break; - case java.sql.Types.DOUBLE: - b.append("DOUBLE"); - break; - case java.sql.Types.TIMESTAMP: - b.append("TIMESTAMP"); - break; - case java.sql.Types.NVARCHAR: - b.append("NVARCHAR"); - break; - case java.sql.Types.VARBINARY: - b.append("VARBINARY"); - break; - default: - b.append("**").append(arg.getSqlType()).append("**"); - } - if ( arg.getValue() == null ) { - b.append(" is null"); - } else { - b.append(" = ").append(arg.getValue()); - } - } - - @Override - public void setValues(PreparedStatement ps) throws SQLException { - if ( logBindDetails ) { - StringBuilder b = new StringBuilder(); - b.append(sql); - for (int i = 0; i < argList.size(); ++i) { - SqlParameterValue arg = argList.get(i); - createLogContent(b, i+1, arg); - } - LogFactory.getLog(DatastoreImpl.class).info(b.toString()); - } - for (int i = 0; i < argList.size(); ++i) { - SqlParameterValue arg = argList.get(i); - if ((arg.getSqlType() == java.sql.Types.LONGVARBINARY) || - (arg.getSqlType() == java.sql.Types.VARBINARY)) { - if (arg.getValue() == null) { - ps.setNull(i + 1, arg.getSqlType()); - } else { - ps.setBytes(i + 1, (byte[]) arg.getValue()); - } - } else if (arg.getSqlType() == java.sql.Types.TIMESTAMP) { - // we actually bind an iso8601 string - if ( arg.getValue() == null ) { - // seems to require a type vs. Types.NULL - ps.setNull(i + 1, java.sql.Types.NVARCHAR); - } else { - ps.setObject(i + 1, arg.getValue(), java.sql.Types.NVARCHAR); - } - } else if (arg.getSqlType() == java.sql.Types.DECIMAL) { - // nulls don't go through as DECIMAL -- assert they are strings - if ( arg.getValue() == null ) { - // DECIMAL seems to require a type but doesn't like itself - ps.setNull(i + 1, java.sql.Types.NVARCHAR); - } else { - ps.setObject(i + 1, arg.getValue(), arg.getSqlType()); - } - } else if (arg.getValue() == null) { - ps.setNull(i + 1, arg.getSqlType()); - } else { - ps.setObject(i + 1, arg.getValue(), arg.getSqlType()); - } - } - } - } - - @Override - public void putEntity(CommonFieldsBase entity, User user) throws ODKEntityPersistException { - dam.recordPutUsage(entity); - try { - boolean first; - StringBuilder b = new StringBuilder(); - if (entity.isFromDatabase()) { - // we need to do an update - entity.setDateField(entity.lastUpdateDate, new Date()); - entity.setStringField(entity.lastUpdateUriUser, user.getUriUser()); - - b.append(K_UPDATE); - b.append(K_BQ); - b.append(entity.getSchemaName()); - b.append(K_BQ); - b.append("."); - b.append(K_BQ); - b.append(entity.getTableName()); - b.append(K_BQ); - b.append(K_SET); - - ArrayList pv = new ArrayList(); - - first = true; - // fields... - for (DataField f : entity.getFieldList()) { - // primary key goes in the where clause... - if (f == entity.primaryKey) - continue; - if (!first) { - b.append(K_CS); - } - first = false; - b.append(K_BQ); - b.append(f.getName()); - b.append(K_BQ); - - b.append(K_EQ); - b.append(K_BIND_VALUE); - buildArgumentList(pv, entity, f); - } - b.append(K_WHERE); - b.append(K_BQ); - b.append(entity.primaryKey.getName()); - b.append(K_BQ); - b.append(K_EQ); - b.append(K_BIND_VALUE); - buildArgumentList(pv, entity, entity.primaryKey); - - // update... - String sql = b.toString(); - ReusableStatementSetter setter = new ReusableStatementSetter(sql, pv); - getJdbcConnection().update(sql, setter); - } else { - // not yet in database -- insert - b.append(K_INSERT_INTO); - b.append(K_BQ); - b.append(entity.getSchemaName()); - b.append(K_BQ); - b.append("."); - b.append(K_BQ); - b.append(entity.getTableName()); - b.append(K_BQ); - first = true; - b.append(K_OPEN_PAREN); - // fields... - for (DataField f : entity.getFieldList()) { - if (!first) { - b.append(K_CS); - } - first = false; - b.append(K_BQ); - b.append(f.getName()); - b.append(K_BQ); - } - b.append(K_CLOSE_PAREN); - b.append(K_VALUES); - - ArrayList pv = new ArrayList(); - - first = true; - b.append(K_OPEN_PAREN); - // fields... - for (DataField f : entity.getFieldList()) { - if (!first) { - b.append(K_CS); - } - first = false; - b.append(K_BIND_VALUE); - buildArgumentList(pv, entity, f); - } - b.append(K_CLOSE_PAREN); - - // insert... - String sql = b.toString(); - ReusableStatementSetter setter = new ReusableStatementSetter(sql, pv); - getJdbcConnection().update(sql, setter); - entity.setFromDatabase(true); // now it is in the database... - } - } catch (Exception e) { - throw new ODKEntityPersistException(e); - } - } - - @Override - public void putEntities(Collection entityList, User user) - throws ODKEntityPersistException { - for (CommonFieldsBase d : entityList) { - putEntity(d, user); - } - } - - private static final class BatchStatementFieldSetter implements BatchPreparedStatementSetter { - - final String sql; - final List > batchArgs; - ReusableStatementSetter setter = new ReusableStatementSetter(); - - BatchStatementFieldSetter(String sql, List > batchArgs) { - this.sql = sql; - this.batchArgs = batchArgs; - } - - @Override - public int getBatchSize() { - return batchArgs.size(); - } - - @Override - public void setValues(PreparedStatement ps, int idx) throws SQLException { - List argArray = batchArgs.get(idx); - setter.setArgList(sql, argArray); - setter.setValues(ps); - } - } - - @Override - public void batchAlterData(List changes, User user) - throws ODKEntityPersistException { - if (changes.isEmpty()) { - return; - } - - // we need to be careful -- SqlServer only allows a small number of - // bind parameters on a request. This severely limits the batch size - // that can be sent. - CommonFieldsBase firstEntity = changes.get(0); - int maxPerBatch = (MAX_BIND_PARAMS / firstEntity.getFieldList().size()); - for ( int idxStart = 0; idxStart < changes.size() ; idxStart += maxPerBatch ) { - int idxAfterEnd = idxStart + maxPerBatch; - if ( idxAfterEnd > changes.size() ) { - idxAfterEnd = changes.size(); - } - partialBatchAlterData(changes, idxStart, idxAfterEnd, user); - } - - } - - private void partialBatchAlterData(List allChanges, - int idxStart, int idxAfterEnd, User user) - throws ODKEntityPersistException { - if (allChanges.isEmpty()) { - return; - } - - boolean generateSQL = true; - String sql = null; - List > batchArgs = new ArrayList >(); - StringBuilder b = new StringBuilder(); - - for (int idx = idxStart ; idx < idxAfterEnd ; ++idx ) { - CommonFieldsBase entity = allChanges.get(idx); - dam.recordPutUsage(entity); - - boolean first; - b.setLength(0); - - ArrayList pv = new ArrayList(); - - if (entity.isFromDatabase()) { - // we need to do an update - entity.setDateField(entity.lastUpdateDate, new Date()); - entity.setStringField(entity.lastUpdateUriUser, user.getUriUser()); - - if (generateSQL) { - b.append(K_UPDATE); - b.append(K_BQ); - b.append(entity.getSchemaName()); - b.append(K_BQ); - b.append("."); - b.append(K_BQ); - b.append(entity.getTableName()); - b.append(K_BQ); - b.append(K_SET); - } - - first = true; - // fields... - for (DataField f : entity.getFieldList()) { - // primary key goes in the where clause... - if (f == entity.primaryKey) - continue; - - if (generateSQL) { - if (!first) { - b.append(K_CS); - } - first = false; - b.append(K_BQ); - b.append(f.getName()); - b.append(K_BQ); - b.append(K_EQ); - b.append(K_BIND_VALUE); - } - - buildArgumentList(pv, entity, f); - } - if (generateSQL) { - b.append(K_WHERE); - b.append(K_BQ); - b.append(entity.primaryKey.getName()); - b.append(K_BQ); - b.append(K_EQ); - b.append(K_BIND_VALUE); - } - buildArgumentList(pv, entity, entity.primaryKey); - - } else { - if (generateSQL) { - // not yet in database -- insert - b.append(K_INSERT_INTO); - b.append(K_BQ); - b.append(entity.getSchemaName()); - b.append(K_BQ); - b.append("."); - b.append(K_BQ); - b.append(entity.getTableName()); - b.append(K_BQ); - first = true; - b.append(K_OPEN_PAREN); - // fields... - for (DataField f : entity.getFieldList()) { - if (!first) { - b.append(K_CS); - } - first = false; - b.append(K_BQ); - b.append(f.getName()); - b.append(K_BQ); - } - b.append(K_CLOSE_PAREN); - b.append(K_VALUES); - b.append(K_OPEN_PAREN); - } - - first = true; - // fields... - for (DataField f : entity.getFieldList()) { - if (generateSQL) { - if (!first) { - b.append(K_CS); - } - first = false; - b.append(K_BIND_VALUE); - } - buildArgumentList(pv, entity, f); - } - - if (generateSQL) { - b.append(K_CLOSE_PAREN); - } - } - - if (generateSQL) { - b.append(K_COLON); - sql = b.toString(); - } - generateSQL = false; - batchArgs.add(pv); - } - - try { - // update... - BatchStatementFieldSetter setter = new BatchStatementFieldSetter(sql, batchArgs); - getJdbcConnection().batchUpdate(sql, setter); - - // if this was an insert, set the fromDatabase flag in the entities - if (!allChanges.get(0).isFromDatabase()) { - for (int idx = idxStart ; idx < idxAfterEnd ; ++idx ) { - CommonFieldsBase entity = allChanges.get(idx); - entity.setFromDatabase(true); - } - } - } catch (Exception e) { - throw new ODKEntityPersistException(e); - } - } - - @Override - public void deleteEntity(EntityKey key, User user) throws ODKDatastoreException { - - dam.recordDeleteUsage(key); - try { - CommonFieldsBase d = key.getRelation(); - - StringBuilder b = new StringBuilder(); - b.append(K_DELETE_FROM); - b.append(K_BQ); - b.append(d.getSchemaName()); - b.append(K_BQ); - b.append("."); - b.append(K_BQ); - b.append(d.getTableName()); - b.append(K_BQ); - b.append(K_WHERE); - b.append(K_BQ); - b.append(d.primaryKey.getName()); - b.append(K_BQ); - b.append(K_EQ); - b.append(K_BIND_VALUE); - - LogFactory.getLog(DatastoreImpl.class).info("Executing " + b.toString() + " with key " - + key.getKey() + " by user " + user.getUriUser()); - getJdbcConnection().update(b.toString(), new Object[] { key.getKey() }); - } catch (Exception e) { - throw new ODKDatastoreException("delete failed", e); - } - } - - @Override - public void deleteEntities(Collection keys, User user) throws ODKDatastoreException { - ODKDatastoreException e = null; - for (EntityKey k : keys) { - try { - deleteEntity(k, user); - } catch (ODKDatastoreException ex) { - ex.printStackTrace(); - if (e == null) { - e = ex; // save the first exception... - } - } - } - if (e != null) - throw e; // throw the first exception... - } - - @Override - public TaskLock createTaskLock(User user) { - return new TaskLockImpl(this, dam, user); - } -} diff --git a/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/QueryImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/QueryImpl.java deleted file mode 100644 index 7e07bbf7e..000000000 --- a/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/QueryImpl.java +++ /dev/null @@ -1,454 +0,0 @@ -/** - * Copyright (C) 2010 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.common.persistence.engine.sqlserver; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.opendatakit.common.persistence.CommonFieldsBase; -import org.opendatakit.common.persistence.DataField; -import org.opendatakit.common.persistence.EntityKey; -import org.opendatakit.common.persistence.Query; -import org.opendatakit.common.persistence.QueryResult; -import org.opendatakit.common.persistence.QueryResumePoint; -import org.opendatakit.common.persistence.engine.EngineUtils; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.security.User; -import org.springframework.jdbc.core.ResultSetExtractor; -import org.springframework.jdbc.core.RowMapper; - -/** - * - * @author wbrunette@gmail.com - * @author mitchellsundt@gmail.com - * - */ -public class QueryImpl implements Query { - - private static final String K_IS_NULL = " IS NULL "; - private static final String K_IS_NOT_NULL = " IS NOT NULL "; - private static final String K_SELECT = "SELECT "; - private static final String K_SELECT_DISTINCT = "SELECT DISTINCT "; - private static final String K_BQ = "\""; - private static final String K_CS = ", "; - private static final String K_FROM = " FROM "; - private static final String K_WHERE = " WHERE "; - private static final String K_AND = " AND "; - private static final String K_IN_OPEN = " IN ("; - private static final String K_IN_CLOSE = ")"; - private static final String K_BIND_VALUE = " ? "; - private static final String K_ORDER_BY = " ORDER BY "; - - private static Map operationMap = new HashMap(); - private static Map directionMap = new HashMap(); - - static { - operationMap.put(FilterOperation.EQUAL, " = "); - operationMap.put(FilterOperation.NOT_EQUAL, " <> "); - operationMap.put(FilterOperation.GREATER_THAN, " > "); - operationMap.put(FilterOperation.GREATER_THAN_OR_EQUAL, " >= "); - operationMap.put(FilterOperation.LESS_THAN, " < "); - operationMap.put(FilterOperation.LESS_THAN_OR_EQUAL, " <= "); - - directionMap.put(Direction.ASCENDING, " ASC "); - directionMap.put(Direction.DESCENDING, " DESC "); - } - - private final CommonFieldsBase relation; - private final DatastoreImpl dataStoreImpl; - private final User user; - - private DataField dominantSortAttr = null; - private Direction dominantSortDirection = null; - private boolean isSortedByUri = false; - - private final StringBuilder queryBindBuilder = new StringBuilder(); - private final List bindValues = new ArrayList(); - private final StringBuilder querySortBuilder = new StringBuilder(); - private final Log queryStringLogger; - - public QueryImpl(CommonFieldsBase relation, String loggingContextTag, - DatastoreImpl dataStoreImpl, User user) { - this.queryStringLogger = LogFactory.getLog("org.opendatakit.common.persistence.LogQueryString." + relation.getSchemaName() + "." + relation.getTableName()); - this.relation = relation; - this.dataStoreImpl = dataStoreImpl; - this.user = user; - } - - private String generateQuery() { - // generate the query - StringBuilder baseQueryBuilder = new StringBuilder(); - - baseQueryBuilder.append(K_SELECT); - - boolean first = true; - for (DataField f : relation.getFieldList()) { - if (!first) { - baseQueryBuilder.append(K_CS); - } - first = false; - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append(f.getName()); - baseQueryBuilder.append(K_BQ); - } - baseQueryBuilder.append(K_FROM); - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append(relation.getSchemaName()); - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append("."); - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append(relation.getTableName()); - baseQueryBuilder.append(K_BQ); - - return baseQueryBuilder.toString(); - } - - private String generateDistinctFieldValueQuery(DataField dataField) { - if (!relation.getFieldList().contains(dataField)) { - throw new IllegalStateException("Attempting to retrieve non-existent data field " - + dataField.getName() + " from " + relation.getSchemaName() + "." - + relation.getTableName()); - } - - StringBuilder baseQueryBuilder = new StringBuilder(); - // generate the query - baseQueryBuilder.append(K_SELECT_DISTINCT); - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append(dataField.getName()); - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append(K_FROM); - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append(relation.getSchemaName()); - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append("."); - baseQueryBuilder.append(K_BQ); - baseQueryBuilder.append(relation.getTableName()); - baseQueryBuilder.append(K_BQ); - - return baseQueryBuilder.toString(); - } - - @Override - public void addFilter(DataField attributeName, FilterOperation op, Object value) { - if (queryBindBuilder.length() == 0) { - queryBindBuilder.append(K_WHERE); - } else { - queryBindBuilder.append(K_AND); - } - queryBindBuilder.append(K_BQ); - queryBindBuilder.append(attributeName.getName()); - queryBindBuilder.append(K_BQ); - if (op.equals(FilterOperation.EQUAL) && value == null) { - queryBindBuilder.append(K_IS_NULL); - } else if (op.equals(FilterOperation.NOT_EQUAL) && value == null) { - queryBindBuilder.append(K_IS_NOT_NULL); - } else { - queryBindBuilder.append(operationMap.get(op)); - queryBindBuilder.append(K_BIND_VALUE); - bindValues.add(DatastoreImpl.getBindValue(attributeName, value)); - } - } - - /** - * Constructs the necessary filter clause to append to the Query filters to - * support continuation cursors. - * - * @param queryContinuationBindBuilder - * @param continuationValue - * @return the updated bindArgs - */ - private ArrayList addContinuationFilter(StringBuilder queryContinuationBindBuilder, - Object continuationValue) { - if (dominantSortAttr == null) { - throw new IllegalStateException("unexpected state"); - } - if (continuationValue == null) { - throw new IllegalStateException("unexpected state"); - } - - if (queryBindBuilder.length() == 0) { - queryContinuationBindBuilder.append(K_WHERE); - } else { - queryContinuationBindBuilder.append(K_AND); - } - queryContinuationBindBuilder.append(K_BQ); - queryContinuationBindBuilder.append(dominantSortAttr.getName()); - queryContinuationBindBuilder.append(K_BQ); - queryContinuationBindBuilder.append(operationMap.get(dominantSortDirection - .equals(Direction.ASCENDING) ? FilterOperation.GREATER_THAN_OR_EQUAL - : FilterOperation.LESS_THAN_OR_EQUAL)); - queryContinuationBindBuilder.append(K_BIND_VALUE); - - ArrayList values = new ArrayList(); - values.addAll(bindValues); - values.add(DatastoreImpl.getBindValue(dominantSortAttr, continuationValue)); - - return values; - } - - @Override - public void addValueSetFilter(DataField attributeName, Collection valueSet) { - if (queryBindBuilder.length() == 0) { - queryBindBuilder.append(K_WHERE); - } else { - queryBindBuilder.append(K_AND); - } - queryBindBuilder.append(K_BQ); - queryBindBuilder.append(attributeName.getName()); - queryBindBuilder.append(K_BQ); - queryBindBuilder.append(K_IN_OPEN); - boolean first = true; - for (Object o : valueSet) { - if (!first) { - queryBindBuilder.append(K_CS); - } - first = false; - queryBindBuilder.append(K_BIND_VALUE); - bindValues.add(DatastoreImpl.getBindValue(attributeName, o)); - } - queryBindBuilder.append(K_IN_CLOSE); - } - - @Override - public void addSort(DataField attributeName, Direction direction) { - if (querySortBuilder.length() == 0) { - querySortBuilder.append(K_ORDER_BY); - } else { - querySortBuilder.append(K_CS); - } - querySortBuilder.append(K_BQ); - querySortBuilder.append(attributeName.getName()); - querySortBuilder.append(K_BQ); - querySortBuilder.append(directionMap.get(direction)); - - // keep track of the dominant sort attribute... - if (dominantSortAttr == null) { - dominantSortAttr = attributeName; - dominantSortDirection = direction; - } - - // track whether or not the PK is a sort criteria - if (attributeName.equals(relation.primaryKey)) { - isSortedByUri = true; - } - } - - @Override - public List executeQuery() throws ODKDatastoreException { - - String query = generateQuery() + queryBindBuilder.toString() + querySortBuilder.toString() - + ";"; - RowMapper rowMapper = null; - rowMapper = new RelationRowMapper(relation, user); - - try { - queryStringLogger.debug(query); - List l = dataStoreImpl.getJdbcConnection().query(query, - bindValues.toArray(), rowMapper); - dataStoreImpl.recordQueryUsage(relation, l.size()); - return l; - } catch (Exception e) { - dataStoreImpl.recordQueryUsage(relation, 0); - e.printStackTrace(); - throw new ODKDatastoreException(e); - } - } - - @Override - public List executeDistinctValueForDataField(DataField dataField) throws ODKDatastoreException { - - String query = generateDistinctFieldValueQuery(dataField) + queryBindBuilder.toString() - + querySortBuilder.toString() + ";"; - - List keys = null; - try { - keys = dataStoreImpl.getJdbcConnection().queryForList(query, bindValues.toArray(), - String.class); - dataStoreImpl.recordQueryUsage(relation, keys.size()); - } catch (Exception e) { - dataStoreImpl.recordQueryUsage(relation, 0); - e.printStackTrace(); - throw new ODKDatastoreException(e); - } - return keys; - } - - @Override - public Set executeForeignKeyQuery(CommonFieldsBase topLevelTable, - DataField topLevelAuri) throws ODKDatastoreException { - - List keys = executeDistinctValueForDataField(topLevelAuri); - - Set keySet = new HashSet(); - for (Object o : keys) { - String key = (String) o; - // we don't have the top level records themselves. Construct the entity - // keys - // from the supplied relation and the value of the AURI fields in the - // records - // we do have. - keySet.add(new EntityKey(topLevelTable, key)); - } - return keySet; - } - - private class CoreResult { - final List results; - final boolean hasMoreResults; - - CoreResult(List results, boolean hasMoreResults) { - this.results = results; - this.hasMoreResults = hasMoreResults; - } - } - - private class RowMapperFilteredResultSetExtractor implements ResultSetExtractor { - - private int readCount = 0; - private final QueryResumePoint startCursor; - private final int fetchLimit; - private final RowMapper rowMapper; - - RowMapperFilteredResultSetExtractor(QueryResumePoint startCursor, int fetchLimit, - RowMapper rowMapper) { - this.startCursor = startCursor; - this.fetchLimit = fetchLimit; - this.rowMapper = rowMapper; - } - - @Override - public CoreResult extractData(ResultSet rs) throws SQLException { - boolean hasMoreResults = false; - List results = new ArrayList(); - String startUri = (startCursor == null) ? null : startCursor.getUriLastReturnedValue(); - boolean beforeUri = (startUri != null); - while (rs.next()) { - ++readCount; - CommonFieldsBase cb = this.rowMapper.mapRow(rs, results.size()); - if (beforeUri) { - if (startUri.equals(cb.getUri())) { - beforeUri = false; - } - } else if (fetchLimit == 0 || results.size() < fetchLimit) { - results.add(cb); - } else { - hasMoreResults = true; - break; - } - } - return new CoreResult(results, hasMoreResults); - } - - public int getReadCount() { - return readCount; - } - - } - - @Override - public QueryResult executeQuery(QueryResumePoint startCursor, int fetchLimit) - throws ODKDatastoreException { - - // we must have at least one sort column defined - if (dominantSortDirection == null) { - throw new IllegalStateException("no sort column defined -- cannot execute cusor-style query"); - } - - // if we don't have any sort on the PK, add one - // direction of PK sort matches that of dominant sort - if (!isSortedByUri) { - addSort(relation.primaryKey, dominantSortDirection); - } - - // for continuation executions of queries - StringBuilder queryContinuationBindBuilder = new StringBuilder(); - List values; - - if (startCursor != null) { - DataField matchingStartCursorAttr = null; - for (DataField d : relation.getFieldList()) { - if (d.getName().equals(startCursor.getAttributeName())) { - matchingStartCursorAttr = d; - break; - } - } - if (matchingStartCursorAttr == null) { - throw new IllegalStateException("unable to find the matching attribute name " - + "for dominant sort attribute in start cursor: " + startCursor.getAttributeName()); - } - - if (!matchingStartCursorAttr.equals(dominantSortAttr)) { - // the dominant sort column is different - // -- the start cursor is not appropriate for this query. - throw new IllegalStateException("start cursor is inappropriate for query"); - } - - Object continuationValue = EngineUtils.getDominantSortAttributeValueFromString( - startCursor.getValue(), dominantSortAttr); - values = addContinuationFilter(queryContinuationBindBuilder, continuationValue); - } else { - values = bindValues; - } - - String query = generateQuery() + queryBindBuilder.toString() - + queryContinuationBindBuilder.toString() + querySortBuilder.toString() + ";"; - RowMapper rowMapper = null; - rowMapper = new RelationRowMapper(relation, user); - RowMapperFilteredResultSetExtractor rse = new RowMapperFilteredResultSetExtractor(startCursor, - fetchLimit, rowMapper); - - try { - CoreResult r; - try { - queryStringLogger.debug(query); - r = dataStoreImpl.getJdbcConnection().query(query, values.toArray(), rse); - } finally { - dataStoreImpl.recordQueryUsage(relation, rse.getReadCount()); - } - - if (r.results.size() == 0) { - return new QueryResult(startCursor, r.results, null, startCursor, false); - } - - // otherwise, we need to get the values of the dominantAttr and uri of the - // last field. - CommonFieldsBase cb; - String value; - // determine the resume cursor... - cb = r.results.get(r.results.size() - 1); - value = EngineUtils.getDominantSortAttributeValueAsString(cb, dominantSortAttr); - QueryResumePoint resumeCursor = new QueryResumePoint(dominantSortAttr.getName(), value, - cb.getUri(), ((startCursor != null) ? startCursor.isForwardCursor() : true)); - // determine the backward cursor... - cb = r.results.get(0); - value = EngineUtils.getDominantSortAttributeValueAsString(cb, dominantSortAttr); - QueryResumePoint backwardCursor = new QueryResumePoint(dominantSortAttr.getName(), value, - cb.getUri(), !((startCursor != null) ? startCursor.isForwardCursor() : true)); - - return new QueryResult(startCursor, r.results, backwardCursor, resumeCursor, r.hasMoreResults); - } catch (Exception e) { - e.printStackTrace(); - throw new ODKDatastoreException(e); - } - } -} diff --git a/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/RelationRowMapper.java b/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/RelationRowMapper.java deleted file mode 100644 index 6dfcf8232..000000000 --- a/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/RelationRowMapper.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (C) 2010 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.common.persistence.engine.sqlserver; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Calendar; -import java.util.Date; -import java.util.SimpleTimeZone; - -import org.opendatakit.common.persistence.CommonFieldsBase; -import org.opendatakit.common.persistence.DataField; -import org.opendatakit.common.persistence.WrappedBigDecimal; -import org.opendatakit.common.security.User; -import org.springframework.jdbc.core.RowMapper; - -/** - * - * @author wbrunette@gmail.com - * @author mitchellsundt@gmail.com - * - */ -public class RelationRowMapper implements RowMapper { - - private final CommonFieldsBase relation; - private final User user; - - RelationRowMapper(CommonFieldsBase relation, User user) { - this.relation = relation; - this.user = user; - } - - @Override - public CommonFieldsBase mapRow(ResultSet rs, int rowNum) throws SQLException { - - CommonFieldsBase row; - try { - row = relation.getEmptyRow(user); - row.setFromDatabase(true); - } catch (Exception e) { - throw new IllegalStateException("failed to create empty row", e); - } - - /** - * Correct for the funky handling of nulls by the various accessors... - */ - for (DataField f : relation.getFieldList()) { - switch (f.getDataType()) { - case BINARY: - byte[] blobBytes = rs.getBytes(f.getName()); - row.setBlobField(f, blobBytes); - break; - case LONG_STRING: - case URI: - case STRING: - row.setStringField(f, rs.getString(f.getName())); - break; - case INTEGER: - long l = rs.getLong(f.getName()); - if (rs.wasNull()) { - row.setLongField(f, null); - } else { - row.setLongField(f, Long.valueOf(l)); - } - break; - case DECIMAL: { - String value = rs.getString(f.getName()); - if ( value == null ) { - row.setNumericField(f, null); - } else { - row.setNumericField(f, new WrappedBigDecimal(value)); - } - } - break; - case BOOLEAN: - Boolean b = rs.getBoolean(f.getName()); - if (rs.wasNull()) { - row.setBooleanField(f, null); - } else { - row.setBooleanField(f, b); - } - break; - case DATETIME: - Calendar cal = Calendar.getInstance(new SimpleTimeZone(0, "UTC")); - Date d = rs.getTimestamp(f.getName(), cal); - if (d == null) { - row.setDateField(f, null); - } else { - row.setDateField(f, (Date) d.clone()); - } - break; - default: - throw new IllegalStateException("Did not expect non-primitive type in column fetch"); - } - } - return row; - } -} diff --git a/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/TaskLockImpl.java b/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/TaskLockImpl.java deleted file mode 100644 index 7a86f1529..000000000 --- a/src/main/java/org/opendatakit/common/persistence/engine/sqlserver/TaskLockImpl.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (C) 2010 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.opendatakit.common.persistence.engine.sqlserver; - -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.commons.logging.LogFactory; -import org.opendatakit.common.persistence.CommonFieldsBase; -import org.opendatakit.common.persistence.DataField; -import org.opendatakit.common.persistence.Datastore; -import org.opendatakit.common.persistence.EntityKey; -import org.opendatakit.common.persistence.ITaskLockType; -import org.opendatakit.common.persistence.TaskLock; -import org.opendatakit.common.persistence.engine.DatastoreAccessMetrics; -import org.opendatakit.common.persistence.exception.ODKDatastoreException; -import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; -import org.opendatakit.common.persistence.exception.ODKTaskLockException; -import org.opendatakit.common.security.User; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.ConnectionCallback; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * - * @author wbrunette@gmail.com - * @author mitchellsundt@gmail.com - * - */ -public class TaskLockImpl implements TaskLock { - - private static final String PERSISTENCE_LAYER_PROBLEM = "Persistence layer failure"; - - final DatastoreAccessMetrics dam; - final DatastoreImpl datastore; - final User user; - - TaskLockImpl(DatastoreImpl datastore, DatastoreAccessMetrics dam, User user) { - this.datastore = datastore; - this.dam = dam; - this.user = user; - } - - private static final String K_BQ = "\""; - - private TaskLockTable doTransaction(TaskLockTable entity, long l) - throws ODKEntityNotFoundException, ODKTaskLockException { - boolean first; - - final List stmts = new ArrayList(); - - String uri = entity.getUri(); - - StringBuilder b = new StringBuilder(); - String tableName = K_BQ + datastore.getDefaultSchemaName() + K_BQ + "." + K_BQ - + TaskLockTable.TABLE_NAME + K_BQ; - - b.append("'").append(user.getUriUser().replaceAll("'", "''")).append("'"); - String uriUserInline = b.toString(); - b.setLength(0); - b.append("'").append(uri.replaceAll("'", "''")).append("'"); - String uriLockInline = b.toString(); - b.setLength(0); - b.append("'").append(entity.getFormId().replaceAll("'", "''")).append("'"); - String formIdInline = b.toString(); - b.setLength(0); - b.append("'").append(entity.getTaskType().replaceAll("'", "''")).append("'"); - String taskTypeInline = b.toString(); - b.setLength(0); - b.append("DATEADD(ms,").append(l).append(",SYSUTCDATETIME())"); - String nowPlusLifetimeIntervalMilliseconds = b.toString(); - b.setLength(0); - - b.append("SELECT COUNT(1) FROM ").append(tableName).append(" WITH (TABLOCKX, HOLDLOCK)"); - stmts.add(b.toString()); - b.setLength(0); - - dam.recordPutUsage(TaskLockTable.TABLE_NAME); - if (!entity.isFromDatabase()) { - // insert a new record (prospective lock) - b.append("INSERT INTO "); - b.append(tableName); - b.append(" ("); - first = true; - for (DataField f : entity.getFieldList()) { - if (!first) { - b.append(","); - } - first = false; - b.append(K_BQ); - b.append(f.getName()); - b.append(K_BQ); - } - first = true; - b.append(") VALUES ( "); - for (DataField f : entity.getFieldList()) { - if (!first) { - b.append(","); - } - first = false; - if (f.equals(entity.creationDate) || f.equals(entity.lastUpdateDate)) { - b.append("SYSUTCDATETIME()"); - } else if (f.equals(entity.creatorUriUser) || f.equals(entity.lastUpdateUriUser)) { - b.append(uriUserInline); - } else if (f.equals(entity.formId)) { - b.append(formIdInline); - } else if (f.equals(entity.taskType)) { - b.append(taskTypeInline); - } else if (f.equals(entity.primaryKey)) { - b.append(uriLockInline); - } else if (f.equals(entity.expirationDateTime)) { - b.append(nowPlusLifetimeIntervalMilliseconds); - } else { - throw new IllegalStateException("unexpected case " + f.getName()); - } - } - b.append(")"); - stmts.add(b.toString()); - b.setLength(0); - } else { - // update existing record (prospective lock) - b.append("UPDATE "); - b.append(tableName); - b.append(" SET "); - first = true; - for (DataField f : entity.getFieldList()) { - if (f == entity.primaryKey) - continue; - if (!first) { - b.append(","); - } - first = false; - b.append(K_BQ); - b.append(f.getName()); - b.append(K_BQ); - b.append(" = "); - if (f.equals(entity.creationDate) || f.equals(entity.lastUpdateDate)) { - b.append("SYSUTCDATETIME()"); - } else if (f.equals(entity.creatorUriUser) || f.equals(entity.lastUpdateUriUser)) { - b.append(uriUserInline); - } else if (f.equals(entity.formId)) { - b.append(formIdInline); - } else if (f.equals(entity.taskType)) { - b.append(taskTypeInline); - } else if (f.equals(entity.primaryKey)) { - b.append(uriLockInline); - } else if (f.equals(entity.expirationDateTime)) { - b.append(nowPlusLifetimeIntervalMilliseconds); - } else { - throw new IllegalStateException("unexpected case " + f.getName()); - } - } - b.append(" WHERE "); - b.append(K_BQ); - b.append(entity.primaryKey.getName()); - b.append(K_BQ); - b.append(" = "); - b.append(uriLockInline); - stmts.add(b.toString()); - b.setLength(0); - } - // delete stale locks (don't care who's) - dam.recordDeleteUsage(TaskLockTable.TABLE_NAME); - b.append("DELETE FROM ").append(tableName).append(" WHERE "); - b.append(K_BQ).append(entity.expirationDateTime.getName()).append(K_BQ).append(" <= SYSUTCDATETIME()"); - stmts.add(b.toString()); - b.setLength(0); - // delete prospective locks which are not the oldest for that resource and - // task type - dam.recordDeleteUsage(TaskLockTable.TABLE_NAME); - b.append("DELETE FROM ").append(tableName).append(" WHERE "); - b.append(K_BQ).append(entity.formId.getName()).append(K_BQ).append(" = ") - .append(formIdInline).append(" AND "); - b.append(K_BQ).append(entity.taskType.getName()).append(K_BQ).append(" = ") - .append(taskTypeInline).append(" AND "); - b.append(K_BQ).append(entity.expirationDateTime.getName()).append(K_BQ); - b.append(" > (SELECT MIN(t3.").append(K_BQ).append(entity.expirationDateTime.getName()) - .append(K_BQ); - b.append(") FROM ").append(tableName).append(" AS t3 WHERE t3."); - b.append(K_BQ).append(entity.formId.getName()).append(K_BQ).append(" = ").append(formIdInline) - .append(" AND t3."); - b.append(K_BQ).append(entity.taskType.getName()).append(K_BQ).append(" = ") - .append(taskTypeInline).append(")"); - stmts.add(b.toString()); - b.setLength(0); - // delete our entry if it collides with another entry with exactly - // this time. - b.append("DELETE FROM ").append(tableName).append(" WHERE "); - b.append(K_BQ).append(entity.formId.getName()).append(K_BQ).append(" = ") - .append(formIdInline).append(" AND "); - b.append(K_BQ).append(entity.taskType.getName()).append(K_BQ).append(" = ") - .append(taskTypeInline).append(" AND "); - b.append(K_BQ).append(entity.primaryKey.getName()).append(K_BQ).append(" = ") - .append(uriLockInline).append(" AND "); - b.append("1 < (SELECT COUNT(t3.").append(K_BQ).append(entity.expirationDateTime.getName()) - .append(K_BQ); - b.append(") FROM ").append(tableName).append(" AS t3 WHERE t3."); - b.append(K_BQ).append(entity.formId.getName()).append(K_BQ).append(" = ").append(formIdInline) - .append(" AND t3."); - b.append(K_BQ).append(entity.taskType.getName()).append(K_BQ).append(" = ") - .append(taskTypeInline).append(")"); - stmts.add(b.toString()); - b.setLength(0); - // assert: only the lock that holds the resource for that task type appears - // in the task lock table - TaskLockTable relation; - try { - - JdbcTemplate jdbc = datastore.getJdbcConnection(); - jdbc.execute(new ConnectionCallback() { - - @Override - public Object doInConnection(Connection conn) throws SQLException, DataAccessException { - boolean oldAutoCommitValue = conn.getAutoCommit(); - int oldTransactionValue = conn.getTransactionIsolation(); - try { - conn.setAutoCommit(false); - conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); - Statement stmt = conn.createStatement(); - for (String s : stmts) { - // for debugging: LogFactory.getLog(TaskLockImpl.class).info(s); - stmt.execute(s); - } - conn.commit(); - } catch (Exception e) { - e.printStackTrace(); - conn.rollback(); - } - conn.setTransactionIsolation(oldTransactionValue); - conn.setAutoCommit(oldAutoCommitValue); - return null; - } - - }); - - relation = TaskLockTable.assertRelation(datastore, user); - } catch (Exception e) { - throw new ODKTaskLockException(PERSISTENCE_LAYER_PROBLEM, e); - } - return (TaskLockTable) datastore.getEntity(relation, entity.getUri(), user); - } - - @Override - public boolean obtainLock(String lockId, String formId, ITaskLockType taskType) { - boolean result = false; - try { - TaskLockTable relation = TaskLockTable.assertRelation(datastore, user); - TaskLockTable entity = datastore.createEntityUsingRelation(relation, user); - entity.setStringField(entity.primaryKey, lockId); - entity.setFormId(formId); - entity.setTaskType(taskType.getName()); - entity = doTransaction(entity, taskType.getLockExpirationTimeout()); - result = true; - } catch (ODKEntityNotFoundException e) { - // didn't gain the lock... - } catch (ODKTaskLockException e) { - // unexpected failure... - e.printStackTrace(); - } catch (ODKDatastoreException e) { - // unexpected failure... - e.printStackTrace(); - } - return result; - } - - @Override - public boolean renewLock(String lockId, String formId, ITaskLockType taskType) { - boolean result = false; - try { - TaskLockTable relation = TaskLockTable.assertRelation(datastore, user); - TaskLockTable entity = datastore.getEntity(relation, lockId, user); - if (!(entity.getFormId().equals(formId) && entity.getTaskType().equals(taskType.getName()))) { - throw new IllegalArgumentException("formId or taskType don't match datastore values"); - } - entity = doTransaction(entity, taskType.getLockExpirationTimeout()); - result = true; - } catch (IllegalArgumentException e) { - // unexpected failure... - e.printStackTrace(); - } catch (ODKEntityNotFoundException e) { - // unexpected failure... - e.printStackTrace(); - } catch (ODKDatastoreException e) { - // unexpected failure... - e.printStackTrace(); - } catch (ODKTaskLockException e) { - // unexpected failure... - e.printStackTrace(); - } - return result; - } - - @Override - public boolean releaseLock(String lockId, String formId, ITaskLockType taskType) { - boolean result = false; - try { - TaskLockTable relation = TaskLockTable.assertRelation(datastore, user); - // we don't have the record that we want to delete; construct - // the entity key from the relation and the URI for the record. - datastore.deleteEntity(new EntityKey(relation, lockId), user); - result = true; - } catch (ODKDatastoreException e) { - // if we see a lot of these, we are running too long between renewals - LogFactory.getLog(TaskLockImpl.class).info("delete of taskLock threw exception!"); - e.printStackTrace(); - } - return result; - } - - private static class TaskLockTable extends CommonFieldsBase { - static final String TABLE_NAME = "_task_lock"; - - private static final DataField FORM_ID = new DataField("FORM_ID", DataField.DataType.STRING, - false, DatastoreImpl.MAX_IN_ROW_NVARCHAR); - private static final DataField TASK_TYPE = new DataField("TASK_TYPE", - DataField.DataType.STRING, false, 80L); - private static final DataField EXPIRATION_DATETIME = new DataField("EXPIRATION_DATETIME", - DataField.DataType.DATETIME, true); - - DataField formId; - DataField taskType; - DataField expirationDateTime; - - TaskLockTable(String schema) { - super(schema, TABLE_NAME); - fieldList.add(formId = new DataField(FORM_ID)); - fieldList.add(taskType = new DataField(TASK_TYPE)); - fieldList.add(expirationDateTime = new DataField(EXPIRATION_DATETIME)); - } - - TaskLockTable(TaskLockTable ref, User user) { - super(ref, user); - formId = ref.formId; - taskType = ref.taskType; - expirationDateTime = ref.expirationDateTime; - } - - String getFormId() { - return getStringField(formId); - } - - void setFormId(String value) { - if (!setStringField(formId, value)) { - throw new IllegalStateException("overflow formId"); - } - } - - String getTaskType() { - return getStringField(taskType); - } - - void setTaskType(String value) { - if (!setStringField(taskType, value)) { - throw new IllegalStateException("overflow taskType"); - } - } - - @SuppressWarnings("unused") - Date getExpirationDateTime() { - return getDateField(expirationDateTime); - } - - @SuppressWarnings("unused") - void setExpirationDateTime(Date value) { - setDateField(expirationDateTime, value); - } - - @Override - public CommonFieldsBase getEmptyRow(User user) { - return new TaskLockTable(this, user); - } - - static TaskLockTable relation = null; - - static synchronized final TaskLockTable assertRelation(Datastore datastore, User user) - throws ODKDatastoreException { - if (relation == null) { - TaskLockTable relationPrototype; - relationPrototype = new TaskLockTable(datastore.getDefaultSchemaName()); - datastore.assertRelation(relationPrototype, user); - relation = relationPrototype; - } - return relation; - } - } -} diff --git a/src/main/java/org/opendatakit/common/security/User.java b/src/main/java/org/opendatakit/common/security/User.java index 6e989b938..79c54ce1b 100644 --- a/src/main/java/org/opendatakit/common/security/User.java +++ b/src/main/java/org/opendatakit/common/security/User.java @@ -15,10 +15,10 @@ */ package org.opendatakit.common.security; -import java.util.Set; - import org.springframework.security.core.GrantedAuthority; +import java.util.Set; + /** * Minimal features of a user. Note that the security permissions granted a diff --git a/src/main/java/org/opendatakit/common/security/client/UserSecurityInfo.java b/src/main/java/org/opendatakit/common/security/client/UserSecurityInfo.java index b65edf385..41c0a7f02 100644 --- a/src/main/java/org/opendatakit/common/security/client/UserSecurityInfo.java +++ b/src/main/java/org/opendatakit/common/security/client/UserSecurityInfo.java @@ -16,11 +16,11 @@ package org.opendatakit.common.security.client; +import org.opendatakit.common.security.common.EmailParser; + import java.io.Serializable; import java.util.TreeSet; -import org.opendatakit.common.security.common.EmailParser; - /** * Heavy object comparable to User that is transportable across the GWT interfaces. diff --git a/src/main/java/org/opendatakit/common/security/server/SecurityServiceUtil.java b/src/main/java/org/opendatakit/common/security/server/SecurityServiceUtil.java index 09c0c5786..f128c41be 100644 --- a/src/main/java/org/opendatakit/common/security/server/SecurityServiceUtil.java +++ b/src/main/java/org/opendatakit/common/security/server/SecurityServiceUtil.java @@ -16,10 +16,6 @@ package org.opendatakit.common.security.server; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - import org.opendatakit.aggregate.odktables.rest.entity.PrivilegesInfo; import org.opendatakit.aggregate.odktables.rest.entity.UserInfo; import org.opendatakit.common.persistence.client.exception.DatastoreFailureException; @@ -37,6 +33,19 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.stream.Collectors; +import java.util.stream.Stream; + /** * Common utility methods extracted from the AccessConfigurationServlet so they * can be shared between the servlet and GWT server classes. diff --git a/src/main/java/org/opendatakit/common/security/spring/ActiveDirectoryAuthenticationException.java b/src/main/java/org/opendatakit/common/security/spring/ActiveDirectoryAuthenticationException.java deleted file mode 100644 index 283cc839b..000000000 --- a/src/main/java/org/opendatakit/common/security/spring/ActiveDirectoryAuthenticationException.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * Copyright 2017 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.opendatakit.common.security.spring; - -import org.springframework.security.core.AuthenticationException; - -/** - *

- * Thrown as a translation of an {@link javax.naming.AuthenticationException} when - * attempting to authenticate against Active Directory using - * {@link ActiveDirectoryLdapAuthenticationProvider}. Typically this error is wrapped by - * an {@link AuthenticationException} since it does not provide a user friendly message. - * When wrapped, the original Exception can be caught and - * {@link ActiveDirectoryAuthenticationException} can be accessed using - * {@link AuthenticationException#getCause()} for custom error handling. - *

- *

- * The {@link #getDataCode()} will return the error code associated with the data portion - * of the error message. For example, the following error message would return 773 for - * {@link #getDataCode()}. - *

- * - *
- * javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 775, vece ]
- * 
- * - * @author Rob Winch - */ -@SuppressWarnings("serial") -public final class ActiveDirectoryAuthenticationException extends AuthenticationException { - private final String dataCode; - - ActiveDirectoryAuthenticationException(String dataCode, String message, - Throwable cause) { - super(message, cause); - this.dataCode = dataCode; - } - - public String getDataCode() { - return dataCode; - } -} diff --git a/src/main/java/org/opendatakit/common/security/spring/ActiveDirectoryLdapAuthenticationProvider.java b/src/main/java/org/opendatakit/common/security/spring/ActiveDirectoryLdapAuthenticationProvider.java deleted file mode 100644 index 7bc1fda96..000000000 --- a/src/main/java/org/opendatakit/common/security/spring/ActiveDirectoryLdapAuthenticationProvider.java +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * Copyright 2017 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.opendatakit.common.security.spring; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.naming.AuthenticationException; -import javax.naming.Context; -import javax.naming.NamingEnumeration; -import javax.naming.NamingException; -import javax.naming.OperationNotSupportedException; -import javax.naming.PartialResultException; -import javax.naming.directory.Attribute; -import javax.naming.directory.Attributes; -import javax.naming.directory.DirContext; -import javax.naming.directory.SearchControls; -import javax.naming.directory.SearchResult; -import javax.naming.ldap.InitialLdapContext; -import javax.naming.ldap.LdapName; - -import org.opendatakit.common.persistence.client.exception.DatastoreFailureException; -import org.opendatakit.common.security.User; -import org.opendatakit.common.security.client.UserSecurityInfo; -import org.opendatakit.common.security.client.exception.AccessDeniedException; -import org.opendatakit.common.security.server.SecurityServiceUtil; -import org.opendatakit.common.web.CallingContext; -import org.springframework.dao.IncorrectResultSizeDataAccessException; -import org.springframework.ldap.InvalidNameException; -import org.springframework.ldap.core.DirContextAdapter; -import org.springframework.ldap.core.DirContextOperations; -import org.springframework.ldap.core.support.DefaultDirObjectFactory; -import org.springframework.ldap.support.LdapUtils; -import org.springframework.security.authentication.AccountExpiredException; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.CredentialsExpiredException; -import org.springframework.security.authentication.DisabledException; -import org.springframework.security.authentication.LockedException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.ldap.SpringSecurityLdapTemplate; -import org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Specialized LDAP authentication provider which uses Active Directory configuration - * conventions. - *

- * It will authenticate using the Active Directory - * {@code userPrincipalName} or a custom {@link #setSearchFilter(String) searchFilter} - * in the form {@code username@domain}. If the username does not already end with the - * domain name, the {@code userPrincipalName} will be built by appending the configured - * domain name to the username supplied in the authentication request. If no domain name - * is configured, it is assumed that the username will always contain the domain name. - *

- * The user authorities are obtained from the data contained in the {@code memberOf} - * attribute. - * - *

Active Directory Sub-Error Codes

- * - * When an authentication fails, resulting in a standard LDAP 49 error code, Active - * Directory also supplies its own sub-error codes within the error message. These will be - * used to provide additional log information on why an authentication has failed. Typical - * examples are - * - *
    - *
  • 525 - user not found
  • - *
  • 52e - invalid credentials
  • - *
  • 530 - not permitted to logon at this time
  • - *
  • 532 - password expired
  • - *
  • 533 - account disabled
  • - *
  • 701 - account expired
  • - *
  • 773 - user must reset password
  • - *
  • 775 - account locked
  • - *
- * - * If you set the {@link #setConvertSubErrorCodesToExceptions(boolean) - * convertSubErrorCodesToExceptions} property to {@code true}, the codes will also be used - * to control the exception raised. - * - * @author Luke Taylor - * @author Rob Winch - * @since 3.1 - */ -public final class ActiveDirectoryLdapAuthenticationProvider - extends AbstractLdapAuthenticationProvider - implements DirectoryAwareAuthenticationProvider { - private static final Pattern SUB_ERROR_CODE = Pattern - .compile(".*data\\s([0-9a-f]{3,4}).*"); - - // Error codes - private static final int USERNAME_NOT_FOUND = 0x525; - private static final int INVALID_PASSWORD = 0x52e; - private static final int NOT_PERMITTED = 0x530; - private static final int PASSWORD_EXPIRED = 0x532; - private static final int ACCOUNT_DISABLED = 0x533; - private static final int ACCOUNT_EXPIRED = 0x701; - private static final int PASSWORD_NEEDS_RESET = 0x773; - private static final int ACCOUNT_LOCKED = 0x775; - - private final String domain; - private final String rootDn; - private final String url; - private String ldapUser; - private String ldapPassword; - private boolean convertSubErrorCodesToExceptions; - private String searchFilter = "(&(objectClass=user)(userPrincipalName={0}))"; - - // Only used to allow tests to substitute a mock LdapContext - ContextFactory contextFactory = new ContextFactory(); - - /** - * @param domain the domain name (may be null or empty) - * @param url an LDAP url (or multiple URLs) - * @param rootDn the root DN (may be null or empty) - */ - public ActiveDirectoryLdapAuthenticationProvider(String domain, String url, - String rootDn) { - Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty"); - this.domain = StringUtils.hasText(domain) ? domain.toLowerCase() : null; - this.url = url; - this.rootDn = StringUtils.hasText(rootDn) ? rootDn.toLowerCase() : null; - } - - /** - * @param domain the domain name (may be null or empty) - * @param url an LDAP url (or multiple URLs) - */ - public ActiveDirectoryLdapAuthenticationProvider(String domain, String url) { - Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty"); - this.domain = StringUtils.hasText(domain) ? domain.toLowerCase() : null; - this.url = url; - rootDn = this.domain == null ? null : rootDnFromDomain(this.domain); - } - - public String getLdapUser() { - return ldapUser; - } - - public void setLdapUser(String ldapUser) { - this.ldapUser = ldapUser; - } - - public String getLdapPassword() { - return ldapPassword; - } - - public void setLdapPassword(String ldapPassword) { - this.ldapPassword = ldapPassword; - } - - private PrefixedAuthoritiesMapper savedAuthoritiesMapper; - - public void setAuthoritiesMapper(PrefixedAuthoritiesMapper authoritiesMapper) { - Assert.notNull(authoritiesMapper); - - this.savedAuthoritiesMapper = authoritiesMapper; - super.setAuthoritiesMapper(authoritiesMapper); - } - - public PrefixedAuthoritiesMapper getGrantedAuthoritiesMapper() { - return savedAuthoritiesMapper; - } - - public String getUrl() { - return url; - } - - public String getRootDn() { - return rootDn; - } - - public String getSearchFilter() { - return searchFilter; - } - - /** - * @param cc - * @return the defaultGroup of the current user or null. - * This is the defaultGroup from the LDAP system - * (on ActiveDirectory, it is found in streetAddress) - * This may not be a group in which the user belongs. - * The caller is responsible for filtering out those - * before making use of this value. - */ - @Override - public String getDefaultGroup(CallingContext cc) { - final String username = getLdapUser(); - final String password = getLdapPassword(); - - DirContext context = bindAsUser(username, password); - - try { - SearchControls searchControls = new SearchControls(); - searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - - String uri = cc.getCurrentUser().getUriUser(); - String bindPrincipal = createBindPrincipal(uri); - String searchRoot = rootDn != null ? rootDn - : searchRootFromPrincipal(bindPrincipal); - - DirContextOperations userRecord = - SpringSecurityLdapTemplate.searchForSingleEntryInternal(context, - searchControls, searchRoot, searchFilter, - new Object[] { bindPrincipal }); - - Assert.notNull(userRecord, - "No object returned by search, DirContext is not correctly configured"); - - String[] cnDefaultGroupList = userRecord.getStringAttributes("streetAddress"); - if (cnDefaultGroupList == null || cnDefaultGroupList.length == 0) { - return null; - } - - String cnDefaultGroup = cnDefaultGroupList[0]; - - LdapName name = LdapUtils.newLdapName(cnDefaultGroup); - - try { - // see if the group exists - context.getAttributes(name, new String[]{"memberOf"}); - } catch (NamingException e) { - logger.error("Failed to locate directory entry for group: " + cnDefaultGroup, e); - return null; - } - - String rawGroupName = name.getRdn(name.getRdns().size() - 1).getValue().toString(); - - String groupPrefix = getGrantedAuthoritiesMapper().getGroupPrefix(); - - return SecurityServiceUtil.resolveAsGroupOrRoleAuthority(groupPrefix, rawGroupName); - - } catch (NamingException e) { - logger.error("Error retrieving default group (streetAddress) for user: " + username, e); - return null; - } catch (InvalidNameException e) { - logger.error("Error retrieving default group (streetAddress) for user: " + username, e); - return null; - } finally { - LdapUtils.closeContext(context); - } - } - - /** - * Return all registered users and the Anonymous user. - * Invoked from SecurityServiceUtils - * - * @param withAuthorities - * @param cc - * @return - * @throws AccessDeniedException - * @throws DatastoreFailureException - */ - @Override - public ArrayList getAllUsers(boolean withAuthorities, CallingContext cc) - throws AccessDeniedException, DatastoreFailureException { - - ArrayList results = new ArrayList(); - ArrayList users = new ArrayList(); - - final String username = getLdapUser(); - final String password = getLdapPassword(); - - DirContext context = bindAsUser(username, password); - - try { - SearchControls searchControls = new SearchControls(); - searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - String searchFilter = "(&(objectClass=user)(objectClass=organizationalPerson))"; - boolean RETURN_OBJECT = true; - - SearchControls wrappedControls = new SearchControls(searchControls.getSearchScope(), - searchControls.getCountLimit(), searchControls.getTimeLimit(), - searchControls.getReturningAttributes(), RETURN_OBJECT, - searchControls.getDerefLinkFlag()); - - // final LdapName ctxBaseDn = - // LdapUtils.newLdapName(context.getNameInNamespace()); - final LdapName searchBaseDn = LdapUtils.newLdapName(getRootDn()); - final NamingEnumeration resultsEnum = context.search(searchBaseDn, searchFilter, - null, wrappedControls); - - try { - while (resultsEnum.hasMore()) { - SearchResult searchResult = resultsEnum.next(); - DirContextAdapter dca = (DirContextAdapter) searchResult.getObject(); - Assert.notNull(dca, - "No object returned by search, DirContext is not correctly configured"); - // don't care about users that don't have principal names - String[] userPrincipalNameList = dca.getStringAttributes("userPrincipalName"); - if (userPrincipalNameList == null || userPrincipalNameList.length == 0) { - continue; - } - String[] nameList = dca.getStringAttributes("name"); - UserSecurityInfo i = new UserSecurityInfo(userPrincipalNameList[0], nameList[0], null, - UserSecurityInfo.UserType.REGISTERED); - results.add(dca); - users.add(i); - } - } catch (PartialResultException e) { - try { - resultsEnum.close(); - } catch (NamingException ex) { - ex.printStackTrace(); - } - } - if (withAuthorities) { - // process results - for (int j = 0; j < results.size(); ++j) { - DirContextOperations userData = results.get(j); - - String[] groups = userData.getStringAttributes("memberOf"); - - if (groups == null) { - continue; - } - // groups[] raw list of groups. Each of which might contain - // sub-groups. - // copy these into a Set and then populate a new set with all groups - // as we - // process them for sub-groups. - ArrayList groupsToProcess = new ArrayList(); - groupsToProcess.addAll(Arrays.asList(groups)); - HashSet groupsAlreadyProcessed = new HashSet(); - - while (!groupsToProcess.isEmpty()) { - String group = groupsToProcess.remove(groupsToProcess.size() - 1); - if (groupsAlreadyProcessed.contains(group)) { - continue; - } - groupsAlreadyProcessed.add(group); - try { - Attributes attrs = context.getAttributes(LdapUtils.newLdapName(group), - new String[] { "memberOf" }); - Attribute includedGroups = attrs.get("memberOf"); - if (includedGroups != null) { - for (int i = 0; i < includedGroups.size(); ++i) { - String includedGroup = (String) includedGroups.get(i); - if (!groupsAlreadyProcessed.contains(includedGroup)) { - groupsToProcess.add(includedGroup); - } - } - } - } catch (NamingException e) { - e.printStackTrace(); - } - } - - ArrayList authorities = new ArrayList( - groupsAlreadyProcessed.size()); - - for (String group : groupsAlreadyProcessed) { - LdapName name = LdapUtils.newLdapName(group); - String groupName = name.getRdn(name.getRdns().size() - 1).getValue().toString(); - authorities.add(new SimpleGrantedAuthority(groupName)); - } - Collection directAuthorities = getGrantedAuthoritiesMapper() - .mapAuthorities(authorities); - - SecurityServiceUtil.setUserAuthenticationLists(users.get(j), directAuthorities); - } - } - } catch (NamingException e) { - e.printStackTrace(); - throw new DatastoreFailureException(e); - } finally { - LdapUtils.closeContext(context); - } - ArrayList filteredUsers = new ArrayList(); - if (withAuthorities) { - for (UserSecurityInfo ui : users) { - if (ui.getGrantedAuthorities().isEmpty()) { - continue; - } - filteredUsers.add(ui); - } - } else { - filteredUsers.addAll(users); - } - - UserSecurityInfo anonymous = new UserSecurityInfo(User.ANONYMOUS_USER, - User.ANONYMOUS_USER_NICKNAME, null, UserSecurityInfo.UserType.ANONYMOUS); - if (withAuthorities) { - SecurityServiceUtil.setAuthenticationListsForAnonymousUser(anonymous, cc); - } - filteredUsers.add(anonymous); - return filteredUsers; - } - - @Override - protected DirContextOperations doAuthentication( - UsernamePasswordAuthenticationToken auth) { - String username = auth.getName(); - String password = (String) auth.getCredentials(); - - DirContext ctx = bindAsUser(username, password); - - try { - return searchForUser(ctx, username); - } - catch (NamingException e) { - logger.error("Failed to locate directory entry for authenticated user: " - + username, e); - throw badCredentials(e); - } - finally { - LdapUtils.closeContext(ctx); - } - } - - /** - * Creates the user authority list from the values of the {@code memberOf} attribute - * obtained from the user's Active Directory entry. - */ - @Override - protected Collection loadUserAuthorities( - DirContextOperations userData, String username, String password) { - String[] groups = userData.getStringAttributes("memberOf"); - - if (groups == null) { - logger.debug("No values for 'memberOf' attribute."); - - return AuthorityUtils.NO_AUTHORITIES; - } - - if (logger.isDebugEnabled()) { - logger.debug("'memberOf' attribute values: " + Arrays.asList(groups)); - } - - // groups[] raw list of groups. Each of which might contain sub-groups. - // copy these into a Set and then populate a new set with all groups as we - // process them for sub-groups. - ArrayList groupsToProcess = new ArrayList(); - groupsToProcess.addAll(Arrays.asList(groups)); - HashSet groupsAlreadyProcessed = new HashSet(); - - DirContext ctx = bindAsUser(username, password); - - try { - while ( !groupsToProcess.isEmpty() ) { - String group = groupsToProcess.remove(groupsToProcess.size()-1); - if ( groupsAlreadyProcessed.contains(group) ) { - continue; - } - groupsAlreadyProcessed.add(group); - try { - Attributes attrs = ctx.getAttributes(LdapUtils.newLdapName(group), new String[]{"memberOf"}); - Attribute includedGroups = attrs.get("memberOf"); - if ( includedGroups != null ) { - for ( int i = 0 ; i < includedGroups.size() ; ++i ) { - String includedGroup = (String) includedGroups.get(i); - if ( !groupsAlreadyProcessed.contains(includedGroup) ) { - groupsToProcess.add(includedGroup); - } - } - } - } catch (NamingException e) { - logger.error("Failed to locate directory entry for group: " + group, e); - } - } - } - finally { - LdapUtils.closeContext(ctx); - } - - ArrayList authorities = new ArrayList( - groupsAlreadyProcessed.size()); - - for (String group : groupsAlreadyProcessed) { - LdapName name = LdapUtils.newLdapName(group); - String groupName = name.getRdn(name.getRdns().size()-1).getValue().toString(); - authorities.add(new SimpleGrantedAuthority(groupName)); - } - - return authorities; - } - - public DirContext bindAsUser(String username, String password) { - // TODO. add DNS lookup based on domain - final String bindUrl = url; - - Hashtable env = new Hashtable(); - env.put(Context.SECURITY_AUTHENTICATION, "simple"); - String bindPrincipal = createBindPrincipal(username); - env.put(Context.SECURITY_PRINCIPAL, bindPrincipal); - env.put(Context.PROVIDER_URL, bindUrl); - env.put(Context.SECURITY_CREDENTIALS, password); - env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - env.put(Context.OBJECT_FACTORIES, DefaultDirObjectFactory.class.getName()); - - try { - return contextFactory.createContext(env); - } - catch (NamingException e) { - if ((e instanceof AuthenticationException) - || (e instanceof OperationNotSupportedException)) { - handleBindException(bindPrincipal, e); - throw badCredentials(e); - } - else { - throw LdapUtils.convertLdapException(e); - } - } - } - - private void handleBindException(String bindPrincipal, NamingException exception) { - if (logger.isDebugEnabled()) { - logger.debug("Authentication for " + bindPrincipal + " failed:" + exception); - } - - int subErrorCode = parseSubErrorCode(exception.getMessage()); - - if (subErrorCode <= 0) { - logger.debug("Failed to locate AD-specific sub-error code in message"); - return; - } - - logger.info("Active Directory authentication failed: " - + subCodeToLogMessage(subErrorCode)); - - if (convertSubErrorCodesToExceptions) { - raiseExceptionForErrorCode(subErrorCode, exception); - } - } - - private int parseSubErrorCode(String message) { - Matcher m = SUB_ERROR_CODE.matcher(message); - - if (m.matches()) { - return Integer.parseInt(m.group(1), 16); - } - - return -1; - } - - private void raiseExceptionForErrorCode(int code, NamingException exception) { - String hexString = Integer.toHexString(code); - Throwable cause = new ActiveDirectoryAuthenticationException(hexString, - exception.getMessage(), exception); - switch (code) { - case PASSWORD_EXPIRED: - throw new CredentialsExpiredException(messages.getMessage( - "LdapAuthenticationProvider.credentialsExpired", - "User credentials have expired"), cause); - case ACCOUNT_DISABLED: - throw new DisabledException(messages.getMessage( - "LdapAuthenticationProvider.disabled", "User is disabled"), cause); - case ACCOUNT_EXPIRED: - throw new AccountExpiredException(messages.getMessage( - "LdapAuthenticationProvider.expired", "User account has expired"), - cause); - case ACCOUNT_LOCKED: - throw new LockedException(messages.getMessage( - "LdapAuthenticationProvider.locked", "User account is locked"), cause); - default: - throw badCredentials(cause); - } - } - - private String subCodeToLogMessage(int code) { - switch (code) { - case USERNAME_NOT_FOUND: - return "User was not found in directory"; - case INVALID_PASSWORD: - return "Supplied password was invalid"; - case NOT_PERMITTED: - return "User not permitted to logon at this time"; - case PASSWORD_EXPIRED: - return "Password has expired"; - case ACCOUNT_DISABLED: - return "Account is disabled"; - case ACCOUNT_EXPIRED: - return "Account expired"; - case PASSWORD_NEEDS_RESET: - return "User must reset password"; - case ACCOUNT_LOCKED: - return "Account locked"; - } - - return "Unknown (error code " + Integer.toHexString(code) + ")"; - } - - private BadCredentialsException badCredentials() { - return new BadCredentialsException(messages.getMessage( - "LdapAuthenticationProvider.badCredentials", "Bad credentials")); - } - - private BadCredentialsException badCredentials(Throwable cause) { - return (BadCredentialsException) badCredentials().initCause(cause); - } - - private DirContextOperations searchForUser(DirContext context, String username) - throws NamingException { - SearchControls searchControls = new SearchControls(); - searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - - String bindPrincipal = createBindPrincipal(username); - String searchRoot = rootDn != null ? rootDn - : searchRootFromPrincipal(bindPrincipal); - - try { - return SpringSecurityLdapTemplate.searchForSingleEntryInternal(context, - searchControls, searchRoot, searchFilter, - new Object[] { bindPrincipal }); - } - catch (IncorrectResultSizeDataAccessException incorrectResults) { - // Search should never return multiple results if properly configured - just - // rethrow - if (incorrectResults.getActualSize() != 0) { - throw incorrectResults; - } - // If we found no results, then the username/password did not match - UsernameNotFoundException userNameNotFoundException = new UsernameNotFoundException( - "User " + username + " not found in directory.", incorrectResults); - throw badCredentials(userNameNotFoundException); - } - } - - private String searchRootFromPrincipal(String bindPrincipal) { - int atChar = bindPrincipal.lastIndexOf('@'); - - if (atChar < 0) { - logger.debug("User principal '" + bindPrincipal - + "' does not contain the domain, and no domain has been configured"); - throw badCredentials(); - } - - return rootDnFromDomain(bindPrincipal.substring(atChar + 1, - bindPrincipal.length())); - } - - private String rootDnFromDomain(String domain) { - String[] tokens = StringUtils.tokenizeToStringArray(domain, "."); - StringBuilder root = new StringBuilder(); - - for (String token : tokens) { - if (root.length() > 0) { - root.append(','); - } - root.append("dc=").append(token); - } - - return root.toString(); - } - - String createBindPrincipal(String username) { - if (domain == null || username.toLowerCase().endsWith(domain)) { - return username; - } - - return username + "@" + domain; - } - - /** - * By default, a failed authentication (LDAP error 49) will result in a - * {@code BadCredentialsException}. - *

- * If this property is set to {@code true}, the exception message from a failed bind - * attempt will be parsed for the AD-specific error code and a - * {@link CredentialsExpiredException}, {@link DisabledException}, - * {@link AccountExpiredException} or {@link LockedException} will be thrown for the - * corresponding codes. All other codes will result in the default - * {@code BadCredentialsException}. - * - * @param convertSubErrorCodesToExceptions {@code true} to raise an exception based on - * the AD error code. - */ - public void setConvertSubErrorCodesToExceptions( - boolean convertSubErrorCodesToExceptions) { - this.convertSubErrorCodesToExceptions = convertSubErrorCodesToExceptions; - } - - /** - * The LDAP filter string to search for the user being authenticated. Occurrences of - * {0} are replaced with the {@code username@domain}. - *

- * Defaults to: {@code (&(objectClass=user)(userPrincipalName= 0}))} - *

- * - * @param searchFilter the filter string - * - * @since 3.2.6 - */ - public void setSearchFilter(String searchFilter) { - Assert.hasText(searchFilter, "searchFilter must have text"); - this.searchFilter = searchFilter; - } - - static class ContextFactory { - DirContext createContext(Hashtable env) throws NamingException { - return new InitialLdapContext(env, null); - } - } -} - diff --git a/src/main/java/org/opendatakit/common/security/spring/AnonymousAuthenticationFilter.java b/src/main/java/org/opendatakit/common/security/spring/AnonymousAuthenticationFilter.java index 6092dcc05..58bd08ed9 100644 --- a/src/main/java/org/opendatakit/common/security/spring/AnonymousAuthenticationFilter.java +++ b/src/main/java/org/opendatakit/common/security/spring/AnonymousAuthenticationFilter.java @@ -16,15 +16,6 @@ * limitations under the License. */ -import java.io.IOException; -import java.util.HashSet; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; - import org.opendatakit.aggregate.constants.BeanDefs; import org.opendatakit.aggregate.server.ServerPreferencesProperties; import org.opendatakit.aggregate.task.Watchdog; @@ -43,6 +34,14 @@ import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.filter.GenericFilterBean; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.HashSet; + /** * Detects if there is no {@code Authentication} object in the * {@code SecurityContextHolder}, and populates it with one if needed. diff --git a/src/main/java/org/opendatakit/common/security/spring/BasicAuthenticationFilter.java b/src/main/java/org/opendatakit/common/security/spring/BasicAuthenticationFilter.java index 00c90e2b9..ba756e907 100644 --- a/src/main/java/org/opendatakit/common/security/spring/BasicAuthenticationFilter.java +++ b/src/main/java/org/opendatakit/common/security/spring/BasicAuthenticationFilter.java @@ -15,13 +15,13 @@ */ package org.opendatakit.common.security.spring; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; - import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.AuthenticationEntryPoint; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + /** * Wraps the Spring class and ensures that if an Authentication is already * determined for this request, that it isn't overridden. diff --git a/src/main/java/org/opendatakit/common/security/spring/DefaultLdapAuthenticationProvider.java b/src/main/java/org/opendatakit/common/security/spring/DefaultLdapAuthenticationProvider.java index e5b4b5954..c32408e1e 100644 --- a/src/main/java/org/opendatakit/common/security/spring/DefaultLdapAuthenticationProvider.java +++ b/src/main/java/org/opendatakit/common/security/spring/DefaultLdapAuthenticationProvider.java @@ -18,7 +18,13 @@ import javax.naming.directory.SearchControls; import java.text.MessageFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; /** @@ -116,8 +122,8 @@ public DefaultLdapAuthenticationProvider( GroupPrefixAwareAuthoritiesMapper authoritiesMapper) { super(authenticator, authoritiesPopulator); - Assert.notNull(contextSource); - Assert.notNull(authoritiesMapper); + Assert.notNull(contextSource, "contextSource must not be null"); + Assert.notNull(authoritiesMapper, "authoritiesMapper must not be null"); this.authoritiesMapper = authoritiesMapper; this.contextSource = contextSource; diff --git a/src/main/java/org/opendatakit/common/security/spring/Dhis2AuthenticationProvider.java b/src/main/java/org/opendatakit/common/security/spring/Dhis2AuthenticationProvider.java index 4dd20b01d..c1c76bf97 100644 --- a/src/main/java/org/opendatakit/common/security/spring/Dhis2AuthenticationProvider.java +++ b/src/main/java/org/opendatakit/common/security/spring/Dhis2AuthenticationProvider.java @@ -1,15 +1,17 @@ package org.opendatakit.common.security.spring; -import org.opendatakit.common.persistence.client.exception.DatastoreFailureException; import org.opendatakit.common.security.User; import org.opendatakit.common.security.client.UserSecurityInfo; -import org.opendatakit.common.security.client.exception.AccessDeniedException; import org.opendatakit.common.security.server.SecurityServiceUtil; -import org.opendatakit.common.security.spring.dhis2.*; +import org.opendatakit.common.security.spring.dhis2.Dhis2GroupList; +import org.opendatakit.common.security.spring.dhis2.Dhis2ListEntry; +import org.opendatakit.common.security.spring.dhis2.Dhis2OuList; +import org.opendatakit.common.security.spring.dhis2.Dhis2User; +import org.opendatakit.common.security.spring.dhis2.Dhis2UserList; import org.opendatakit.common.web.CallingContext; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.http.client.support.BasicAuthorizationInterceptor; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -148,7 +150,7 @@ public Authentication authenticate(Authentication authentication) throws Authent String password = (String) authentication.getCredentials(); RestTemplate restTemplate = new RestTemplate(); - restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(username, password)); + restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(username, password)); try { restTemplate.headForHeaders(getApiUrl() + ME_ENDPOINT_URL); diff --git a/src/main/java/org/opendatakit/common/security/spring/PortResolverBySchemeImpl.java b/src/main/java/org/opendatakit/common/security/spring/PortResolverBySchemeImpl.java index 1fdc5e848..2e25dec71 100644 --- a/src/main/java/org/opendatakit/common/security/spring/PortResolverBySchemeImpl.java +++ b/src/main/java/org/opendatakit/common/security/spring/PortResolverBySchemeImpl.java @@ -15,10 +15,10 @@ */ package org.opendatakit.common.security.spring; -import javax.servlet.ServletRequest; - import org.springframework.security.web.PortResolver; +import javax.servlet.ServletRequest; + /** * PortResolver that makes its decisions solely based upon the scheme. * This is used by the channel security filter. diff --git a/src/main/java/org/opendatakit/common/security/spring/PrefixedAuthoritiesMapper.java b/src/main/java/org/opendatakit/common/security/spring/PrefixedAuthoritiesMapper.java index 5ac3ba58f..5aa9f88be 100644 --- a/src/main/java/org/opendatakit/common/security/spring/PrefixedAuthoritiesMapper.java +++ b/src/main/java/org/opendatakit/common/security/spring/PrefixedAuthoritiesMapper.java @@ -25,7 +25,7 @@ public String[] getDefaultAuthorities() { } public PrefixedAuthoritiesMapper(String groupPrefix, String[] defaultAuthorities) { - Assert.notNull(groupPrefix); + Assert.notNull(groupPrefix, "groupPrefix cannot be null"); this.groupPrefix = groupPrefix; this.defaultAuthorities = defaultAuthorities; diff --git a/src/main/java/org/opendatakit/common/security/spring/SecurityContextHolderAwareAuthPreservingRequestFilter.java b/src/main/java/org/opendatakit/common/security/spring/SecurityContextHolderAwareAuthPreservingRequestFilter.java index 05825aaae..61f68766a 100644 --- a/src/main/java/org/opendatakit/common/security/spring/SecurityContextHolderAwareAuthPreservingRequestFilter.java +++ b/src/main/java/org/opendatakit/common/security/spring/SecurityContextHolderAwareAuthPreservingRequestFilter.java @@ -15,19 +15,18 @@ * limitations under the License. */ -import java.io.IOException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper; +import org.springframework.util.Assert; +import org.springframework.web.filter.GenericFilterBean; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper; -import org.springframework.util.Assert; -import org.springframework.web.filter.GenericFilterBean; +import java.io.IOException; /** diff --git a/src/main/java/org/opendatakit/common/security/spring/UserImpl.java b/src/main/java/org/opendatakit/common/security/spring/UserImpl.java index 4e7621f70..3d6bc25f8 100644 --- a/src/main/java/org/opendatakit/common/security/spring/UserImpl.java +++ b/src/main/java/org/opendatakit/common/security/spring/UserImpl.java @@ -15,16 +15,16 @@ */ package org.opendatakit.common.security.spring; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - import org.opendatakit.common.security.User; import org.opendatakit.common.security.common.GrantedAuthorityName; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + public class UserImpl implements org.opendatakit.common.security.User { final String nickName; diff --git a/src/main/java/org/opendatakit/common/security/spring/UserServiceImpl.java b/src/main/java/org/opendatakit/common/security/spring/UserServiceImpl.java index 36d8f2d08..24a77a69a 100644 --- a/src/main/java/org/opendatakit/common/security/spring/UserServiceImpl.java +++ b/src/main/java/org/opendatakit/common/security/spring/UserServiceImpl.java @@ -15,10 +15,6 @@ */ package org.opendatakit.common.security.spring; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - import org.opendatakit.common.security.Realm; import org.opendatakit.common.security.SecurityUtils; import org.opendatakit.common.security.User; @@ -29,6 +25,10 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + public class UserServiceImpl implements org.opendatakit.common.security.UserService, InitializingBean { diff --git a/src/main/java/org/opendatakit/common/utils/HtmlUtil.java b/src/main/java/org/opendatakit/common/utils/HtmlUtil.java index 0c7f418b6..827100c19 100644 --- a/src/main/java/org/opendatakit/common/utils/HtmlUtil.java +++ b/src/main/java/org/opendatakit/common/utils/HtmlUtil.java @@ -16,17 +16,17 @@ package org.opendatakit.common.utils; +import org.apache.commons.text.StringEscapeUtils; +import org.opendatakit.common.web.constants.BasicConsts; +import org.opendatakit.common.web.constants.HtmlConsts; +import org.opendatakit.common.web.constants.HtmlStrUtil; + import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.commons.text.StringEscapeUtils; -import org.opendatakit.common.web.constants.BasicConsts; -import org.opendatakit.common.web.constants.HtmlConsts; -import org.opendatakit.common.web.constants.HtmlStrUtil; - public class HtmlUtil extends HtmlStrUtil{ public static final String createHrefWithProperties(String urlBase, Map properties, diff --git a/src/main/java/org/opendatakit/common/utils/HttpClientFactory.java b/src/main/java/org/opendatakit/common/utils/HttpClientFactory.java index 9ab9b9b52..66ec11137 100644 --- a/src/main/java/org/opendatakit/common/utils/HttpClientFactory.java +++ b/src/main/java/org/opendatakit/common/utils/HttpClientFactory.java @@ -15,14 +15,10 @@ */ package org.opendatakit.common.utils; -import java.io.IOException; -import java.security.GeneralSecurityException; - -import org.apache.http.client.config.RequestConfig; -import org.apache.http.config.ConnectionConfig; -import org.apache.http.config.SocketConfig; -import org.apache.http.impl.client.CloseableHttpClient; - +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.io.SocketConfig; /** * Interface for the bean that will construct an HttpClient that is appropriate * for the GAE or Tomcat container in which the application runs. The GAE diff --git a/src/main/java/org/opendatakit/common/utils/WebUtils.java b/src/main/java/org/opendatakit/common/utils/WebUtils.java index 072442b27..37bdeadac 100644 --- a/src/main/java/org/opendatakit/common/utils/WebUtils.java +++ b/src/main/java/org/opendatakit/common/utils/WebUtils.java @@ -13,6 +13,12 @@ */ package org.opendatakit.common.utils; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.javarosa.core.model.utils.DateUtils; +import org.opendatakit.common.web.constants.HtmlConsts; + import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -20,6 +26,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.text.DateFormat; import java.text.ParseException; import java.text.ParsePosition; @@ -30,16 +37,6 @@ import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang3.CharEncoding; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.javarosa.core.model.utils.DateUtils; -import org.opendatakit.common.web.constants.BasicConsts; -import org.opendatakit.common.web.constants.HtmlConsts; - /** * Useful methods for parsing boolean and date values and formatting dates. * @@ -100,7 +97,7 @@ public static String safeEncode(String rawString) { try { ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(out); - gzip.write(rawString.getBytes(CharEncoding.UTF_8)); + gzip.write(rawString.getBytes(StandardCharsets.UTF_8)); gzip.finish(); gzip.close(); String candidate = Base64.encodeBase64URLSafeString(out.toByteArray()); @@ -127,7 +124,7 @@ public static String safeDecode(String encodedWebsafeString) { try { ByteArrayInputStream in = new ByteArrayInputStream(Base64.decodeBase64(encodedWebsafeString - .getBytes(CharEncoding.UTF_8))); + .getBytes(StandardCharsets.UTF_8))); GZIPInputStream gzip = new GZIPInputStream(in); ByteArrayOutputStream out = new ByteArrayOutputStream(); int ch = gzip.read(); @@ -138,7 +135,7 @@ public static String safeDecode(String encodedWebsafeString) { gzip.close(); out.flush(); out.close(); - return new String(out.toByteArray(), CharEncoding.UTF_8); + return new String(out.toByteArray(), StandardCharsets.UTF_8); } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new IllegalArgumentException("Unexpected failure: " + e.toString()); @@ -304,24 +301,6 @@ public static final Date parseDate(String value) { throw new IllegalArgumentException("Unable to parse the date: " + value); } - public static final String asSubmissionDateTimeString(Date d) { - if (d == null) - return null; - return DateUtils.formatDateTime(d, DateUtils.FORMAT_ISO8601); - } - - public static final String asSubmissionDateOnlyString(Date d) { - if (d == null) - return null; - return DateUtils.formatDate(d, DateUtils.FORMAT_ISO8601); - } - - public static final String asSubmissionTimeOnlyString(Date d) { - if (d == null) - return null; - return DateUtils.formatTime(d, DateUtils.FORMAT_ISO8601); - } - /** * Useful static method for constructing a UPPER_CASE persistence layer name * from a camelCase name. This inserts an underscore before a leading capital @@ -358,33 +337,6 @@ public static final String unCamelCase(String name) { return b.toString(); } - /** - * Return the GoogleDocs datetime string representation of a datetime. - * - * @param d - * @return - */ - public static final String googleDocsDateTime(Date d) { - if (d == null) - return null; - SimpleDateFormat asGoogleDoc = new SimpleDateFormat(PATTERN_GOOGLE_DOCS); - asGoogleDoc.setTimeZone(TimeZone.getTimeZone("GMT")); - return asGoogleDoc.format(d); - } - - /** - * Return the GoogleDocs date string representation of a date-only datetime. - * - * @param d - * @return - */ - public static final String googleDocsDateOnly(Date d) { - if (d == null) - return null; - SimpleDateFormat asGoogleDocDateOnly = new SimpleDateFormat(PATTERN_GOOGLE_DOCS_DATE_ONLY); - asGoogleDocDateOnly.setTimeZone(TimeZone.getTimeZone("GMT")); - return asGoogleDocDateOnly.format(d); - } /** * Return the ISO8601 string representation of a date. diff --git a/src/main/java/org/opendatakit/common/utils/tomcat/TomcatHttpClientFactoryImpl.java b/src/main/java/org/opendatakit/common/utils/tomcat/TomcatHttpClientFactoryImpl.java index 6cdaf6f4e..65d14026e 100644 --- a/src/main/java/org/opendatakit/common/utils/tomcat/TomcatHttpClientFactoryImpl.java +++ b/src/main/java/org/opendatakit/common/utils/tomcat/TomcatHttpClientFactoryImpl.java @@ -15,14 +15,12 @@ */ package org.opendatakit.common.utils.tomcat; -import java.io.IOException; -import java.security.GeneralSecurityException; - -import org.apache.http.client.config.RequestConfig; -import org.apache.http.config.ConnectionConfig; -import org.apache.http.config.SocketConfig; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager; +import org.apache.hc.core5.http.io.SocketConfig; import org.opendatakit.common.utils.HttpClientFactory; /** @@ -40,12 +38,21 @@ public TomcatHttpClientFactoryImpl() { public CloseableHttpClient createHttpClient(SocketConfig socketConfig, ConnectionConfig connectionConfig, RequestConfig requestConfig) { HttpClientBuilder builder = HttpClientBuilder.create(); + BasicHttpClientConnectionManager cm = new BasicHttpClientConnectionManager(); + boolean connectionManagerSet = false; + if (socketConfig != null) { - builder.setDefaultSocketConfig(socketConfig); + cm.setSocketConfig(socketConfig); + connectionManagerSet = true; } if (connectionConfig != null) { - builder.setDefaultConnectionConfig(connectionConfig); + cm.setConnectionConfig(connectionConfig); + connectionManagerSet = true; } + if(connectionManagerSet) { + builder.setConnectionManager(cm); + } + if (requestConfig != null) { builder.setDefaultRequestConfig(requestConfig); } diff --git a/src/main/java/org/opendatakit/common/web/CallingContext.java b/src/main/java/org/opendatakit/common/web/CallingContext.java index d726d548b..e75415d37 100644 --- a/src/main/java/org/opendatakit/common/web/CallingContext.java +++ b/src/main/java/org/opendatakit/common/web/CallingContext.java @@ -15,12 +15,12 @@ */ package org.opendatakit.common.web; -import javax.servlet.ServletContext; - import org.opendatakit.common.persistence.Datastore; import org.opendatakit.common.security.User; import org.opendatakit.common.security.UserService; +import javax.servlet.ServletContext; + /** * Context in which the call occurs. * The standard implementation is in ContextFactory. diff --git a/src/main/java/org/opendatakit/common/web/servlet/CommonServletBase.java b/src/main/java/org/opendatakit/common/web/servlet/CommonServletBase.java index 022314fb9..15a7155cf 100644 --- a/src/main/java/org/opendatakit/common/web/servlet/CommonServletBase.java +++ b/src/main/java/org/opendatakit/common/web/servlet/CommonServletBase.java @@ -17,19 +17,6 @@ package org.opendatakit.common.web.servlet; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - import org.apache.commons.logging.Log; import org.opendatakit.common.security.spring.SpringInternals; import org.opendatakit.common.web.CallingContext; @@ -38,6 +25,18 @@ import org.opendatakit.common.web.constants.HtmlStrUtil; import org.springframework.security.web.savedrequest.SavedRequest; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + /** * Base class for Servlets that contain useful utilities * diff --git a/src/main/webapp/WEB-INF/applicationContext-security.xml b/src/main/webapp/WEB-INF/applicationContext-security.xml index 722bd4ab0..d6ec37833 100644 --- a/src/main/webapp/WEB-INF/applicationContext-security.xml +++ b/src/main/webapp/WEB-INF/applicationContext-security.xml @@ -3,7 +3,7 @@ + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-5.6.xsd"> @@ -32,18 +32,9 @@ - + - - - - - - - - - @@ -54,8 +45,6 @@ - - @@ -332,7 +321,7 @@ - + @@ -455,7 +444,7 @@ - + diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 0f0578879..b6a76b98e 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -11,15 +11,6 @@ odk-settings.xml,/WEB-INF/applicationContext-security.xml - - - TaskQueue Interfaces - /gae/* - - - admin - - @@ -48,26 +39,6 @@ serverSpringSecurityFilterChain /* - - - GaeAwareContentEncodingRequestFilter - org.opendatakit.aggregate.odktables.impl.api.wink.GaeAwareContentEncodingRequestFilter - - - - GaeAwareContentEncodingRequestFilter - /odktables/* - - - - GaeAwareContentEncodingResponseFilter - org.opendatakit.aggregate.odktables.impl.api.wink.GaeAwareContentEncodingResponseFilter - - - - GaeAwareContentEncodingResponseFilter - /odktables/* - diff --git a/src/test/java/org/opendatakit/aggregate/SerializationTest.java b/src/test/java/org/opendatakit/aggregate/SerializationTest.java index 222493f2e..5581c542b 100644 --- a/src/test/java/org/opendatakit/aggregate/SerializationTest.java +++ b/src/test/java/org/opendatakit/aggregate/SerializationTest.java @@ -16,12 +16,7 @@ package org.opendatakit.aggregate; -import static org.junit.Assert.assertEquals; - -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; - +import com.fasterxml.jackson.dataformat.xml.XmlMapper; import org.junit.Before; import org.junit.Test; import org.opendatakit.aggregate.odktables.rest.SavepointTypeManipulator; @@ -37,7 +32,11 @@ import org.opendatakit.aggregate.odktables.rest.entity.TableResource; import org.opendatakit.aggregate.odktables.rest.entity.TableRole; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; public class SerializationTest { diff --git a/src/test/java/org/opendatakit/aggregate/T.java b/src/test/java/org/opendatakit/aggregate/T.java index 883144f5a..31ca618c3 100644 --- a/src/test/java/org/opendatakit/aggregate/T.java +++ b/src/test/java/org/opendatakit/aggregate/T.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; @Ignore public class T { @@ -50,12 +51,12 @@ public static class Columns { public static final String savepoint_creator_1 = null; public static final String form_id_1 = null; public static final String locale_1 = "default"; - public static final String savepoint_timestamp_1 = TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()-1000); + public static final String savepoint_timestamp_1 = TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()-1000, Locale.US); public static final String savepoint_creator_2 = "fred"; public static final String form_id_2 = "ralph"; public static final String locale_2 = "default"; - public static final String savepoint_timestamp_2 = TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()-2000); + public static final String savepoint_timestamp_2 = TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()-2000, Locale.US); public static enum Data { DYLAN("1", "dylan", "23", "175"), JOHN("2", "john", "58", "200"); diff --git a/src/test/java/org/opendatakit/aggregate/parser/NamingTest.java b/src/test/java/org/opendatakit/aggregate/parser/NamingTest.java index 5949cd504..02d1e3b26 100644 --- a/src/test/java/org/opendatakit/aggregate/parser/NamingTest.java +++ b/src/test/java/org/opendatakit/aggregate/parser/NamingTest.java @@ -13,11 +13,11 @@ */ package org.opendatakit.aggregate.parser; -import static org.junit.Assert.*; - import org.junit.Test; import org.junit.runner.RunWith; +import static org.junit.Assert.assertEquals; + /** * @author mitchellsundt@gmail.com * @author wbrunette@gmail.com diff --git a/src/test/testfiles/forms/MultiWidget.xml b/src/test/testfiles/forms/MultiWidget.xml index aafec4220..7da711890 100644 --- a/src/test/testfiles/forms/MultiWidget.xml +++ b/src/test/testfiles/forms/MultiWidget.xml @@ -1,5 +1,6 @@ - + Multiwidgets Form diff --git a/src/test/testfiles/forms/dylan_form.xml b/src/test/testfiles/forms/dylan_form.xml index 1ab696de4..18a2ad3df 100644 --- a/src/test/testfiles/forms/dylan_form.xml +++ b/src/test/testfiles/forms/dylan_form.xml @@ -1,8 +1,6 @@ Dylan's Form diff --git a/src/test/testfiles/forms/landUse.xml b/src/test/testfiles/forms/landUse.xml index 7070082c6..9375efc41 100644 --- a/src/test/testfiles/forms/landUse.xml +++ b/src/test/testfiles/forms/landUse.xml @@ -1,5 +1,6 @@ - + Land Use diff --git a/sync-endpoint-common-dependencies/pom.xml b/sync-endpoint-common-dependencies/pom.xml index e0b810bf2..ffd8bf014 100644 --- a/sync-endpoint-common-dependencies/pom.xml +++ b/sync-endpoint-common-dependencies/pom.xml @@ -6,7 +6,7 @@ org.opendatakit sync-endpoint - 2.1.9 + 2.2.0-SNAPSHOT ../pom.xml @@ -18,35 +18,6 @@ org.opendatakit opendatakit-javarosa - - com.microsoft.sqlserver - mssql-jdbc - - - - com.microsoft.azure - adal4j - - - com.google.code.gson - gson - - - org.slf4j - slf4j-api - - - - - - org.bouncycastle - bcprov-jdk15on - - - - org.bouncycastle - bcpkix-jdk15on - javax javaee-web-api @@ -80,30 +51,16 @@ commons-logging - com.google.code.gson - gson - - - com.google.guava - guava - - - org.apache.httpcomponents - httpclient - - - commons-codec - commons-codec - - + commons-codec + commons-codec - org.apache.httpcomponents - httpcore + org.apache.httpcomponents.client5 + httpclient5 - org.apache.httpcomponents - httpmime + org.apache.httpcomponents.core5 + httpcore5 com.fasterxml.jackson.core @@ -286,10 +243,6 @@ junit junit - - net.lightbody.bmp - browsermob-core - io.netty netty-all diff --git a/sync-endpoint-docker-swarm/Dockerfile b/sync-endpoint-docker-swarm/Dockerfile index 994c1ccc9..951ce9dd6 100644 --- a/sync-endpoint-docker-swarm/Dockerfile +++ b/sync-endpoint-docker-swarm/Dockerfile @@ -1,4 +1,4 @@ -FROM tomcat:8.5 +FROM tomcat:9-jdk11 COPY init.sh /tmp/init.sh COPY resources/server.xml conf/ @@ -7,9 +7,10 @@ COPY resources/logging.properties conf/ COPY target/dependency/sync-endpoint-war.war / RUN chmod +x /tmp/init.sh && \ rm -rf /usr/local/tomcat/webapps/ROOT && \ - unzip /sync-endpoint-war.war -d /usr/local/tomcat/webapps/ROOT && \ + mkdir /usr/local/tomcat/webapps/ROOT && \ + cd /usr/local/tomcat/webapps/ROOT && \ + jar -xvf /sync-endpoint-war.war && \ rm /sync-endpoint-war.war EXPOSE 8443 -ENTRYPOINT ["/tmp/init.sh"] CMD ["/usr/local/tomcat/bin/catalina.sh", "run"] diff --git a/sync-endpoint-docker-swarm/pom.xml b/sync-endpoint-docker-swarm/pom.xml index 8c3575d71..1cbbf9288 100644 --- a/sync-endpoint-docker-swarm/pom.xml +++ b/sync-endpoint-docker-swarm/pom.xml @@ -7,7 +7,7 @@ org.opendatakit sync-endpoint - 2.1.9 + 2.2.0-SNAPSHOT ../pom.xml diff --git a/sync-endpoint-docker-test/Dockerfile b/sync-endpoint-docker-test/Dockerfile index 44fa563c9..34218f5c9 100644 --- a/sync-endpoint-docker-test/Dockerfile +++ b/sync-endpoint-docker-test/Dockerfile @@ -1,4 +1,4 @@ -FROM tomcat:8.5 +FROM tomcat:9-jdk11 COPY init.sh /tmp/init.sh COPY resources/server.xml conf/ @@ -8,10 +8,11 @@ COPY target/dependency/mysql-connector.jar lib/ COPY target/dependency/sync-endpoint-war.war / RUN chmod +x /tmp/init.sh && \ rm -rf /usr/local/tomcat/webapps/ROOT && \ - unzip /sync-endpoint-war.war -d /usr/local/tomcat/webapps/ROOT && \ + mkdir /usr/local/tomcat/webapps/ROOT && \ + cd /usr/local/tomcat/webapps/ROOT && \ + jar -xvf /sync-endpoint-war.war && \ rm /sync-endpoint-war.war EXPOSE 8888 EXPOSE 8443 -ENTRYPOINT ["/tmp/init.sh"] CMD ["/usr/local/tomcat/bin/catalina.sh", "run"] diff --git a/sync-endpoint-docker-test/pom.xml b/sync-endpoint-docker-test/pom.xml index a234e8d0a..4a00f88d6 100644 --- a/sync-endpoint-docker-test/pom.xml +++ b/sync-endpoint-docker-test/pom.xml @@ -7,7 +7,7 @@ org.opendatakit sync-endpoint - 2.1.9 + 2.2.0-SNAPSHOT ../pom.xml @@ -33,8 +33,8 @@ sync-endpoint-war.war - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${mysql.mysql-connector-java.version} jar mysql-connector.jar @@ -81,8 +81,8 @@ war - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${mysql.mysql-connector-java.version} jar diff --git a/sync-endpoint-war-local-test/pom.xml b/sync-endpoint-war-local-test/pom.xml new file mode 100644 index 000000000..f07dc0f05 --- /dev/null +++ b/sync-endpoint-war-local-test/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + + org.opendatakit + sync-endpoint-common-dependencies + 2.2.0-SNAPSHOT + ../sync-endpoint-common-dependencies/pom.xml + + + sync-endpoint-war-local-test + war + Sync Endpoint WAR for Local Tomcat + + ${project.basedir}/../src/main/java + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + compile + compile + + compile + + + + testCompile + test-compile + + testCompile + + + + + -Xlint:all + true + true + + + + org.codehaus.mojo + build-helper-maven-plugin + + + org.apache.maven.plugins + maven-war-plugin + + + + false + ${toplevel.directory}/src/main/resources/ + + odk-postgres-settings.xml + + + + + false + ${project.basedir}/resources/ + + odk-settings.xml + + + + false + ${project.basedir}/resources/ + WEB-INF/classes + + **/*.properties + + + + + + + + + + diff --git a/sync-endpoint-war-local-test/resources/jdbc.properties b/sync-endpoint-war-local-test/resources/jdbc.properties new file mode 100644 index 000000000..d5e160fd0 --- /dev/null +++ b/sync-endpoint-war-local-test/resources/jdbc.properties @@ -0,0 +1,6 @@ +jdbc.driverClassName=org.postgresql.Driver +jdbc.resourceName=jdbc/odk_aggregate +jdbc.url=jdbc:postgresql://localhost/postgres?autoDeserialize=true +jdbc.username=odk +jdbc.password=odk +jdbc.schema=odk_sync \ No newline at end of file diff --git a/sync-endpoint-war-local-test/resources/odk-settings.xml b/sync-endpoint-war-local-test/resources/odk-settings.xml new file mode 100644 index 000000000..6e5dd959a --- /dev/null +++ b/sync-endpoint-war-local-test/resources/odk-settings.xml @@ -0,0 +1,36 @@ + + + + + + + + + + classpath:jdbc.properties + classpath:security.properties + + + + + + + + + + + + + + + + + + + + + diff --git a/sync-endpoint-war-local-test/resources/security.properties b/sync-endpoint-war-local-test/resources/security.properties new file mode 100644 index 000000000..9bd95e1fc --- /dev/null +++ b/sync-endpoint-war-local-test/resources/security.properties @@ -0,0 +1,113 @@ +#TODO: Figure out the right way to do this +sync.preference.appName=default +sync.preference.anonymousTablesSync=false +sync.preference.anonymousAttachmentAccess=false + +# choose whether to secure everything with https or allow http access. +# +# NOTE: changes also needed to: +# -- server.xml (Tomcat configuration file) to set up the secure channel +# +# issue 648 - REQUIRES_INSECURE_CHANNEL is now the default instead of ANY_CHANNEL +# there are various edge cases that have not been tested in the UI for +# allowing arbitrary accesses, as the session cookie and authentication +# do get set for a specific http: or https: scheme and are not transferrable. +# +# should be REQUIRES_SECURE_CHANNEL but can't unless SSL is available. +security.server.secureChannelType=REQUIRES_INSECURE_CHANNEL +#security.server.secureChannelType=REQUIRES_SECURE_CHANNEL +# either REQUIRES_INSECURE_CHANNEL to secure nothing +# or REQUIRES_SECURE_CHANNEL to secure everything +# or perhaps ANY_CHANNEL when running through a proxy server +security.server.channelType=REQUIRES_INSECURE_CHANNEL +#security.server.channelType=REQUIRES_SECURE_CHANNEL +# +# When running under Tomcat, you need to set the hostname and port for +# the server so that the background tasks can generate properly-constructed +# links in their documents and in their publications to the +# external services. +# +# This is configured during install. If blank, discovers an IP address +security.server.hostname=localhost +#security.server.hostname=aggserver.southcentralus.cloudapp.azure.com +#security.server.hostname=sprite.dyn.cs.washington.edu +#security.server.hostname=clarlars.appspot.com +# +# any port pairings can be used. +#security.server.port=80 +#security.server.securePort=443 +security.server.port=8888 +security.server.securePort=8443 + +# currently supported options are activeDirectory and ldap +security.server.authenticationMethod=ldap + +# +# Settings for both Active Directory (ldap) and LDAP Authentication +# +# Username and password for doing read-only queries. +# For activeDirectory, use username@domain +# For LDAP, use username +security.server.ldapQueryUsername=cn=readonly,dc=example,dc=org +security.server.ldapQueryPassword=readonly +# +# Exclude Active Directory (ldap) and LDAP groups that don't begin with groupPrefix + space + ... +# For those that do, replace all punctuation and spaces with underscore and replace +# the groupPrefix with GROUP_ The resulting group membership will be propagated down +# to the device during a sync. +security.server.groupPrefix=default_prefix + +# +# Settings for ActiveDirectory Domain Controller +# NOTE: the DC Url should ALWAYS be ldaps +# The bind authentication uses basic auth and therefore is not +# secure unless a TLS channel is used (i.e., ldaps). +# +security.server.ldapDomainDClevel2=YOURLDAPDOMAIN2 +security.server.ldapDomainDClevel1=YOURLDAPDOMAIN1 +security.server.ldapDomain=${security.server.ldapDomainDClevel2}.${security.server.ldapDomainDClevel1} +security.server.ldapDomainControllerUrl=ldaps://${security.server.ldapDomainDClevel2}.${security.server.ldapDomainDClevel1} +security.server.ldapDomainDC=DC=${security.server.ldapDomainDClevel2},DC=${security.server.ldapDomainDClevel1} + +# +# Settings for LDAP Authentication +# +security.server.ldapUrl=ldap://localhost:389 +# for example, dc=example,dc=org +security.server.ldapBaseDn=dc=example,dc=org +security.server.ldapPooled=false +security.server.userSearchBase=ou=people +security.server.groupSearchBase=ou=${security.server.groupPrefix},ou=groups +security.server.groupRoleAttribute=cn +security.server.userFullnameAttribute=givenName +security.server.usernameAttribute=uid +# {0} is username entered during basic auth +security.server.userDnPattern=${security.server.usernameAttribute}={0},${security.server.userSearchBase} +# {0} is user dn, {1} is username, this filter is for searching groups that a user belongs to +security.server.memberOfGroupSearchFilter=(memberUid={1}) +# {0} is groupPrefix, {1} is groupRoleAttribute, this filter is for searching all groups +security.server.serverGroupSearchFilter=(&(objectClass=posixGroup)({1}={0} *)) + +# +# Settings for DHIS2 Authentication +# +security.server.dhis2ApiUrl=http://YOUR_DHIS2_SERVER/api/VERSION +security.server.dhis2AdminUsername=YOUR_ADMIN_USERNAME +security.server.dhis2AdminPassword=YOUR_ADMIN_PASSWORD +security.server.dhis2SiteAdmins=ODK_SITE_ADMIN +security.server.dhis2AdministerTables=ODK_ADMIN_TABLES +security.server.dhis2SuperUserTables=ODK_SUPER_USER_TABLES +security.server.dhis2SyncTables=ODK_SYNC_TABLES +security.server.dhis2FormManagers=ODK_FORM_MNGR +security.server.dhis2DataViewers=ODK_DATA_VIEWERS +security.server.dhis2DataCollectors=ODK_DATA_COLLECTORS + +wink.handlersFactoryClass=org.opendatakit.aggregate.odktables.impl.api.wink.AppEngineHandlersFactory + +# realm definition +# realmString -- what should be sent to users when BasicAuth or DigestAuth is done +security.server.realm.realmString=opendatakit.org ODK Aggregate +# +# + + diff --git a/sync-endpoint-war/pom.xml b/sync-endpoint-war/pom.xml index 1a49bf1da..8b151cd08 100644 --- a/sync-endpoint-war/pom.xml +++ b/sync-endpoint-war/pom.xml @@ -6,7 +6,7 @@ org.opendatakit sync-endpoint-common-dependencies - 2.1.9 + 2.2.0-SNAPSHOT ../sync-endpoint-common-dependencies/pom.xml @@ -40,26 +40,10 @@ **/*.xml - - - false - ${toplevel.directory}/src/main/resources/ - - **/*.properties - - - - - org.opendatakit - sync-endpoint-common-dependencies - ${project.parent.version} - pom - -