├── .circleci └── config.yml ├── .coveralls.yml ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── Readme.md ├── build.gradle ├── buildsupport └── eclipsesupport │ └── settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.jdt.ui.prefs ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src ├── main └── java │ └── io │ └── jsondb │ ├── CollectionMetaData.java │ ├── DefaultSchemaVersionComparator.java │ ├── InvalidJsonDbApiUsageException.java │ ├── JsonDBConfig.java │ ├── JsonDBException.java │ ├── JsonDBOperations.java │ ├── JsonDBTemplate.java │ ├── SchemaVersion.java │ ├── Util.java │ ├── annotation │ ├── Document.java │ ├── Id.java │ └── Secret.java │ ├── crypto │ ├── CryptoUtil.java │ ├── Default1Cipher.java │ ├── DefaultAESCBCCipher.java │ └── ICipher.java │ ├── events │ ├── CollectionFileChangeAdapter.java │ ├── CollectionFileChangeListener.java │ └── EventListenerList.java │ ├── io │ ├── JsonFileLockException.java │ ├── JsonReader.java │ └── JsonWriter.java │ └── query │ ├── Update.java │ └── ddl │ ├── AbstractOperation.java │ ├── AddOperation.java │ ├── CollectionSchemaUpdate.java │ ├── DeleteOperation.java │ ├── IOperation.java │ └── RenameOperation.java └── test ├── java └── io │ └── jsondb │ └── tests │ ├── CollectionMetaDataTests.java │ ├── CollectionSchemaUpdateTests.java │ ├── CreateDropCollectionTests.java │ ├── DefaultAESCipherTests.java │ ├── EncryptionTests.java │ ├── ExceptionTests.java │ ├── FileChangeAdapterTests.java │ ├── FileChangeListenerTests.java │ ├── FindAndModifyTests.java │ ├── FindAndRemoveTests.java │ ├── FindByIdTests.java │ ├── FindQueryTests.java │ ├── InitializeDBNegativeTests.java │ ├── InitializeDBTests.java │ ├── InsertTests.java │ ├── JsonDBConfigTests.java │ ├── JsonReaderTests.java │ ├── JsonWriterTests.java │ ├── LoadInvalidJsonTests.java │ ├── PojoWithEnumFieldsTest.java │ ├── RemoveTests.java │ ├── SaveTests.java │ ├── UpsertTests.java │ ├── UtilTests.java │ ├── model │ ├── Instance.java │ ├── LoadBalancer.java │ ├── PojoForPrivateGetIdTest.java │ ├── PojoForPrivateSetIdTest.java │ ├── PojoWithEnumFields.java │ ├── PojoWithList.java │ ├── SecureVolume.java │ ├── Site.java │ └── Volume.java │ └── util │ └── TestUtils.java └── resources └── dbfiles ├── instances.json ├── loadbalancer.json └── pojowithenumfields.json /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build: 5 | environment: 6 | # Configure the JVM and Gradle to avoid OOM errors 7 | _JAVA_OPTIONS: "-Xmx3g" 8 | GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2" 9 | docker: # run the steps with Docker 10 | - image: circleci/openjdk:8u222-jdk-stretch-node-browsers-legacy 11 | 12 | steps: 13 | - checkout 14 | - run: 15 | name: Build and Test 16 | command: 17 | ./gradlew test 18 | 19 | workflows: 20 | version: 2 21 | workflow: 22 | jobs: 23 | - build 24 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: KaiaNcXBfP2cda4WAV2tMJyqepXXLei5l 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.*~ 2 | *.swp 3 | .gradle 4 | *.log 5 | .DS_Store 6 | 7 | **/build/* 8 | 9 | **/.DS_Store 10 | 11 | **/bin/**/*.class 12 | 13 | #Eclipse Files 14 | **/.classpath 15 | **/.project 16 | **/.settings/* 17 | **/.springBeans 18 | 19 | #Ignore .gitignore from subdirectories 20 | */.gitignore 21 | /bin/ 22 | /.idea/ 23 | *.iml 24 | *.ipr 25 | *.iws 26 | /out/ 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | dist: trusty 3 | 4 | git: 5 | depth: 3 6 | 7 | jdk: 8 | - oraclejdk8 9 | 10 | script: 11 | - ./gradlew clean build 12 | 13 | after_success: 14 | - ./gradlew jacocoTestReport coveralls 15 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at farooq_m_khan@yahoo.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Farooq Khan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | [![Circle CI](https://circleci.com/gh/Jsondb/jsondb-core.svg?style=shield&circle-token=ead22be4576932974f9fda267a4cc31d883f5927)](https://circleci.com/gh/Jsondb/jsondb-core) [![Travis branch](https://img.shields.io/travis/Jsondb/jsondb-core/master.svg?maxAge=2592000?style=plastic&label=travisci)](https://travis-ci.org/Jsondb/jsondb-core) [![Coveralls branch](https://img.shields.io/coveralls/Jsondb/jsondb-core/master.svg?maxAge=2592000?style=plastic)](https://coveralls.io/github/Jsondb/jsondb-core?branch=master) 2 | 3 | JsonDB is a pure java database that stores its data as Json Files. 4 | 5 | A very small memory footprint, runs embedded within your java program. 6 | 7 | Provides APIs that are very similar and inspired by MongoDB. 8 | 9 | Provides a Apache JxPath based query system. 10 | 11 | Visit https://jsondb.github.io for detailed information about Jsondb, Why Jsondb and Using Jsondb 12 | 13 | 14 | 15 | 16 | ## Stargazers over time 17 | 18 | [![Stargazers over time](https://starchart.cc/Jsondb/jsondb-core.svg)](https://starchart.cc/Jsondb/jsondb-core) 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | plugins { 22 | //id 'net.saliman.cobertura' version '2.3.1' 23 | id 'jacoco' 24 | id 'com.github.kt3k.coveralls' version '2.6.3' 25 | id 'idea' 26 | } 27 | 28 | apply plugin: "java" 29 | apply plugin: "jacoco" 30 | apply plugin: "eclipse" 31 | apply plugin: "signing" 32 | apply plugin: "maven" 33 | 34 | description = 'A pure java JSON based database.' 35 | group = 'io.jsondb' 36 | version = getVersionName() 37 | 38 | ext { 39 | println "Build Version: $version" 40 | } 41 | 42 | repositories { 43 | mavenCentral() 44 | } 45 | 46 | dependencies { 47 | compile "org.slf4j:slf4j-api:1.7.21", 48 | "com.fasterxml.jackson.core:jackson-annotations:2.9.9", 49 | "com.fasterxml.jackson.core:jackson-core:2.9.9", 50 | "com.fasterxml.jackson.core:jackson-databind:2.9.9", 51 | "com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.9", 52 | "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.9", 53 | "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.9", 54 | "org.reflections:reflections:0.9.10", 55 | "org.javassist:javassist:3.20.0-GA", 56 | "commons-jxpath:commons-jxpath:1.3", 57 | "com.google.guava:guava:19.0", 58 | "commons-beanutils:commons-beanutils:1.9.3" 59 | 60 | testCompile "junit:junit:4.12", 61 | "org.hamcrest:hamcrest-library:1.3", 62 | "org.springframework:spring-beans:4.3.3.RELEASE", 63 | "org.springframework:spring-test:4.3.3.RELEASE" 64 | } 65 | 66 | //cobertura.coverageFormats = ['html', 'xml'] // coveralls plugin depends on xml format report 67 | 68 | jacocoTestReport { 69 | reports { 70 | xml.enabled = true // coveralls plugin depends on xml format report 71 | html.enabled = true 72 | } 73 | } 74 | 75 | eclipse { 76 | project { 77 | name = "${project.name}" 78 | } 79 | } 80 | 81 | eclipseJdt { 82 | inputFile = file("${rootDir}/buildsupport/eclipsesupport/settings/org.eclipse.jdt.core.prefs") 83 | doLast { 84 | copy { 85 | from "${rootDir}/buildsupport/eclipsesupport/settings/org.eclipse.jdt.ui.prefs" 86 | into "${projectDir}/.settings" 87 | fileMode 0644 88 | } 89 | } 90 | } 91 | 92 | cleanEclipseJdt { 93 | doFirst { 94 | delete "${projectDir}/.settings" 95 | } 96 | } 97 | tasks.eclipse.dependsOn(cleanEclipse) 98 | 99 | task javadocJar(type: Jar) { 100 | classifier = 'javadoc' 101 | from javadoc 102 | } 103 | 104 | task sourcesJar(type: Jar) { 105 | classifier = 'sources' 106 | from sourceSets.main.allSource 107 | } 108 | 109 | artifacts { 110 | archives javadocJar, sourcesJar 111 | } 112 | 113 | signing { 114 | required { gradle.taskGraph.hasTask("uploadArchives") } 115 | sign configurations.archives 116 | } 117 | 118 | uploadArchives { 119 | //How to publish to MavenCentral: http://weibeld.net/java/publish-to-maven-central.html 120 | repositories { 121 | mavenDeployer { 122 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 123 | 124 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 125 | authentication(userName: OSSRH_USERNAME, password: OSSRH_PASSWORD) 126 | } 127 | 128 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 129 | authentication(userName: OSSRH_USERNAME, password: OSSRH_PASSWORD) 130 | } 131 | 132 | pom.project { 133 | name 'jsondb-core' 134 | packaging 'jar' 135 | // optionally artifactId can be defined here 136 | description 'A pure java JSON based database.' 137 | url 'http://www.jsondb.io' 138 | 139 | scm { 140 | connection 'scm:git:https://github.com/Jsondb/jsondb-core.git' 141 | developerConnection 'scm:git:https://github.com/Jsondb/jsondb-core.git' 142 | url 'scm:git:https://github.com/Jsondb/jsondb-core.git' 143 | } 144 | 145 | licenses { 146 | license { 147 | name 'MIT License' 148 | url 'https://opensource.org/licenses/MIT' 149 | } 150 | } 151 | 152 | developers { 153 | developer { 154 | id 'FarooqKhan' 155 | name 'Farooq Khan' 156 | email 'FarooqKhan@users.noreply.github.com' 157 | } 158 | } 159 | } 160 | } 161 | } 162 | } 163 | 164 | /* 165 | * Gets the version name from the latest Git tag 166 | */ 167 | def getVersionName() { 168 | def stdout = new ByteArrayOutputStream() 169 | exec { 170 | commandLine 'git', 'describe', '--tags' 171 | standardOutput = stdout 172 | } 173 | def versionString = stdout.toString().replaceFirst("-", "."); 174 | versionString = versionString.substring(0, versionString.indexOf("-")); 175 | 176 | if (JavaVersion.current().isJava8()) { 177 | versionString = versionString + '-j8' 178 | } else if (JavaVersion.current().isJava11()){ 179 | versionString = versionString + '-j11' 180 | } else { 181 | assert 'Only build with Java LTS version' 182 | } 183 | 184 | return versionString 185 | } 186 | -------------------------------------------------------------------------------- /buildsupport/eclipsesupport/settings/org.eclipse.jdt.ui.prefs: -------------------------------------------------------------------------------- 1 | cleanup.add_default_serial_version_id=true 2 | cleanup.add_generated_serial_version_id=false 3 | cleanup.add_missing_annotations=true 4 | cleanup.add_missing_deprecated_annotations=true 5 | cleanup.add_missing_methods=false 6 | cleanup.add_missing_nls_tags=false 7 | cleanup.add_missing_override_annotations=true 8 | cleanup.add_missing_override_annotations_interface_methods=true 9 | cleanup.add_serial_version_id=false 10 | cleanup.always_use_blocks=true 11 | cleanup.always_use_parentheses_in_expressions=false 12 | cleanup.always_use_this_for_non_static_field_access=false 13 | cleanup.always_use_this_for_non_static_method_access=false 14 | cleanup.convert_to_enhanced_for_loop=false 15 | cleanup.correct_indentation=false 16 | cleanup.format_source_code=false 17 | cleanup.format_source_code_changes_only=false 18 | cleanup.make_local_variable_final=true 19 | cleanup.make_parameters_final=false 20 | cleanup.make_private_fields_final=true 21 | cleanup.make_type_abstract_if_missing_method=false 22 | cleanup.make_variable_declarations_final=false 23 | cleanup.never_use_blocks=false 24 | cleanup.never_use_parentheses_in_expressions=true 25 | cleanup.organize_imports=false 26 | cleanup.qualify_static_field_accesses_with_declaring_class=false 27 | cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true 28 | cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true 29 | cleanup.qualify_static_member_accesses_with_declaring_class=true 30 | cleanup.qualify_static_method_accesses_with_declaring_class=false 31 | cleanup.remove_private_constructors=true 32 | cleanup.remove_trailing_whitespaces=false 33 | cleanup.remove_trailing_whitespaces_all=true 34 | cleanup.remove_trailing_whitespaces_ignore_empty=false 35 | cleanup.remove_unnecessary_casts=true 36 | cleanup.remove_unnecessary_nls_tags=true 37 | cleanup.remove_unused_imports=true 38 | cleanup.remove_unused_local_variables=false 39 | cleanup.remove_unused_private_fields=true 40 | cleanup.remove_unused_private_members=false 41 | cleanup.remove_unused_private_methods=true 42 | cleanup.remove_unused_private_types=true 43 | cleanup.sort_members=false 44 | cleanup.sort_members_all=false 45 | cleanup.use_blocks=false 46 | cleanup.use_blocks_only_for_return_and_throw=false 47 | cleanup.use_parentheses_in_expressions=false 48 | cleanup.use_this_for_non_static_field_access=false 49 | cleanup.use_this_for_non_static_field_access_only_if_necessary=true 50 | cleanup.use_this_for_non_static_method_access=false 51 | cleanup.use_this_for_non_static_method_access_only_if_necessary=true 52 | cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile 53 | cleanup_settings_version=2 54 | eclipse.preferences.version=1 55 | formatter_profile=_Farooq_AutoGenerated 56 | formatter_settings_version=12 57 | org.eclipse.jdt.ui.javadoc=true 58 | org.eclipse.jdt.ui.text.custom_code_templates= 59 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | #sonatype login used for uploading build to MavenCentral 2 | #This only exist so that the build goes fine even on circleci or travisci or for everyone else 3 | OSSRH_USERNAME= 4 | OSSRH_PASSWORD= 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jsondb/jsondb-core/f45460cd4667f79c3548c76baf5215a695b1a956/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS='"-Xmx64m"' 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/DefaultSchemaVersionComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb; 22 | 23 | import java.util.Comparator; 24 | 25 | /** 26 | * A default schema version comparator that expects the version to be in x.y.z form where each of the digits is 27 | * strictly a integer. 28 | * 29 | * @author Farooq Khan 30 | * @version 1.0 25-Sep-2016 31 | */ 32 | public class DefaultSchemaVersionComparator implements Comparator { 33 | 34 | /** 35 | * compare the expected version with the actual version. 36 | * 37 | * Checkout: http://stackoverflow.com/questions/6701948/efficient-way-to-compare-version-strings-in-java 38 | * 39 | * @param expected the version that is obtained from @Document annotation 40 | * @param actual the version that is read from the .json file 41 | * @return a negative integer, zero, or a positive integer as the first argument is less 42 | * than, equal to, or greater than the second. 43 | */ 44 | @Override 45 | public int compare(String expected, String actual) { 46 | String[] vals1 = expected.split("\\."); 47 | String[] vals2 = actual.split("\\."); 48 | 49 | int i = 0; 50 | while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) { 51 | i++; 52 | } 53 | 54 | if (i < vals1.length && i < vals2.length) { 55 | int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i])); 56 | return Integer.signum(diff); 57 | } else { 58 | return Integer.signum(vals1.length - vals2.length); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/InvalidJsonDbApiUsageException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb; 22 | 23 | /** 24 | * @author Farooq Khan 25 | * @version 1.0 25-Sep-2016 26 | */ 27 | public class InvalidJsonDbApiUsageException extends RuntimeException { 28 | private static final long serialVersionUID = 5146122546986827377L; 29 | 30 | public InvalidJsonDbApiUsageException(String msg) { 31 | super(msg); 32 | } 33 | 34 | public InvalidJsonDbApiUsageException(String msg, Throwable cause) { 35 | super(msg, cause); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/JsonDBConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb; 22 | 23 | import java.io.File; 24 | import java.nio.charset.Charset; 25 | import java.nio.file.Path; 26 | import java.util.Comparator; 27 | 28 | import com.fasterxml.jackson.databind.DeserializationFeature; 29 | import com.fasterxml.jackson.databind.ObjectMapper; 30 | 31 | import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; 32 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 33 | import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; 34 | import io.jsondb.crypto.ICipher; 35 | 36 | /** 37 | * A POJO that has settings for the functioning of DB. 38 | * @author Farooq Khan 39 | * @version 1.0 25-Sep-2016 40 | */ 41 | public class JsonDBConfig { 42 | //Settings 43 | private Charset charset; 44 | private String dbFilesLocationString; 45 | private File dbFilesLocation; 46 | private Path dbFilesPath; 47 | private String baseScanPackage; 48 | private ICipher cipher; 49 | private boolean compatibilityMode; 50 | 51 | //References 52 | private ObjectMapper objectMapper; 53 | private Comparator schemaComparator; 54 | 55 | public JsonDBConfig(String dbFilesLocationString, String baseScanPackage, 56 | ICipher cipher, boolean compatibilityMode, Comparator schemaComparator) { 57 | 58 | this.charset = Charset.forName("UTF-8"); 59 | this.dbFilesLocationString = dbFilesLocationString; 60 | this.dbFilesLocation = new File(dbFilesLocationString); 61 | this.dbFilesPath = dbFilesLocation.toPath(); 62 | this.baseScanPackage = baseScanPackage; 63 | this.cipher = cipher; 64 | 65 | this.compatibilityMode = compatibilityMode; 66 | this.objectMapper = new ObjectMapper() 67 | .registerModule(new ParameterNamesModule()) 68 | .registerModule(new Jdk8Module()) 69 | .registerModule(new JavaTimeModule()); 70 | 71 | if (compatibilityMode) { 72 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 73 | } 74 | 75 | if (null == schemaComparator) { 76 | this.schemaComparator = new DefaultSchemaVersionComparator(); 77 | } else { 78 | this.schemaComparator = schemaComparator; 79 | } 80 | } 81 | 82 | public Charset getCharset() { 83 | return charset; 84 | } 85 | public void setCharset(Charset charset) { 86 | this.charset = charset; 87 | } 88 | public String getDbFilesLocationString() { 89 | return dbFilesLocationString; 90 | } 91 | public void setDbFilesLocationString(String dbFilesLocationString) { 92 | this.dbFilesLocationString = dbFilesLocationString; 93 | this.dbFilesLocation = new File(dbFilesLocationString); 94 | this.dbFilesPath = dbFilesLocation.toPath(); 95 | } 96 | public File getDbFilesLocation() { 97 | return dbFilesLocation; 98 | } 99 | public Path getDbFilesPath() { 100 | return dbFilesPath; 101 | } 102 | 103 | public String getBaseScanPackage() { 104 | return baseScanPackage; 105 | } 106 | public void setBaseScanPackage(String baseScanPackage) { 107 | this.baseScanPackage = baseScanPackage; 108 | } 109 | public ICipher getCipher() { 110 | return cipher; 111 | } 112 | public void setCipher(ICipher cipher) { 113 | this.cipher = cipher; 114 | } 115 | public boolean isCompatibilityMode() { 116 | return compatibilityMode; 117 | } 118 | public void setCompatibilityMode(boolean compatibilityMode) { 119 | this.compatibilityMode = compatibilityMode; 120 | if (compatibilityMode) { 121 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 122 | } else { 123 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); 124 | } 125 | } 126 | public ObjectMapper getObjectMapper() { 127 | return objectMapper; 128 | } 129 | public void setObjectMapper(ObjectMapper objectMapper) { 130 | this.objectMapper = objectMapper; 131 | } 132 | public Comparator getSchemaComparator() { 133 | return schemaComparator; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/JsonDBException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb; 22 | 23 | /** 24 | * @version 1.0 06-Oct-2016 25 | */ 26 | public class JsonDBException extends RuntimeException { 27 | 28 | private static final long serialVersionUID = -1397228179744504376L; 29 | 30 | public JsonDBException(String msg) { 31 | super(msg); 32 | } 33 | 34 | public JsonDBException(String msg, Throwable cause) { 35 | super(msg, cause); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/SchemaVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb; 22 | 23 | /** 24 | * @author Farooq Khan 25 | * @version 1.0 25-Sep-2016 26 | */ 27 | public class SchemaVersion { 28 | private String schemaVersion; 29 | 30 | //Default constructor required for Jackson 31 | public SchemaVersion() { } 32 | 33 | public SchemaVersion(String schemaVersion) { 34 | this.schemaVersion = schemaVersion; 35 | } 36 | 37 | public String getSchemaVersion() { 38 | return schemaVersion; 39 | } 40 | 41 | public void setSchemaVersion(String schemaVersion) { 42 | this.schemaVersion = schemaVersion; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/annotation/Document.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.annotation; 22 | 23 | import java.lang.annotation.ElementType; 24 | import java.lang.annotation.Inherited; 25 | import java.lang.annotation.Retention; 26 | import java.lang.annotation.RetentionPolicy; 27 | import java.lang.annotation.Target; 28 | 29 | /** 30 | * @version 1.0 25-Sep-2016 31 | */ 32 | @Inherited 33 | @Retention(RetentionPolicy.RUNTIME) 34 | @Target({ ElementType.TYPE }) 35 | public @interface Document { 36 | String collection(); 37 | String schemaVersion(); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/annotation/Id.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.annotation; 22 | 23 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 24 | import static java.lang.annotation.ElementType.FIELD; 25 | import static java.lang.annotation.ElementType.METHOD; 26 | 27 | import java.lang.annotation.Retention; 28 | import java.lang.annotation.RetentionPolicy; 29 | import java.lang.annotation.Target; 30 | 31 | /** 32 | * @version 1.0 25-Sep-2016 33 | */ 34 | @Retention(RetentionPolicy.RUNTIME) 35 | @Target(value = { FIELD, METHOD, ANNOTATION_TYPE }) 36 | public @interface Id { 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/annotation/Secret.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.annotation; 22 | 23 | import java.lang.annotation.ElementType; 24 | import java.lang.annotation.Inherited; 25 | import java.lang.annotation.Retention; 26 | import java.lang.annotation.RetentionPolicy; 27 | import java.lang.annotation.Target; 28 | 29 | /** 30 | * @version 1.0 25-Sep-2016 31 | */ 32 | @Inherited 33 | @Retention(RetentionPolicy.RUNTIME) 34 | @Target({ ElementType.FIELD }) 35 | public @interface Secret { 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/crypto/CryptoUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.crypto; 22 | 23 | import java.io.UnsupportedEncodingException; 24 | import java.lang.reflect.InvocationTargetException; 25 | import java.lang.reflect.Method; 26 | import java.security.NoSuchAlgorithmException; 27 | import java.security.spec.InvalidKeySpecException; 28 | import java.security.spec.KeySpec; 29 | import java.util.Base64; 30 | 31 | import javax.crypto.SecretKey; 32 | import javax.crypto.SecretKeyFactory; 33 | import javax.crypto.spec.PBEKeySpec; 34 | 35 | import org.slf4j.Logger; 36 | import org.slf4j.LoggerFactory; 37 | 38 | import io.jsondb.CollectionMetaData; 39 | 40 | /** 41 | * @author Farooq Khan 42 | * @version 1.0 25-Sep-2016 43 | */ 44 | public class CryptoUtil { 45 | private static Logger logger = LoggerFactory.getLogger(CryptoUtil.class); 46 | 47 | /** 48 | * A utility method to encrypt the value of field marked by the @Secret annotation using its 49 | * setter/mutator method. 50 | * @param object the actual Object representing the POJO we want the Id of. 51 | * @param cmd the CollectionMetaData object from which we can obtain the list 52 | * containing names of fields which have the @Secret annotation 53 | * @param cipher the actual cipher implementation to use 54 | * @throws IllegalAccessException Error when invoking method for a @Secret annotated field due to permissions 55 | * @throws IllegalArgumentException Error when invoking method for a @Secret annotated field due to wrong arguments 56 | * @throws InvocationTargetException Error when invoking method for a @Secret annotated field, the method threw a exception 57 | */ 58 | public static void encryptFields(Object object, CollectionMetaData cmd, ICipher cipher) 59 | throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 60 | for (String secretAnnotatedFieldName: cmd.getSecretAnnotatedFieldNames()) { 61 | Method getterMethod = cmd.getGetterMethodForFieldName(secretAnnotatedFieldName); 62 | Method setterMethod = cmd.getSetterMethodForFieldName(secretAnnotatedFieldName); 63 | 64 | String value; 65 | String encryptedValue = null; 66 | try { 67 | value = (String)getterMethod.invoke(object); 68 | if (null != value) { 69 | encryptedValue = cipher.encrypt(value); 70 | setterMethod.invoke(object, encryptedValue); 71 | } 72 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 73 | logger.error("Error when invoking method for a @Secret annotated field", e); 74 | throw e; 75 | } 76 | } 77 | } 78 | 79 | /** 80 | * A utility method to decrypt the value of field marked by the @Secret annotation using its 81 | * setter/mutator method. 82 | * @param object the actual Object representing the POJO we want the Id of. 83 | * @param cmd the CollectionMetaData object from which we can obtain the list 84 | * containing names of fields which have the @Secret annotation 85 | * @param cipher the actual cipher implementation to use 86 | * @throws IllegalAccessException Error when invoking method for a @Secret annotated field due to permissions 87 | * @throws IllegalArgumentException Error when invoking method for a @Secret annotated field due to wrong arguments 88 | * @throws InvocationTargetException Error when invoking method for a @Secret annotated field, the method threw a exception 89 | */ 90 | public static void decryptFields(Object object, CollectionMetaData cmd, ICipher cipher) 91 | throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 92 | 93 | for (String secretAnnotatedFieldName: cmd.getSecretAnnotatedFieldNames()) { 94 | Method getterMethod = cmd.getGetterMethodForFieldName(secretAnnotatedFieldName); 95 | Method setterMethod = cmd.getSetterMethodForFieldName(secretAnnotatedFieldName); 96 | 97 | String value; 98 | String decryptedValue = null; 99 | try { 100 | value = (String)getterMethod.invoke(object); 101 | if (null != value) { 102 | decryptedValue = cipher.decrypt(value); 103 | setterMethod.invoke(object, decryptedValue); 104 | } 105 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 106 | logger.error("Error when invoking method for a @Secret annotated field", e); 107 | throw e; 108 | } 109 | } 110 | } 111 | 112 | /** 113 | * Utility method to help generate a strong 128 bit Key to be used for the DefaultAESCBCCipher. 114 | * 115 | * Note: This function is only provided as a utility to generate strong password it should 116 | * be used statically to generate a key and then the key should be captured and used in your program. 117 | * 118 | * This function defaults to using 65536 iterations and 128 bits for key size. If you wish to use 256 bits key size 119 | * then ensure that you have Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy installed 120 | * and change the last argument to {@link javax.crypto.spec.PBEKeySpec} below to 256 121 | * 122 | * @param password A password which acts as a seed for generation of the key 123 | * @param salt A salt used in combination with the password for the generation of the key 124 | * 125 | * @return A Base64 Encoded string representing the 128 bit key 126 | * 127 | * @throws NoSuchAlgorithmException if the KeyFactory algorithm is not found in available crypto providers 128 | * @throws UnsupportedEncodingException if the char encoding of the salt is not known. 129 | * @throws InvalidKeySpecException invalid generated key 130 | */ 131 | public static String generate128BitKey(String password, String salt) 132 | throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException { 133 | 134 | SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); 135 | 136 | KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 128); 137 | SecretKey key = factory.generateSecret(spec); 138 | byte[] keybyte = key.getEncoded(); 139 | return Base64.getEncoder().encodeToString(keybyte); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/crypto/Default1Cipher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Reinier Zwitserloot 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.crypto; 22 | 23 | import java.nio.ByteBuffer; 24 | import java.nio.charset.Charset; 25 | import java.nio.charset.StandardCharsets; 26 | import java.security.GeneralSecurityException; 27 | import java.security.InvalidAlgorithmParameterException; 28 | import java.security.InvalidKeyException; 29 | import java.security.NoSuchAlgorithmException; 30 | import java.security.NoSuchProviderException; 31 | import java.security.SecureRandom; 32 | import java.util.Base64; 33 | 34 | import javax.crypto.AEADBadTagException; 35 | import javax.crypto.BadPaddingException; 36 | import javax.crypto.Cipher; 37 | import javax.crypto.IllegalBlockSizeException; 38 | import javax.crypto.NoSuchPaddingException; 39 | import javax.crypto.ShortBufferException; 40 | import javax.crypto.spec.GCMParameterSpec; 41 | import javax.crypto.spec.SecretKeySpec; 42 | 43 | import io.jsondb.JsonDBException; 44 | 45 | /** 46 | * A default AES (GCM Mode) Cipher. AES is a 128-bit block cipher supporting keys of 128, 192, and 256 bits. 47 | * 48 | * The constructors do not check if key provided as parameter indeed specifies a valid AES key. It does not check key size, 49 | * nor does it check for weak or sem-weak keys. 50 | * 51 | * Note: If you want to use Key > 128 bits then you need to install Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction 52 | * Policy files. 53 | * 54 | * @author Reinier Zwitserloot 55 | * @version 1.0 20-Jun-2019 56 | */ 57 | public class Default1Cipher implements ICipher { 58 | private static final String ENCRYPTION_ALGORITHM = "AES"; 59 | private static final String MODE_ALGORITHM = "GCM"; 60 | private static final String PADDING_ALGORITHM = "NoPadding"; 61 | private static final String PROVIDER = "SunJCE"; 62 | private static final String CIPHER_ALGORITHM = ENCRYPTION_ALGORITHM + "/" + MODE_ALGORITHM + "/" + PADDING_ALGORITHM; 63 | private static final int IV_SIZE = 16; 64 | private static final int TAG_SIZE = 128; 65 | 66 | /* intentionally letting the system pick a sane SecureRandom; SecureRandom.getInstanceStrong() can block and is overkill. */ 67 | private static final SecureRandom rnd = createNewSecureRandom(); 68 | 69 | private static final SecureRandom createNewSecureRandom() { 70 | try { 71 | return SecureRandom.getInstance("NativePRNGNonBlocking"); 72 | } catch (NoSuchAlgorithmException e) { 73 | try { 74 | return SecureRandom.getInstance("SHA1PRNG"); 75 | } catch (NoSuchAlgorithmException e2) { 76 | return new SecureRandom(); 77 | } 78 | } 79 | } 80 | 81 | private final Charset charset; 82 | private final SecretKeySpec key; 83 | 84 | /** 85 | * Creates a new default cipher using 'UTF-8' encoding, with a base64-encoded key. 86 | * 87 | * @param base64CodedEncryptionKey A base 64 encoded symmetric key to be used during encryption and decryption. 88 | * @throws GeneralSecurityException a general security exception 89 | */ 90 | public Default1Cipher(String base64CodedEncryptionKey) throws GeneralSecurityException { 91 | this(Base64.getDecoder().decode(base64CodedEncryptionKey), StandardCharsets.UTF_8); 92 | } 93 | 94 | /** 95 | * Creates a new default cipher using 'UTF-8' encoding and key. 96 | * 97 | * @param encryptionKey A symmetric key to be used during encryption and decryption. 98 | * @throws GeneralSecurityException a general security exception 99 | */ 100 | public Default1Cipher(byte[] encryptionKey) throws GeneralSecurityException { 101 | this(encryptionKey, StandardCharsets.UTF_8); 102 | } 103 | 104 | /** 105 | * Creates a new default cipher with the specified charset encoding, with a base64-encoded key. 106 | * 107 | * @param base64CodedEncryptionKey A base 64 encoded symmetric key to be used during encryption and decryption. 108 | * @param charset The charset to be considered when encrypting plaintext or decrypting ciphertext. 109 | * @throws GeneralSecurityException a general security exception 110 | */ 111 | public Default1Cipher(String base64CodedEncryptionKey, Charset charset) throws GeneralSecurityException { 112 | this(Base64.getDecoder().decode(base64CodedEncryptionKey), charset); 113 | } 114 | 115 | /** 116 | * Creates a new default cipher with the specified charset encoding and key. 117 | * 118 | * @param encryptionKey A symmetric key to be used during encryption and decryption. 119 | * @param charset The charset to be considered when encrypting plaintext or decrypting ciphertext. 120 | * @throws GeneralSecurityException a general security exception 121 | */ 122 | public Default1Cipher(byte[] encryptionKey, Charset charset) throws GeneralSecurityException { 123 | if (charset == null) throw new NullPointerException("charset"); 124 | if (encryptionKey == null) throw new NullPointerException("encryptionKey"); 125 | this.charset = charset; 126 | this.key = new SecretKeySpec(encryptionKey, ENCRYPTION_ALGORITHM); 127 | } 128 | 129 | /** 130 | * This method is used to encrypt(Symmetric) plainText coming in input using AES algorithm 131 | * @param plainText the plain text string to be encrypted 132 | * @return Base64 encoded AES encrypted cipher text 133 | */ 134 | @Override 135 | public String encrypt(String plainText) { 136 | try { 137 | byte[] iv = new byte[IV_SIZE]; 138 | rnd.nextBytes(iv); 139 | Cipher enc = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER); 140 | enc.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(TAG_SIZE, iv)); 141 | byte[] input = plainText.getBytes(charset); 142 | int sizeReq = IV_SIZE + enc.getOutputSize(input.length); 143 | byte[] output = new byte[sizeReq]; 144 | ByteBuffer store = ByteBuffer.wrap(output); 145 | store.put(iv); 146 | int extra = enc.doFinal(input, 0, input.length, output, IV_SIZE); 147 | store.position(store.position() + extra); 148 | store.flip(); 149 | ByteBuffer bb = Base64.getEncoder().encode(store); 150 | return new String(bb.array(), 0, bb.limit(), StandardCharsets.US_ASCII); 151 | } catch (NoSuchPaddingException | NoSuchProviderException | NoSuchAlgorithmException | IllegalBlockSizeException |InvalidAlgorithmParameterException e) { 152 | throw new JsonDBException("Default cipher cannot be used on this VM installation", e); 153 | } catch (InvalidKeyException e) { 154 | throw new JsonDBException("Invalid key", e); 155 | } catch (BadPaddingException | ShortBufferException e) { 156 | throw new JsonDBException("Unexpected (bug?) crypto error", e); 157 | } 158 | } 159 | 160 | /** 161 | * A method to decrypt the provided cipher text. 162 | * 163 | * @param cipherText AES encrypted cipherText 164 | * @return decrypted text 165 | */ 166 | @Override 167 | public String decrypt(String cipherText) { 168 | byte[] in = Base64.getDecoder().decode(cipherText); 169 | try { 170 | Cipher dec = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER); 171 | dec.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(TAG_SIZE, in, 0, IV_SIZE)); 172 | return new String(dec.doFinal(in, IV_SIZE, in.length - IV_SIZE), charset); 173 | } catch (NoSuchPaddingException | NoSuchProviderException | NoSuchAlgorithmException | IllegalBlockSizeException e) { 174 | throw new JsonDBException("Default cipher cannot be used on this VM installation", e); 175 | } catch (InvalidKeyException e) { 176 | throw new JsonDBException("Invalid key", e); 177 | } catch (AEADBadTagException e) { 178 | throw new JsonDBException("Incorrect key for this ciphertext (or ciphertext is corrupted)", e); 179 | } catch (BadPaddingException | InvalidAlgorithmParameterException e) { 180 | throw new JsonDBException("Unexpected (bug?) crypto error", e); 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/crypto/ICipher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.crypto; 22 | 23 | /** 24 | * @author Farooq Khan 25 | * @version 1.0 25-Sep-2016 26 | */ 27 | public interface ICipher { 28 | String encrypt(String plainText); 29 | String decrypt(String cipherText); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/events/CollectionFileChangeAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.events; 22 | 23 | /** 24 | * An abstract adapter class for receiving Collection File Change events. 25 | * The methods in this class are empty. 26 | * This class exists as convenience for creating listener objects. 27 | * 28 | * Extend this class to create a Collection File Change listener and override only the methods for 29 | * the events of interest. (If you implement the CollectionFileChangeListener interface, you have to 30 | * define all of the methods in it. This abstract class defines null methods for them all, so you 31 | * can only have to define methods for events you care about.) 32 | * 33 | * @author Farooq Khan 34 | * @version 1.0 21 Aug 2016 35 | */ 36 | public abstract class CollectionFileChangeAdapter implements CollectionFileChangeListener { 37 | 38 | @Override 39 | public void collectionFileAdded(String collectionName) { } 40 | 41 | @Override 42 | public void collectionFileDeleted(String collectionName) { } 43 | 44 | @Override 45 | public void collectionFileModified(String collectionName) { } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/events/CollectionFileChangeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.events; 22 | 23 | import java.util.EventListener; 24 | 25 | /** 26 | * A listener which fires when a change to one or more files which have corresponding identified collections is detected. 27 | * 28 | * @author Farooq Khan 29 | * @version 1.0 21 Aug 2016 30 | */ 31 | public interface CollectionFileChangeListener extends EventListener { 32 | /** 33 | * Invoked when a new file is detected which has a corresponding identified collection. 34 | * A identified collection is that for which the package scan found a POJO with the @Document annotation. 35 | * This also means that such a identified collection did not have a corresponding collection file before. 36 | * 37 | * New files which do not have corresponding identified collection are ignored. 38 | * 39 | * @param collectionName the name of the collection for which a file was detected. 40 | */ 41 | void collectionFileAdded(String collectionName); 42 | 43 | /** 44 | * Invoked when a file which has a corresponding identified collection is deleted 45 | * 46 | * Deleting files in the background is a dangerous operation after such a operation if the database is 47 | * reloaded that data will be permanently lost. However if any operation that modifies the database is 48 | * done then it will automatically recreate the file. 49 | * 50 | * @param collectionName the name of the collection for which a file was deleted. 51 | */ 52 | void collectionFileDeleted(String collectionName); 53 | 54 | /** 55 | * Invoked when a file which has a corresponding identified collection is modified by program other than this one. 56 | * 57 | * Ideally you might want to reload the database on receiving this event. If you ignore and change to the database happens due to 58 | * a insert of update or any other Database mutating operation the file will be overwritten with the in memory state. 59 | * 60 | * @param collectionName the name of the collection whose corresponding file was modified. 61 | */ 62 | void collectionFileModified(String collectionName); 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/events/EventListenerList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.events; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.nio.file.Path; 26 | import java.nio.file.StandardWatchEventKinds; 27 | import java.nio.file.WatchEvent; 28 | import java.nio.file.WatchKey; 29 | import java.nio.file.WatchService; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | import java.util.Map; 33 | import java.util.concurrent.ExecutorService; 34 | import java.util.concurrent.Executors; 35 | 36 | import org.slf4j.Logger; 37 | import org.slf4j.LoggerFactory; 38 | 39 | import com.google.common.util.concurrent.ThreadFactoryBuilder; 40 | 41 | import io.jsondb.CollectionMetaData; 42 | import io.jsondb.JsonDBConfig; 43 | import io.jsondb.JsonDBException; 44 | 45 | /** 46 | * A class that holds a list of CollectionFileChangeListeners. 47 | * @version 1.0 15-Oct-2016 48 | */ 49 | public class EventListenerList { 50 | private Logger logger = LoggerFactory.getLogger(EventListenerList.class); 51 | 52 | private JsonDBConfig dbConfig = null; 53 | private Map cmdMap; 54 | 55 | private List listeners; 56 | private ExecutorService collectionFilesWatcherExecutor; 57 | private WatchService watcher = null; 58 | private boolean stopWatcher; 59 | 60 | public EventListenerList(JsonDBConfig dbConfig, Map cmdMap) { 61 | this.dbConfig = dbConfig; 62 | this.cmdMap = cmdMap; 63 | } 64 | 65 | public void addCollectionFileChangeListener(CollectionFileChangeListener listener) { 66 | if (null == listeners) { 67 | listeners = new ArrayList(); 68 | 69 | listeners.add(listener); 70 | 71 | collectionFilesWatcherExecutor = Executors.newSingleThreadExecutor( 72 | new ThreadFactoryBuilder().setNameFormat("jsondb-files-watcher-thread-%d").build()); 73 | 74 | try { 75 | watcher = dbConfig.getDbFilesPath().getFileSystem().newWatchService(); 76 | dbConfig.getDbFilesPath().register(watcher, StandardWatchEventKinds.ENTRY_CREATE, 77 | StandardWatchEventKinds.ENTRY_DELETE, 78 | StandardWatchEventKinds.ENTRY_MODIFY); 79 | } catch (IOException e) { 80 | logger.error("Failed to create the WatchService for the dbFiles location", e); 81 | throw new JsonDBException("Failed to create the WatchService for the dbFiles location", e); 82 | } 83 | 84 | collectionFilesWatcherExecutor.execute(new CollectionFilesWatcherRunnable()); 85 | } else { 86 | listeners.add(listener); 87 | } 88 | } 89 | 90 | public void removeCollectionFileChangeListener(CollectionFileChangeListener listener) { 91 | if (null != listeners) { 92 | listeners.remove(listener); 93 | } 94 | if (listeners.size() < 1) { 95 | stopWatcher = true; 96 | collectionFilesWatcherExecutor.shutdownNow(); 97 | try { 98 | watcher.close(); 99 | } catch (IOException e) { 100 | logger.error("Failed to close the WatchService for the dbFiles location", e); 101 | } 102 | } 103 | } 104 | 105 | public boolean hasCollectionFileChangeListener() { 106 | if ((null != listeners) && (listeners.size() > 0)) { 107 | return true; 108 | } 109 | return false; 110 | } 111 | 112 | public void shutdown() { 113 | if (null != listeners && listeners.size() > 0) { 114 | stopWatcher = true; 115 | collectionFilesWatcherExecutor.shutdownNow(); 116 | try { 117 | watcher.close(); 118 | } catch (IOException e) { 119 | logger.error("Failed to close the WatchService for the dbFiles location", e); 120 | } 121 | listeners.clear(); 122 | } 123 | } 124 | 125 | private class CollectionFilesWatcherRunnable implements Runnable { 126 | @Override 127 | public void run() { 128 | while (!stopWatcher) { 129 | WatchKey watckKey = null; 130 | try { 131 | watckKey = watcher.take(); 132 | } catch (InterruptedException e) { 133 | logger.debug("The watcher service thread was interrupted", e); 134 | return; 135 | } 136 | List> events = watckKey.pollEvents(); 137 | for (WatchEvent event : events) { 138 | WatchEvent.Kind kind = event.kind(); 139 | if (kind == StandardWatchEventKinds.OVERFLOW) { 140 | continue; 141 | } 142 | @SuppressWarnings("unchecked") 143 | WatchEvent ev = (WatchEvent)event; 144 | File file = ev.context().toFile(); 145 | String fileName = file.getName(); 146 | int extnLocation = fileName.lastIndexOf('.'); 147 | if(extnLocation != -1) { 148 | String collectionName = fileName.substring(0, extnLocation); 149 | if (fileName.endsWith(".json") && (cmdMap.containsKey(collectionName))) { 150 | if (kind == StandardWatchEventKinds.ENTRY_CREATE) { 151 | for (CollectionFileChangeListener listener : listeners) { 152 | listener.collectionFileAdded(collectionName); 153 | } 154 | } else if (kind == StandardWatchEventKinds.ENTRY_DELETE) { 155 | for (CollectionFileChangeListener listener : listeners) { 156 | listener.collectionFileDeleted(collectionName); 157 | } 158 | } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { 159 | for (CollectionFileChangeListener listener : listeners) { 160 | listener.collectionFileModified(collectionName); 161 | } 162 | } 163 | } 164 | } 165 | } 166 | } 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/io/JsonFileLockException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.io; 22 | 23 | import java.io.IOException; 24 | 25 | /** 26 | * @author Farooq Khan 27 | * @version 1.0 25-Sep-2016 28 | */ 29 | public class JsonFileLockException extends IOException { 30 | private static final long serialVersionUID = -8387556796643594285L; 31 | 32 | public JsonFileLockException(String message, Throwable cause) { 33 | super(message, cause); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/io/JsonReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.io; 22 | 23 | import java.io.BufferedReader; 24 | import java.io.File; 25 | import java.io.FileInputStream; 26 | import java.io.IOException; 27 | import java.io.InputStreamReader; 28 | import java.io.RandomAccessFile; 29 | import java.nio.channels.FileChannel; 30 | import java.nio.channels.FileLock; 31 | import java.nio.channels.OverlappingFileLockException; 32 | import java.nio.charset.CharsetDecoder; 33 | import java.nio.charset.CodingErrorAction; 34 | 35 | import org.slf4j.Logger; 36 | import org.slf4j.LoggerFactory; 37 | 38 | import io.jsondb.JsonDBConfig; 39 | 40 | /** 41 | * A special File Reader to read the .json DB files that ensures 42 | * proper character encoding is used and the necessary File Locks are created. 43 | * 44 | * @author Farooq Khan 45 | * @version 1.0 25-Sep-2016 46 | */ 47 | public class JsonReader { 48 | 49 | private Logger logger = LoggerFactory.getLogger(JsonReader.class); 50 | 51 | private File collectionFile; 52 | 53 | private RandomAccessFile raf; 54 | private FileInputStream fis; 55 | private FileChannel channel; 56 | private InputStreamReader isr; 57 | private BufferedReader reader; 58 | private FileLock lock; 59 | private File lockFilesLocation; 60 | private File fileLockLocation; 61 | 62 | public JsonReader(JsonDBConfig dbConfig, File collectionFile) throws IOException { 63 | this.collectionFile = collectionFile; 64 | this.lockFilesLocation = new File(collectionFile.getParentFile(), "lock"); 65 | this.fileLockLocation = new File(lockFilesLocation, collectionFile.getName() + ".lock"); 66 | 67 | if(!lockFilesLocation.exists()) { 68 | lockFilesLocation.mkdirs(); 69 | } 70 | if(!fileLockLocation.exists()) { 71 | fileLockLocation.createNewFile(); 72 | } 73 | 74 | CharsetDecoder decoder = dbConfig.getCharset().newDecoder(); 75 | decoder.onMalformedInput(CodingErrorAction.REPORT); 76 | decoder.onUnmappableCharacter(CodingErrorAction.REPORT); 77 | 78 | raf = new RandomAccessFile(fileLockLocation, "rw"); 79 | channel = raf.getChannel(); 80 | try { 81 | lock = channel.lock(); 82 | } catch (IOException | OverlappingFileLockException e) { 83 | try { 84 | channel.close(); 85 | raf.close(); 86 | } catch (IOException e1) { 87 | logger.error("Failed while closing RandomAccessFile for collection file {}", collectionFile.getName()); 88 | } 89 | throw new JsonFileLockException("JsonReader failed to obtain a file lock for file " + fileLockLocation, e); 90 | } 91 | 92 | fis = new FileInputStream(collectionFile); 93 | isr = new InputStreamReader(fis, decoder); 94 | reader = new BufferedReader(isr); 95 | } 96 | 97 | /** 98 | * A utility method that reads the next line and returns it. 99 | * Since we use a BufferedReader this method may often read more 100 | * than the next line to determine if the line ended. 101 | * @return the content of the line just read 102 | * @throws IOException if an I/O error occurs 103 | */ 104 | public String readLine() throws IOException { 105 | return reader.readLine(); 106 | } 107 | 108 | public void close() { 109 | try { 110 | reader.close(); 111 | } catch (IOException e) { 112 | logger.error("Failed to close BufferedReader for collection file {}", collectionFile.getName(), e); 113 | } 114 | try { 115 | isr.close(); 116 | } catch (IOException e) { 117 | logger.error("Failed to close InputStreamReader for collection file {}", collectionFile.getName(), e); 118 | } 119 | try { 120 | if(lock.isValid()) { 121 | lock.release(); 122 | } 123 | } catch (IOException e) { 124 | logger.error("Failed to release lock for collection file {}", collectionFile.getName(), e); 125 | } 126 | try { 127 | channel.close(); 128 | } catch (IOException e) { 129 | logger.error("Failed to close FileChannel for collection file {}", collectionFile.getName(), e); 130 | } 131 | try { 132 | fis.close(); 133 | } catch (IOException e) { 134 | logger.error("Failed to close FileInputStream for collection file {}", collectionFile.getName(), e); 135 | } 136 | try { 137 | raf.close(); 138 | } catch (IOException e) { 139 | logger.error("Failed to close RandomAccessFile for collection file {}", collectionFile.getName(), e); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/query/Update.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.query; 22 | 23 | import java.util.Map; 24 | import java.util.TreeMap; 25 | 26 | /** 27 | * @author Farooq Khan 28 | * @version 1.0 21 Aug 2016 29 | */ 30 | public class Update { 31 | 32 | private Map updateData; 33 | 34 | public Update() { 35 | updateData = new TreeMap(); 36 | } 37 | 38 | /** 39 | * Static factory method to create an Update using the provided key 40 | * 41 | * @param key the field name for the update operation 42 | * @param value the value to set for the field 43 | * @return Updated object 44 | */ 45 | public static Update update(String key, Object value) { 46 | return new Update().set(key, value); 47 | } 48 | 49 | public Update set(String key, Object value) { 50 | updateData.put(key, value); 51 | return this; 52 | } 53 | 54 | public Map getUpdateData() { 55 | return updateData; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/query/ddl/AbstractOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.query.ddl; 22 | 23 | import io.jsondb.query.ddl.CollectionSchemaUpdate.Type; 24 | 25 | /** 26 | * @author Farooq Khan 27 | * @version 1.0 21 Aug 2016 28 | */ 29 | public abstract class AbstractOperation implements IOperation { 30 | protected Type operationType; 31 | public Type getOperationType() { 32 | return operationType; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/query/ddl/AddOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.query.ddl; 22 | 23 | import io.jsondb.query.ddl.CollectionSchemaUpdate.Type; 24 | 25 | /** 26 | * Represents a CollectionUpdate ADD operation type. 27 | * 28 | * This operation allows for adding a new field to a POJO 29 | * 30 | * @author Farooq Khan 31 | * @version 1.0 21 Aug 2016 32 | */ 33 | public class AddOperation extends AbstractOperation { 34 | private Object defaultValue; 35 | private boolean isSecret; 36 | 37 | public AddOperation(Object defaultValue, boolean isSecret) { 38 | this.operationType = Type.ADD; 39 | this.defaultValue = defaultValue; 40 | this.isSecret = isSecret; 41 | } 42 | 43 | public Object getDefaultValue() { 44 | return defaultValue; 45 | } 46 | 47 | public boolean isSecret() { 48 | return isSecret; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/query/ddl/CollectionSchemaUpdate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.query.ddl; 22 | 23 | import java.util.Map; 24 | import java.util.Map.Entry; 25 | import java.util.TreeMap; 26 | 27 | /** 28 | * @author Farooq Khan 29 | * @version 1.0 21 Aug 2016 30 | */ 31 | public class CollectionSchemaUpdate { 32 | 33 | public enum Type {ADD, RENAME, DELETE}; 34 | 35 | private Map collectionUpdateData; 36 | 37 | public CollectionSchemaUpdate() { 38 | collectionUpdateData = new TreeMap(); 39 | } 40 | 41 | /** 42 | * Static factory method to create an CollectionUpdate for the specified key 43 | * 44 | * @param key: JSON attribute to update 45 | * @param operation: operation to carry out on the attribute 46 | * @return the updated CollectionSchemaUpdate 47 | */ 48 | public static CollectionSchemaUpdate update(String key, IOperation operation) { 49 | return new CollectionSchemaUpdate().set(key, operation); 50 | } 51 | 52 | /** 53 | * A method to set a new Operation for a key. It may be of type ADD, RENAME or DELETE. 54 | * Only one operation per key can be specified. Attempt to add a second operation for a any key will override the first one. 55 | * Attempt to add a ADD operation for a key which already exists will have no effect. 56 | * Attempt to add a DELETE operation for akey which does not exist will have no effect. 57 | * 58 | * @param key (a.k.a JSON Field name) for which operation is being added 59 | * @param operation operation to perform 60 | * @return the updated CollectionSchemaUpdate 61 | */ 62 | public CollectionSchemaUpdate set(String key, IOperation operation) { 63 | collectionUpdateData.put(key, operation); 64 | return this; 65 | } 66 | 67 | public Map getUpdateData() { 68 | return collectionUpdateData; 69 | } 70 | 71 | /** 72 | * Returns a Map of ADD operations which have a non-null default value specified. 73 | * 74 | * @return Map of ADD operations which have a non-null default value specified 75 | */ 76 | public Map getAddOperations() { 77 | Map addOperations = new TreeMap(); 78 | for (Entry entry : collectionUpdateData.entrySet()) { 79 | String key = entry.getKey(); 80 | IOperation op = entry.getValue(); 81 | if (op.getOperationType().equals(Type.ADD)) { 82 | AddOperation aop = (AddOperation)op; 83 | if (null != aop.getDefaultValue()) { 84 | addOperations.put(key, aop); 85 | } 86 | } 87 | } 88 | return addOperations; 89 | } 90 | 91 | /** 92 | * Returns a Map of RENAME operations. 93 | * 94 | * @return Map of RENAME operations which have a non-null default value specified 95 | */ 96 | public Map getRenameOperations() { 97 | Map renOperations = new TreeMap(); 98 | for (Entry entry : collectionUpdateData.entrySet()) { 99 | String key = entry.getKey(); 100 | IOperation op = entry.getValue(); 101 | if (op.getOperationType().equals(Type.RENAME)) { 102 | renOperations.put(key, (RenameOperation)op); 103 | } 104 | } 105 | return renOperations; 106 | } 107 | 108 | /** 109 | * Returns a Map of DELETE operations. 110 | * 111 | * @return Map of DELETE operations which have a non-null default value specified 112 | */ 113 | public Map getDeleteOperations() { 114 | Map delOperations = new TreeMap(); 115 | for (Entry entry : collectionUpdateData.entrySet()) { 116 | String key = entry.getKey(); 117 | IOperation op = entry.getValue(); 118 | if (op.getOperationType().equals(Type.DELETE)) { 119 | delOperations.put(key, (DeleteOperation)op); 120 | } 121 | } 122 | return delOperations; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/query/ddl/DeleteOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.query.ddl; 22 | 23 | import io.jsondb.query.ddl.CollectionSchemaUpdate.Type; 24 | 25 | /** 26 | * Represents a CollectionUpdate DELETE operation type. 27 | * 28 | * This operation allows for deleting a field from a POJO 29 | * 30 | * @author Farooq Khan 31 | * @version 1.0 21 Aug 2016 32 | */ 33 | public class DeleteOperation extends AbstractOperation { 34 | public DeleteOperation() { 35 | this.operationType = Type.DELETE; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/query/ddl/IOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.query.ddl; 22 | 23 | import io.jsondb.query.ddl.CollectionSchemaUpdate.Type; 24 | 25 | /** 26 | * @author Farooq Khan 27 | * @version 1.0 21 Aug 2016 28 | */ 29 | public interface IOperation { 30 | Type getOperationType(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/jsondb/query/ddl/RenameOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.query.ddl; 22 | 23 | import io.jsondb.query.ddl.CollectionSchemaUpdate.Type; 24 | 25 | /** 26 | * Represents a CollectionUpdate RENAME operation type. 27 | * 28 | * This operation allows for changing the name of a field in a POJO 29 | * 30 | * @author Farooq Khan 31 | * @version 1.0 21 Aug 2016 32 | */ 33 | public class RenameOperation extends AbstractOperation { 34 | private String newName; 35 | 36 | public RenameOperation(String newName) { 37 | this.operationType = Type.RENAME; 38 | this.newName = newName; 39 | } 40 | 41 | public String getNewName() { 42 | return newName; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/CollectionMetaDataTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertFalse; 25 | import static org.junit.Assert.assertNotNull; 26 | import static org.junit.Assert.assertNull; 27 | import static org.junit.Assert.assertTrue; 28 | 29 | import java.io.File; 30 | import java.util.List; 31 | import java.util.Map; 32 | 33 | import org.junit.After; 34 | import org.junit.Before; 35 | import org.junit.Test; 36 | 37 | import com.google.common.io.Files; 38 | 39 | import io.jsondb.CollectionMetaData; 40 | import io.jsondb.JsonDBConfig; 41 | import io.jsondb.Util; 42 | import io.jsondb.crypto.DefaultAESCBCCipher; 43 | import io.jsondb.crypto.ICipher; 44 | import io.jsondb.tests.model.SecureVolume; 45 | import io.jsondb.tests.model.Volume; 46 | 47 | /** 48 | * @version 1.0 06-Oct-2016 49 | */ 50 | public class CollectionMetaDataTests { 51 | private String dbFilesLocation = "src/test/resources/dbfiles/collectionMetadataTests"; 52 | private File dbFilesFolder = new File(dbFilesLocation); 53 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 54 | ICipher cipher = null; 55 | 56 | @Before 57 | public void setUp() throws Exception { 58 | dbFilesFolder.mkdir(); 59 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 60 | cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 61 | } 62 | 63 | @After 64 | public void tearDown() throws Exception { 65 | Util.delete(dbFilesFolder); 66 | } 67 | 68 | @Test 69 | public void test_MetadataLoad_Simple() { 70 | Volume volume = new Volume(); 71 | CollectionMetaData cmd = new CollectionMetaData("volumes", volume.getClass(), "1.0", null); 72 | 73 | assertEquals("id", cmd.getIdAnnotatedFieldName()); 74 | assertEquals("getId", cmd.getIdAnnotatedFieldGetterMethod().getName()); 75 | assertEquals("setId", cmd.getIdAnnotatedFieldSetterMethod().getName()); 76 | 77 | List secretAnnotatedFieldNames = cmd.getSecretAnnotatedFieldNames(); 78 | assertEquals(0, secretAnnotatedFieldNames.size()); 79 | assertEquals(false, cmd.isSecretField("SomeField")); 80 | 81 | assertEquals("setName", cmd.getSetterMethodForFieldName("name").getName()); 82 | assertEquals("getName", cmd.getGetterMethodForFieldName("name").getName()); 83 | 84 | assertEquals("setFlash", cmd.getSetterMethodForFieldName("flash").getName()); 85 | assertEquals("isFlash", cmd.getGetterMethodForFieldName("flash").getName()); 86 | 87 | assertFalse(cmd.hasSecret()); 88 | 89 | assertEquals("1.0", cmd.getSchemaVersion()); 90 | 91 | assertNull(cmd.getActualSchemaVersion()); 92 | 93 | assertEquals("volumes", cmd.getCollectionName()); 94 | } 95 | 96 | @Test 97 | public void test_MetadataLoad_CollectionWithSecret() { 98 | SecureVolume server = new SecureVolume(); 99 | CollectionMetaData cmd = new CollectionMetaData("servers", server.getClass(), "1.0", null); 100 | 101 | assertEquals("id", cmd.getIdAnnotatedFieldName()); 102 | assertEquals("getId", cmd.getIdAnnotatedFieldGetterMethod().getName()); 103 | assertEquals("setId", cmd.getIdAnnotatedFieldSetterMethod().getName()); 104 | 105 | List secretAnnotatedFieldNames = cmd.getSecretAnnotatedFieldNames(); 106 | assertEquals(1, secretAnnotatedFieldNames.size()); 107 | assertEquals(true, cmd.isSecretField("encryptionKey")); 108 | 109 | assertTrue(cmd.hasSecret()); 110 | } 111 | 112 | @Test 113 | public void test_MetadataLoad_UsingBuilder() { 114 | JsonDBConfig dbConfig = new JsonDBConfig(dbFilesLocation, "io.jsondb.tests.model", cipher, false, null); 115 | Map cmdMap = CollectionMetaData.builder(dbConfig); 116 | CollectionMetaData cmd = cmdMap.get("instances"); 117 | assertNotNull(cmd); 118 | assertEquals("1.0", cmd.getSchemaVersion()); 119 | assertEquals("id", cmd.getIdAnnotatedFieldName()); 120 | assertEquals("getId", cmd.getIdAnnotatedFieldGetterMethod().getName()); 121 | assertEquals("setId", cmd.getIdAnnotatedFieldSetterMethod().getName()); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/CreateDropCollectionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertFalse; 25 | import static org.junit.Assert.assertTrue; 26 | 27 | import java.io.File; 28 | import java.util.List; 29 | import java.util.Set; 30 | 31 | import com.google.common.io.Files; 32 | 33 | import io.jsondb.DefaultSchemaVersionComparator; 34 | import io.jsondb.InvalidJsonDbApiUsageException; 35 | import io.jsondb.JsonDBTemplate; 36 | import io.jsondb.Util; 37 | import io.jsondb.tests.model.Instance; 38 | import io.jsondb.tests.model.Site; 39 | 40 | import org.junit.After; 41 | import org.junit.Before; 42 | import org.junit.Test; 43 | 44 | /** 45 | * @author Farooq Khan 46 | * @version 1.0 06-Oct-2016 47 | */ 48 | public class CreateDropCollectionTests { 49 | private String dbFilesLocation = "src/test/resources/dbfiles/createDropCollectionTests"; 50 | private File dbFilesFolder = new File(dbFilesLocation); 51 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 52 | private File sitesJson = new File(dbFilesFolder, "sites.json"); 53 | 54 | private JsonDBTemplate jsonDBTemplate = null; 55 | 56 | @Before 57 | public void setUp() throws Exception { 58 | dbFilesFolder.mkdir(); 59 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 60 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", false, new DefaultSchemaVersionComparator()); 61 | } 62 | 63 | @After 64 | public void tearDown() throws Exception { 65 | Util.delete(dbFilesFolder); 66 | } 67 | 68 | @Test 69 | public void testCreateDropCollection() { 70 | Set collectionNames = jsonDBTemplate.getCollectionNames(); 71 | assertTrue(collectionNames.contains("instances")); 72 | assertEquals("instances", jsonDBTemplate.getCollectionName(Instance.class)); 73 | assertEquals(collectionNames.size(), 1); 74 | 75 | jsonDBTemplate.createCollection(Site.class); 76 | assertTrue(sitesJson.exists()); 77 | 78 | collectionNames = jsonDBTemplate.getCollectionNames(); 79 | assertTrue(collectionNames.contains("instances")); 80 | assertTrue(collectionNames.contains("sites")); 81 | assertEquals(collectionNames.size(), 2); 82 | 83 | List sites = jsonDBTemplate.findAll(Site.class); 84 | assertEquals(sites.size(), 0); 85 | 86 | jsonDBTemplate.dropCollection(Site.class); 87 | assertFalse(sitesJson.exists()); 88 | 89 | collectionNames = jsonDBTemplate.getCollectionNames(); 90 | assertTrue(collectionNames.contains("instances")); 91 | assertEquals(collectionNames.size(), 1); 92 | } 93 | 94 | @Test 95 | public void testGetCollection() { 96 | Set collectionNames = jsonDBTemplate.getCollectionNames(); 97 | assertTrue(collectionNames.contains("instances")); 98 | assertEquals(collectionNames.size(), 1); 99 | 100 | jsonDBTemplate.getCollection(Site.class); 101 | assertTrue(sitesJson.exists()); 102 | 103 | collectionNames = jsonDBTemplate.getCollectionNames(); 104 | assertTrue(collectionNames.contains("instances")); 105 | assertTrue(collectionNames.contains("sites")); 106 | assertEquals(collectionNames.size(), 2); 107 | 108 | jsonDBTemplate.dropCollection(Site.class); 109 | assertFalse(sitesJson.exists()); 110 | } 111 | 112 | @Test(expected=InvalidJsonDbApiUsageException.class) 113 | public void testCreateCollectionForUnknownCollectionName() { 114 | jsonDBTemplate.createCollection("somecollection"); 115 | } 116 | 117 | private class SomeClass {} 118 | 119 | @Test(expected=InvalidJsonDbApiUsageException.class) 120 | public void testCreateCollectionForUnknownCollectionClass() { 121 | jsonDBTemplate.createCollection(SomeClass.class); 122 | } 123 | 124 | @Test(expected=InvalidJsonDbApiUsageException.class) 125 | public void testCreateCollectionWhenAlreadyExisting() { 126 | jsonDBTemplate.createCollection("instances"); 127 | } 128 | 129 | @Test 130 | public void testCollectionExists() { 131 | assertFalse(jsonDBTemplate.collectionExists("somecollection")); 132 | } 133 | 134 | @Test(expected=InvalidJsonDbApiUsageException.class) 135 | public void testDropCollectionForUnknownCollection() { 136 | jsonDBTemplate.dropCollection("SomeCollection"); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/DefaultAESCipherTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.*; 24 | 25 | import java.io.UnsupportedEncodingException; 26 | import java.nio.charset.StandardCharsets; 27 | import java.security.GeneralSecurityException; 28 | import java.security.InvalidKeyException; 29 | 30 | import org.hamcrest.core.IsInstanceOf; 31 | import org.junit.Rule; 32 | import org.junit.Test; 33 | import org.junit.rules.ExpectedException; 34 | 35 | import io.jsondb.JsonDBException; 36 | import io.jsondb.crypto.CryptoUtil; 37 | import io.jsondb.crypto.DefaultAESCBCCipher; 38 | import io.jsondb.crypto.Default1Cipher; 39 | import io.jsondb.crypto.ICipher; 40 | 41 | @SuppressWarnings("deprecation") 42 | public class DefaultAESCipherTests { 43 | @Rule 44 | public ExpectedException expectedException = ExpectedException.none(); 45 | 46 | @Test 47 | public void testKeyValidityAesCbc() throws UnsupportedEncodingException, GeneralSecurityException { 48 | expectedException.expect(InvalidKeyException.class); 49 | expectedException.expectMessage("Failed to create DefaultAESCBCCipher, something wrong with the key"); 50 | 51 | @SuppressWarnings("unused") 52 | DefaultAESCBCCipher cipher = new DefaultAESCBCCipher("badkey", "UTF-8"); 53 | } 54 | 55 | @Test 56 | public void testKeyAesCbc() throws UnsupportedEncodingException, GeneralSecurityException { 57 | String base64EncodedKey = CryptoUtil.generate128BitKey("MyPassword", "ksdfkja923u4anf"); 58 | 59 | ICipher cipher = new DefaultAESCBCCipher(base64EncodedKey); 60 | 61 | String encryptedText = cipher.encrypt("Hallo, Wie gehts"); 62 | assertEquals("cEIxZFDVSlWIN+ZmOGyvmbWv4+ziI884BNu0Hplglws=", encryptedText); 63 | String decryptedText = cipher.decrypt(encryptedText); 64 | assertEquals("Hallo, Wie gehts", decryptedText); 65 | } 66 | 67 | @Test 68 | public void testKeyValidityDefault1() throws UnsupportedEncodingException, GeneralSecurityException { 69 | expectedException.expect(JsonDBException.class); 70 | expectedException.expectCause(IsInstanceOf.any(InvalidKeyException.class)); 71 | 72 | Default1Cipher cipher = new Default1Cipher("badkey", StandardCharsets.UTF_8); 73 | @SuppressWarnings("unused") 74 | String encryptedText = cipher.encrypt("Hallo, Wie gehts"); 75 | } 76 | 77 | @Test 78 | public void testKeyDefault1() throws UnsupportedEncodingException, GeneralSecurityException { 79 | String base64EncodedKey = CryptoUtil.generate128BitKey("MyPassword", "ksdfkja923u4anf"); 80 | ICipher cipher = new Default1Cipher(base64EncodedKey); 81 | 82 | String msg = "Hallo, gru\u00DF"; 83 | 84 | String encryptedText = cipher.encrypt(msg); 85 | String decryptedText = cipher.decrypt(encryptedText); 86 | assertEquals(msg, decryptedText); 87 | assertTrue("ciphertext too short", encryptedText.length() > 40); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/EncryptionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 - 2018 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | 25 | import java.io.File; 26 | import java.security.GeneralSecurityException; 27 | 28 | import org.junit.After; 29 | import org.junit.Before; 30 | import org.junit.Rule; 31 | import org.junit.Test; 32 | import org.junit.rules.ExpectedException; 33 | 34 | import com.google.common.io.Files; 35 | 36 | import io.jsondb.InvalidJsonDbApiUsageException; 37 | import io.jsondb.JsonDBTemplate; 38 | import io.jsondb.Util; 39 | import io.jsondb.crypto.DefaultAESCBCCipher; 40 | import io.jsondb.crypto.ICipher; 41 | import io.jsondb.tests.model.Instance; 42 | import io.jsondb.tests.util.TestUtils; 43 | 44 | /** 45 | * Test for the encryption functionality 46 | * @version 1.0 22-Oct-2016 47 | */ 48 | @SuppressWarnings("deprecation") 49 | public class EncryptionTests { 50 | private String dbFilesLocation = "src/test/resources/dbfiles/encryptionTests"; 51 | private File dbFilesFolder = new File(dbFilesLocation); 52 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 53 | 54 | private String dbFilesLocation2 = "src/test/resources/dbfiles/encryptionTests2"; 55 | private File dbFilesFolder2 = new File(dbFilesLocation2); 56 | 57 | private JsonDBTemplate jsonDBTemplate = null; 58 | private JsonDBTemplate unencryptedjsonDBTemplate = null; 59 | 60 | @Rule 61 | public ExpectedException expectedException = ExpectedException.none(); 62 | 63 | @Before 64 | public void setUp() throws Exception { 65 | dbFilesFolder.mkdir(); 66 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 67 | ICipher cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 68 | 69 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 70 | 71 | unencryptedjsonDBTemplate = new JsonDBTemplate(dbFilesLocation2, "io.jsondb.tests.model"); 72 | } 73 | 74 | @After 75 | public void tearDown() throws Exception { 76 | Util.delete(dbFilesFolder); 77 | Util.delete(dbFilesFolder2); 78 | } 79 | 80 | @Test 81 | public void encryptionTest() { 82 | Instance instance = new Instance(); 83 | instance.setId("11"); 84 | instance.setHostname("ec2-54-191-11"); 85 | instance.setPrivateKey("b87eb02f5dd7e5232d7b0fc30a5015e4"); 86 | instance.setPublicKey("d3aa045f71bf4d1dffd2c5f485a4bc1d"); 87 | jsonDBTemplate.insert(instance); 88 | 89 | String[] expectedLastLineAtEnd = { 90 | "{\"id\":\"11\",\"hostname\":\"ec2-54-191-11\"," 91 | + "\"privateKey\":\"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop\"," 92 | + "\"publicKey\":\"d3aa045f71bf4d1dffd2c5f485a4bc1d\"}"}; 93 | 94 | TestUtils.checkLastLines(instancesJson, expectedLastLineAtEnd); 95 | 96 | Instance i = jsonDBTemplate.findById("11", "instances"); 97 | assertEquals("b87eb02f5dd7e5232d7b0fc30a5015e4", i.getPrivateKey()); 98 | } 99 | 100 | @Test 101 | public void changeEncryptionTest() { 102 | ICipher newCipher = null; 103 | try { 104 | newCipher = new DefaultAESCBCCipher("jCt039xT0eUwkIqAWACw/w=="); 105 | } catch (GeneralSecurityException e) { 106 | e.printStackTrace(); 107 | } 108 | 109 | jsonDBTemplate.changeEncryption(newCipher); 110 | 111 | String[] expectedLastLineAtEnd = { 112 | "{\"id\":\"06\",\"hostname\":\"ec2-54-191-06\"," 113 | + "\"privateKey\":\"J5CnDOTBe4OwePT43esS7vDb5DVqi+VGtRoICipcTdtyyh5N1gxbUdtvx8N9sCpZ\"," 114 | + "\"publicKey\":\"\"}"}; 115 | 116 | TestUtils.checkLastLines(instancesJson, expectedLastLineAtEnd); 117 | 118 | Instance i = jsonDBTemplate.findById("01", "instances"); 119 | assertEquals("b87eb02f5dd7e5232d7b0fc30a5015e4", i.getPrivateKey()); 120 | } 121 | 122 | @Test 123 | public void changeEncryptionTest2() throws GeneralSecurityException { 124 | ICipher newCipher = new DefaultAESCBCCipher("jCt039xT0eUwkIqAWACw/w=="); 125 | 126 | expectedException.expect(InvalidJsonDbApiUsageException.class); 127 | expectedException.expectMessage("DB is not encrypted, nothing to change for EncryptionKey"); 128 | 129 | unencryptedjsonDBTemplate.changeEncryption(newCipher); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/ExceptionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import org.junit.Rule; 24 | import org.junit.Test; 25 | import org.junit.rules.ExpectedException; 26 | 27 | import io.jsondb.InvalidJsonDbApiUsageException; 28 | import io.jsondb.JsonDBException; 29 | import io.jsondb.io.JsonFileLockException; 30 | 31 | /** 32 | * Dumb unit tests for some of the Exception classes 33 | * @version 1.0 25-Oct-2016 34 | */ 35 | public class ExceptionTests { 36 | 37 | @Rule 38 | public ExpectedException expectedException = ExpectedException.none(); 39 | 40 | @Test 41 | public void testJsonfileLockException() throws JsonFileLockException { 42 | expectedException.expect(JsonFileLockException.class); 43 | expectedException.expectMessage("JsonReader failed to obtain a file lock for file"); 44 | 45 | throw new JsonFileLockException("JsonReader failed to obtain a file lock for file", null); 46 | } 47 | 48 | @Test 49 | public void testJsonDBException1() throws JsonDBException { 50 | expectedException.expect(JsonDBException.class); 51 | expectedException.expectMessage("Some Exception"); 52 | 53 | throw new JsonDBException("Some Exception"); 54 | } 55 | 56 | @Test 57 | public void testJsonDBException2() throws JsonDBException { 58 | expectedException.expect(JsonDBException.class); 59 | expectedException.expectMessage("Some Exception"); 60 | 61 | throw new JsonDBException("Some Exception", null); 62 | } 63 | 64 | @Test 65 | public void testInvalidJsonDbApiUsageException() throws InvalidJsonDbApiUsageException { 66 | expectedException.expect(InvalidJsonDbApiUsageException.class); 67 | expectedException.expectMessage("Some Invalid usage"); 68 | 69 | throw new InvalidJsonDbApiUsageException("Some Invalid usage", null); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/FileChangeAdapterTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertFalse; 25 | import static org.junit.Assert.assertNotEquals; 26 | import static org.junit.Assert.assertNotNull; 27 | import static org.junit.Assert.assertTrue; 28 | import static org.junit.Assert.fail; 29 | import static org.junit.Assume.assumeTrue; 30 | 31 | import java.io.File; 32 | import java.io.FileNotFoundException; 33 | import java.io.IOException; 34 | import java.io.PrintWriter; 35 | import java.util.List; 36 | import java.util.Scanner; 37 | 38 | import org.junit.After; 39 | import org.junit.Before; 40 | import org.junit.Rule; 41 | import org.junit.Test; 42 | import org.junit.rules.ExpectedException; 43 | 44 | import com.google.common.io.Files; 45 | 46 | import io.jsondb.JsonDBTemplate; 47 | import io.jsondb.Util; 48 | import io.jsondb.crypto.DefaultAESCBCCipher; 49 | import io.jsondb.crypto.ICipher; 50 | import io.jsondb.events.CollectionFileChangeAdapter; 51 | import io.jsondb.tests.model.Instance; 52 | import io.jsondb.tests.model.PojoWithEnumFields; 53 | import io.jsondb.tests.util.TestUtils; 54 | 55 | /** 56 | * @version 1.0 24-Oct-2016 57 | */ 58 | public class FileChangeAdapterTests { 59 | 60 | private static final long DB_RELOAD_TIMEOUT = 5 * 1000; 61 | private String dbFilesLocation = "src/test/resources/dbfiles/eventsTests"; 62 | private File dbFilesFolder = new File(dbFilesLocation); 63 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 64 | private File pojoWithEnumFieldsJson = new File(dbFilesFolder, "pojowithenumfields.json"); 65 | 66 | private JsonDBTemplate jsonDBTemplate = null; 67 | 68 | @Rule 69 | public ExpectedException expectedException = ExpectedException.none(); 70 | 71 | @Before 72 | public void setUp() throws Exception { 73 | //Filewatcher does not work on Mac and hence JsonDB events will never fire 74 | //and so the EventTests will never succeed. So we run the tests only if 75 | //it is not a Mac system 76 | assumeTrue(!TestUtils.isMac()); 77 | 78 | dbFilesFolder.mkdir(); 79 | Files.copy(new File("src/test/resources/dbfiles/pojowithenumfields.json"), pojoWithEnumFieldsJson); 80 | ICipher cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 81 | 82 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 83 | } 84 | 85 | @After 86 | public void tearDown() throws Exception { 87 | Util.delete(dbFilesFolder); 88 | } 89 | 90 | private boolean collectionFileAddedFired = false; 91 | private class FileAddedChangeAdapter extends CollectionFileChangeAdapter { 92 | @Override 93 | public void collectionFileAdded(String collectionName) { 94 | super.collectionFileAdded(collectionName); 95 | jsonDBTemplate.reloadCollection(collectionName); 96 | collectionFileAddedFired = true; 97 | } 98 | } 99 | @Test 100 | public void testAutoReloadOnCollectionFileAdded() { 101 | jsonDBTemplate.addCollectionFileChangeListener(new FileAddedChangeAdapter()); 102 | assertFalse(jsonDBTemplate.collectionExists(Instance.class)); 103 | try { 104 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 105 | } catch (IOException e1) { 106 | fail("Failed to copy data store files"); 107 | } 108 | try { 109 | // Give it some time to reload DB 110 | Thread.sleep(DB_RELOAD_TIMEOUT); 111 | } catch (InterruptedException e) { 112 | fail("Failed to wait for db reload"); 113 | } 114 | assertTrue(collectionFileAddedFired); 115 | List instances = jsonDBTemplate.findAll(Instance.class); 116 | assertNotNull(instances); 117 | assertNotEquals(instances.size(), 0); 118 | } 119 | 120 | private boolean collectionFileModifiedFired = false; 121 | private class FileModifiedChangeAdapter extends CollectionFileChangeAdapter { 122 | @Override 123 | public void collectionFileModified(String collectionName) { 124 | super.collectionFileModified(collectionName); 125 | jsonDBTemplate.reloadCollection(collectionName); 126 | collectionFileModifiedFired = true; 127 | } 128 | } 129 | @Test 130 | public void testAutoReloadOnCollectionFileModified() throws FileNotFoundException { 131 | try { 132 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 133 | } catch (IOException e1) { 134 | fail("Failed to copy data store files"); 135 | } 136 | jsonDBTemplate.reLoadDB(); 137 | int oldCount = jsonDBTemplate.findAll(Instance.class).size(); 138 | jsonDBTemplate.addCollectionFileChangeListener(new FileModifiedChangeAdapter()); 139 | 140 | @SuppressWarnings("resource") 141 | Scanner sc = new Scanner(new File("src/test/resources/dbfiles/instances.json")).useDelimiter("\\Z"); 142 | String content = sc.next(); 143 | sc.close(); 144 | 145 | content = content + "\n" + "{\"id\":\"07\",\"hostname\":\"ec2-54-191-07\"," 146 | + "\"privateKey\":\"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop\"," 147 | + "\"publicKey\":\"d3aa045f71bf4d1dffd2c5f485a4bc1d\"}"; 148 | 149 | PrintWriter out = new PrintWriter(instancesJson); 150 | out.println(content); 151 | out.close(); 152 | 153 | try { 154 | // Give it some time to reload DB 155 | Thread.sleep(DB_RELOAD_TIMEOUT); 156 | } catch (InterruptedException e) { 157 | fail("Failed to wait for db reload"); 158 | } 159 | assertTrue(collectionFileModifiedFired); 160 | int newCount = jsonDBTemplate.findAll(Instance.class).size(); 161 | assertEquals(oldCount + 1, newCount); 162 | } 163 | 164 | private boolean collectionFileDeletedFired = false; 165 | private class FileDeletedChangeAdapter extends CollectionFileChangeAdapter { 166 | @Override 167 | public void collectionFileDeleted(String collectionName) { 168 | super.collectionFileDeleted(collectionName); 169 | jsonDBTemplate.reLoadDB(); 170 | collectionFileDeletedFired = true; 171 | } 172 | } 173 | @Test 174 | public void testAutoReloadOnCollectionFileDeleted() throws FileNotFoundException { 175 | assertTrue(jsonDBTemplate.collectionExists(PojoWithEnumFields.class)); 176 | 177 | jsonDBTemplate.addCollectionFileChangeListener(new FileDeletedChangeAdapter()); 178 | 179 | pojoWithEnumFieldsJson.delete(); 180 | 181 | try { 182 | // Give it some time to reload DB 183 | Thread.sleep(DB_RELOAD_TIMEOUT); 184 | } catch (InterruptedException e) { 185 | fail("Failed to wait for db reload"); 186 | } 187 | 188 | assertTrue(collectionFileDeletedFired); 189 | assertFalse(jsonDBTemplate.collectionExists(PojoWithEnumFields.class)); 190 | } 191 | 192 | private class DoNothingChangeAdapter extends CollectionFileChangeAdapter { 193 | } 194 | @Test 195 | public void testRemoveListener() { 196 | assertFalse(jsonDBTemplate.hasCollectionFileChangeListener()); 197 | 198 | CollectionFileChangeAdapter adapter = new DoNothingChangeAdapter(); 199 | jsonDBTemplate.addCollectionFileChangeListener(adapter); 200 | assertTrue(jsonDBTemplate.hasCollectionFileChangeListener()); 201 | 202 | jsonDBTemplate.removeCollectionFileChangeListener(adapter); 203 | assertFalse(jsonDBTemplate.hasCollectionFileChangeListener()); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/FindAndModifyTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | 25 | import java.io.File; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import org.junit.After; 30 | import org.junit.Before; 31 | import org.junit.Rule; 32 | import org.junit.Test; 33 | import org.junit.rules.ExpectedException; 34 | 35 | import com.google.common.io.Files; 36 | 37 | import io.jsondb.InvalidJsonDbApiUsageException; 38 | import io.jsondb.JsonDBTemplate; 39 | import io.jsondb.Util; 40 | import io.jsondb.crypto.DefaultAESCBCCipher; 41 | import io.jsondb.crypto.ICipher; 42 | import io.jsondb.query.Update; 43 | import io.jsondb.tests.model.Instance; 44 | import io.jsondb.tests.model.Site; 45 | 46 | /** 47 | * @version 1.0 15-Oct-2016 48 | */ 49 | public class FindAndModifyTests { 50 | private String dbFilesLocation = "src/test/resources/dbfiles/findAndModifyTests"; 51 | private File dbFilesFolder = new File(dbFilesLocation); 52 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 53 | 54 | private JsonDBTemplate jsonDBTemplate = null; 55 | 56 | @Rule 57 | public ExpectedException expectedException = ExpectedException.none(); 58 | 59 | @Before 60 | public void setUp() throws Exception { 61 | dbFilesFolder.mkdir(); 62 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 63 | ICipher cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 64 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 65 | } 66 | 67 | @After 68 | public void tearDown() throws Exception { 69 | Util.delete(dbFilesFolder); 70 | } 71 | 72 | @Test 73 | public void testFindAndModify_1() { 74 | Update update = new Update(); 75 | update.set("privateKey", "SavingPrivateRyan"); 76 | 77 | String jxQuery = String.format("/.[id='%s']", "01"); 78 | jsonDBTemplate.findAndModify(jxQuery, update, "instances"); 79 | 80 | Instance instance = jsonDBTemplate.findById("01", "instances"); 81 | assertEquals("SavingPrivateRyan", instance.getPrivateKey()); 82 | } 83 | 84 | @Test 85 | public void testFindAndModify_2() { 86 | Update update = Update.update("publicKey", "Its all Public"); 87 | 88 | String jxQuery = String.format("/.[id='%s']", "02"); 89 | jsonDBTemplate.findAndModify(jxQuery, update, "instances"); 90 | 91 | Instance instance = jsonDBTemplate.findById("02", "instances"); 92 | assertEquals("Its all Public", instance.getPublicKey()); 93 | } 94 | 95 | @Test 96 | public void testFindAndModify_3() { 97 | Update update = Update.update("SomeColumn1", "Value 1"); 98 | update.set("SomeColumn2", "Value 2"); 99 | 100 | Map allUpdates = update.getUpdateData(); 101 | assertEquals(2, allUpdates.size()); 102 | 103 | assertEquals("Value 1", allUpdates.get("SomeColumn1")); 104 | assertEquals("Value 2", allUpdates.get("SomeColumn2")); 105 | } 106 | 107 | @Test 108 | public void testFindAndModify_4() { 109 | Update update = Update.update("privateKey", "SavingPrivateRyan"); 110 | update.set("publicKey", "SavedByPublic"); 111 | 112 | String jxQuery = String.format("/.[id='%s']", "03"); 113 | Instance retInstance = jsonDBTemplate.findAndModify(jxQuery, update, "instances"); 114 | assertEquals("SavingPrivateRyan", retInstance.getPrivateKey()); 115 | assertEquals("SavedByPublic", retInstance.getPublicKey()); 116 | 117 | Instance instance = jsonDBTemplate.findById("03", "instances"); 118 | assertEquals("SavingPrivateRyan", instance.getPrivateKey()); 119 | assertEquals("SavedByPublic", instance.getPublicKey()); 120 | } 121 | 122 | @Test 123 | public void testFindAndModify_NonExistingCollection_1() { 124 | expectedException.expect(InvalidJsonDbApiUsageException.class); 125 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 126 | 127 | String jxQuery = String.format("/.[id>'%s']", "03"); 128 | jsonDBTemplate.findAndModify(jxQuery, null, "sites"); 129 | } 130 | 131 | @Test 132 | public void testFindAndModify_NonExistingCollection_2() { 133 | expectedException.expect(InvalidJsonDbApiUsageException.class); 134 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 135 | 136 | String jxQuery = String.format("/.[id>'%s']", "03"); 137 | 138 | jsonDBTemplate.findAndModify(jxQuery, null, Site.class); 139 | } 140 | 141 | @Test 142 | public void testFindAllAndModify() { 143 | Update update = Update.update("privateKey", "SavingPrivateRyan"); 144 | update.set("publicKey", "SavedByPublic"); 145 | 146 | String jxQuery = String.format("/.[id>'%s']", "03"); 147 | List retInstances = jsonDBTemplate.findAllAndModify(jxQuery, update, "instances"); 148 | assertEquals(3, retInstances.size()); 149 | assertEquals("SavingPrivateRyan", retInstances.get(0).getPrivateKey()); 150 | assertEquals("SavedByPublic", retInstances.get(0).getPublicKey()); 151 | assertEquals("SavingPrivateRyan", retInstances.get(1).getPrivateKey()); 152 | assertEquals("SavedByPublic", retInstances.get(1).getPublicKey()); 153 | assertEquals("SavingPrivateRyan", retInstances.get(2).getPrivateKey()); 154 | assertEquals("SavedByPublic", retInstances.get(2).getPublicKey()); 155 | 156 | Instance instance1 = jsonDBTemplate.findById("04", "instances"); 157 | assertEquals("SavingPrivateRyan", instance1.getPrivateKey()); 158 | assertEquals("SavedByPublic", instance1.getPublicKey()); 159 | 160 | Instance instance2 = jsonDBTemplate.findById("05", "instances"); 161 | assertEquals("SavingPrivateRyan", instance2.getPrivateKey()); 162 | assertEquals("SavedByPublic", instance2.getPublicKey()); 163 | 164 | Instance instance3 = jsonDBTemplate.findById("06", "instances"); 165 | assertEquals("SavingPrivateRyan", instance3.getPrivateKey()); 166 | assertEquals("SavedByPublic", instance3.getPublicKey()); 167 | } 168 | 169 | @Test 170 | public void testFindAllAndModify_NonExistingCollection_1() { 171 | expectedException.expect(InvalidJsonDbApiUsageException.class); 172 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 173 | 174 | String jxQuery = String.format("/.[id>'%s']", "03"); 175 | jsonDBTemplate.findAllAndModify(jxQuery, null, "sites"); 176 | } 177 | 178 | @Test 179 | public void testFindAllAndModify_NonExistingCollection_2() { 180 | expectedException.expect(InvalidJsonDbApiUsageException.class); 181 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 182 | 183 | String jxQuery = String.format("/.[id>'%s']", "03"); 184 | jsonDBTemplate.findAllAndModify(jxQuery, null, Site.class); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/FindAndRemoveTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertNotNull; 25 | import static org.junit.Assert.assertNull; 26 | 27 | import java.io.File; 28 | import java.util.List; 29 | 30 | import org.junit.After; 31 | import org.junit.Before; 32 | import org.junit.Rule; 33 | import org.junit.Test; 34 | import org.junit.rules.ExpectedException; 35 | 36 | import com.google.common.io.Files; 37 | 38 | import io.jsondb.InvalidJsonDbApiUsageException; 39 | import io.jsondb.JsonDBTemplate; 40 | import io.jsondb.Util; 41 | import io.jsondb.crypto.DefaultAESCBCCipher; 42 | import io.jsondb.crypto.ICipher; 43 | import io.jsondb.tests.model.Instance; 44 | import io.jsondb.tests.model.Site; 45 | 46 | /** 47 | * @version 1.0 11-Oct-2016 48 | */ 49 | public class FindAndRemoveTests { 50 | private String dbFilesLocation = "src/test/resources/dbfiles/findAndRemoveTests"; 51 | private File dbFilesFolder = new File(dbFilesLocation); 52 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 53 | 54 | private JsonDBTemplate jsonDBTemplate = null; 55 | 56 | @Rule 57 | public ExpectedException expectedException = ExpectedException.none(); 58 | 59 | @Before 60 | public void setUp() throws Exception { 61 | dbFilesFolder.mkdir(); 62 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 63 | ICipher cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 64 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 65 | } 66 | 67 | @After 68 | public void tearDown() throws Exception { 69 | Util.delete(dbFilesFolder); 70 | } 71 | 72 | /** 73 | * Test to remove a single non-existing object from a collection 74 | */ 75 | @Test 76 | public void testRemove_NonExistingObject() { 77 | String jxQuery = String.format("/.[id='%s']", "12"); 78 | Instance i = jsonDBTemplate.findAndRemove(jxQuery, Instance.class); 79 | 80 | assertNull(i); 81 | } 82 | 83 | /** 84 | * Test to remove a null object from a collection 85 | */ 86 | @Test 87 | public void testRemove_NullObject() { 88 | expectedException.expect(InvalidJsonDbApiUsageException.class); 89 | expectedException.expectMessage("Query string cannot be null."); 90 | 91 | jsonDBTemplate.findAndRemove(null, Instance.class); 92 | } 93 | 94 | /** 95 | * Test to remove a object from a non-existent collection 96 | */ 97 | @Test 98 | public void testRemove_FromNonExistingCollection_1() { 99 | expectedException.expect(InvalidJsonDbApiUsageException.class); 100 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 101 | 102 | String jxQuery = String.format("/.[id='%s']", "12"); 103 | jsonDBTemplate.findAndRemove(jxQuery, Site.class); 104 | } 105 | 106 | /** 107 | * Test to remove a object from a non-existent collection 108 | */ 109 | @Test 110 | public void testRemove_FromNonExistingCollection_2() { 111 | expectedException.expect(InvalidJsonDbApiUsageException.class); 112 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 113 | 114 | String jxQuery = String.format("/.[id='%s']", "12"); 115 | jsonDBTemplate.findAndRemove(jxQuery, "sites"); 116 | } 117 | 118 | /** 119 | * Test to remove a single object from a collection 120 | */ 121 | @Test 122 | public void testRemove_ValidObject() { 123 | List instances = jsonDBTemplate.getCollection(Instance.class); 124 | int size = instances.size(); 125 | 126 | String jxQuery = String.format("/.[id='%s']", "05"); 127 | Instance removedObject = jsonDBTemplate.findAndRemove(jxQuery, Instance.class); 128 | 129 | instances = jsonDBTemplate.getCollection(Instance.class); 130 | assertNotNull(instances); 131 | assertEquals(size-1, instances.size()); 132 | assertNotNull(removedObject); 133 | assertEquals("05", removedObject.getId()); 134 | } 135 | 136 | /** 137 | * Test to remove a batch of objects from collection 138 | */ 139 | @Test 140 | public void testRemove_OneofManyObjects() { 141 | List instances = jsonDBTemplate.getCollection(Instance.class); 142 | int size = instances.size(); 143 | 144 | String jxQuery = String.format("/.[id>'%s']", "04"); 145 | 146 | Instance removedObjects = jsonDBTemplate.findAndRemove(jxQuery, Instance.class); 147 | 148 | instances = jsonDBTemplate.getCollection(Instance.class); 149 | assertNotNull(instances); 150 | assertEquals(size-1, instances.size()); 151 | assertNotNull(removedObjects); 152 | } 153 | 154 | /** 155 | * Test to remove a batch of objects from collection 156 | */ 157 | @Test 158 | public void testRemove_BatchOfObjects() { 159 | List instances = jsonDBTemplate.getCollection(Instance.class); 160 | int size = instances.size(); 161 | 162 | String jxQuery = String.format("/.[id>'%s']", "04"); 163 | 164 | List removedObjects = jsonDBTemplate.findAllAndRemove(jxQuery, Instance.class); 165 | 166 | instances = jsonDBTemplate.getCollection(Instance.class); 167 | assertNotNull(instances); 168 | assertEquals(size-2, instances.size()); 169 | assertNotNull(removedObjects); 170 | assertEquals(2, removedObjects.size()); 171 | } 172 | 173 | /** 174 | * Test to remove a object from a non-existent collection 175 | */ 176 | @Test 177 | public void testFindAllAndRemove_FromNonExistingCollection_1() { 178 | expectedException.expect(InvalidJsonDbApiUsageException.class); 179 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 180 | 181 | String jxQuery = String.format("/.[id='%s']", "12"); 182 | jsonDBTemplate.findAllAndRemove(jxQuery, Site.class); 183 | } 184 | 185 | /** 186 | * Test to remove a object from a non-existent collection 187 | */ 188 | @Test 189 | public void testFindAllAndRemove_FromNonExistingCollection_2() { 190 | expectedException.expect(InvalidJsonDbApiUsageException.class); 191 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 192 | 193 | String jxQuery = String.format("/.[id='%s']", "12"); 194 | jsonDBTemplate.findAllAndRemove(jxQuery, "sites"); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/FindByIdTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertNotNull; 25 | import static org.junit.Assert.assertNull; 26 | 27 | import java.io.File; 28 | 29 | import org.junit.After; 30 | import org.junit.Before; 31 | import org.junit.Rule; 32 | import org.junit.Test; 33 | import org.junit.rules.ExpectedException; 34 | 35 | import com.google.common.io.Files; 36 | 37 | import io.jsondb.InvalidJsonDbApiUsageException; 38 | import io.jsondb.JsonDBTemplate; 39 | import io.jsondb.Util; 40 | import io.jsondb.crypto.DefaultAESCBCCipher; 41 | import io.jsondb.crypto.ICipher; 42 | import io.jsondb.tests.model.Instance; 43 | 44 | /** 45 | * @version 1.0 14-Oct-2016 46 | */ 47 | public class FindByIdTests { 48 | private String dbFilesLocation = "src/test/resources/dbfiles/findByIdTests"; 49 | private File dbFilesFolder = new File(dbFilesLocation); 50 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 51 | 52 | private JsonDBTemplate jsonDBTemplate = null; 53 | 54 | @Rule 55 | public ExpectedException expectedException = ExpectedException.none(); 56 | 57 | @Before 58 | public void setUp() throws Exception { 59 | dbFilesFolder.mkdir(); 60 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 61 | ICipher cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 62 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 63 | } 64 | 65 | @After 66 | public void tearDown() throws Exception { 67 | Util.delete(dbFilesFolder); 68 | } 69 | 70 | /** 71 | * test to find a document with a existing id. 72 | */ 73 | @Test 74 | public void testFindById_ForExistingId() { 75 | Instance instance = jsonDBTemplate.findById("01", Instance.class); 76 | assertNotNull(instance); 77 | assertEquals(instance.getId(), "01"); 78 | } 79 | 80 | /** 81 | * test to find a document with a non-existent id. 82 | */ 83 | @Test 84 | public void testFindById_ForNonExistentId() { 85 | Instance instance = jsonDBTemplate.findById("00", Instance.class); 86 | assertNull(instance); 87 | } 88 | 89 | private class NonAnotatedClass {} 90 | 91 | /** 92 | * test to find a document formEntity type which does not have @Document annotation 93 | */ 94 | @Test 95 | public void testFindById_NonAnotatedClass() { 96 | expectedException.expect(InvalidJsonDbApiUsageException.class); 97 | expectedException.expectMessage("Entity 'NonAnotatedClass' is not annotated with annotation @Document"); 98 | jsonDBTemplate.findById("000000", NonAnotatedClass.class); 99 | } 100 | 101 | /** 102 | * test to find a document for a unknown collection name 103 | */ 104 | @Test 105 | public void testFindById_UnknownCollectionName() { 106 | expectedException.expect(InvalidJsonDbApiUsageException.class); 107 | expectedException.expectMessage("Collection by name 'SomeCollection' not found. Create collection first"); 108 | jsonDBTemplate.findById("000000", "SomeCollection"); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/InitializeDBNegativeTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertTrue; 25 | import static org.junit.Assert.fail; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.security.GeneralSecurityException; 30 | import java.util.Set; 31 | 32 | import org.junit.After; 33 | import org.junit.Before; 34 | import org.junit.Rule; 35 | import org.junit.Test; 36 | import org.junit.rules.ExpectedException; 37 | 38 | import com.google.common.io.Files; 39 | 40 | import io.jsondb.InvalidJsonDbApiUsageException; 41 | import io.jsondb.JsonDBTemplate; 42 | import io.jsondb.Util; 43 | import io.jsondb.crypto.DefaultAESCBCCipher; 44 | import io.jsondb.crypto.ICipher; 45 | 46 | /** 47 | * Unit tests that cover all aspects of DB initialization 48 | * 49 | * @author Farooq Khan 50 | * @version 1.0 06-Oct-2016 51 | */ 52 | public class InitializeDBNegativeTests { 53 | 54 | private String dbFilesLocation = "src/test/resources/dbfiles/dbInitializationTests"; 55 | private File dbFilesFolder = new File(dbFilesLocation); 56 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 57 | 58 | @Rule 59 | public ExpectedException expectedException = ExpectedException.none(); 60 | 61 | @Before 62 | public void setup() throws IOException, GeneralSecurityException { 63 | dbFilesFolder.mkdir(); 64 | } 65 | 66 | @After 67 | public void tearDown() { 68 | Util.delete(dbFilesFolder); 69 | } 70 | 71 | /** 72 | * A test to see if verify if JsonDB will get initialized when emtpy directory is passed. 73 | */ 74 | @Test 75 | public void testEmptyDBInitialization() { 76 | JsonDBTemplate jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model"); 77 | 78 | Set collectionNames = jsonDBTemplate.getCollectionNames(); 79 | assertEquals(collectionNames.size(), 0); 80 | } 81 | 82 | /** 83 | * A test to see if JsonDB will initialize when a non existing directory is passed 84 | */ 85 | @Test 86 | public void testMissingDBLocationInitialization_1() { 87 | File someDbFilesFolder = new File(dbFilesLocation, "someMissingFolder"); 88 | JsonDBTemplate jsonDBTemplate = new JsonDBTemplate(someDbFilesFolder.toString(), "org.jsondb.testmodel"); 89 | 90 | assertTrue(someDbFilesFolder.exists()); 91 | assertTrue(someDbFilesFolder.isDirectory()); 92 | 93 | Set collectionNames = jsonDBTemplate.getCollectionNames(); 94 | assertEquals(collectionNames.size(), 0); 95 | } 96 | 97 | /** 98 | * A test to see if JsonDB will throw exception when passing non-creatable a non existing directory is passed 99 | */ 100 | @Test 101 | public void testMissingDBLocationInitialization_2() { 102 | File someDbFilesFolder = new File(dbFilesLocation, "someMissingFolder2"); 103 | try { 104 | someDbFilesFolder.createNewFile(); 105 | } catch (IOException e) { 106 | fail("Failed while creating temporary folder " + someDbFilesFolder.toString()); 107 | } 108 | 109 | expectedException.expect(InvalidJsonDbApiUsageException.class); 110 | expectedException.expectMessage("Specified DbFiles directory is actually a file cannot use it as a directory"); 111 | 112 | new JsonDBTemplate(someDbFilesFolder.toString(), "org.jsondb.tests.model"); 113 | } 114 | 115 | @Test 116 | public void testDBInitializationforMissingFile() throws IOException, GeneralSecurityException { 117 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 118 | ICipher cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 119 | JsonDBTemplate jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 120 | 121 | assertTrue(jsonDBTemplate.collectionExists("instances")); 122 | 123 | instancesJson.delete(); 124 | jsonDBTemplate.reloadCollection("instances"); 125 | assertTrue(!jsonDBTemplate.collectionExists("instances")); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/InitializeDBTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertTrue; 25 | 26 | import java.io.File; 27 | import java.io.FileWriter; 28 | import java.io.IOException; 29 | import java.security.GeneralSecurityException; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | import java.util.Set; 33 | 34 | import org.junit.After; 35 | import org.junit.Before; 36 | import org.junit.Test; 37 | 38 | import com.fasterxml.jackson.databind.ObjectMapper; 39 | import com.google.common.io.Files; 40 | 41 | import io.jsondb.JsonDBTemplate; 42 | import io.jsondb.Util; 43 | import io.jsondb.crypto.DefaultAESCBCCipher; 44 | import io.jsondb.crypto.ICipher; 45 | import io.jsondb.tests.model.Instance; 46 | 47 | /** 48 | * Unit tests that cover all aspects of DB initialization 49 | * 50 | * @author Farooq Khan 51 | * @version 1.0 31 Dec 2015 52 | */ 53 | public class InitializeDBTests { 54 | 55 | private ObjectMapper objectMapper = null; 56 | 57 | private String dbFilesLocation = "src/test/resources/dbfiles/initializationTests"; 58 | private File dbFilesFolder = new File(dbFilesLocation); 59 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 60 | private ICipher cipher; 61 | 62 | @Before 63 | public void setup() throws IOException { 64 | dbFilesFolder.mkdir(); 65 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 66 | try { 67 | cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 68 | } catch (GeneralSecurityException e) { 69 | // TODO Auto-generated catch block 70 | e.printStackTrace(); 71 | } 72 | objectMapper = new ObjectMapper(); 73 | } 74 | 75 | @After 76 | public void tearDown() { 77 | Util.delete(dbFilesFolder); 78 | } 79 | 80 | @Test 81 | public void testInitialization() { 82 | JsonDBTemplate jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model"); 83 | 84 | Set collectionNames = jsonDBTemplate.getCollectionNames(); 85 | assertTrue(collectionNames.contains("instances")); 86 | assertEquals(collectionNames.size(), 1); 87 | } 88 | 89 | @Test 90 | public void testReload() { 91 | JsonDBTemplate jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 92 | 93 | Set collectionNames = jsonDBTemplate.getCollectionNames(); 94 | assertTrue(collectionNames.contains("instances")); 95 | List instances = jsonDBTemplate.findAll(Instance.class); 96 | int size = instances.size(); 97 | 98 | //Add more computers directly to the computers.json file. 99 | List instances1 = new ArrayList(); 100 | for (int i = 0; i<10; i++) { 101 | Instance inst = new Instance(); 102 | int id = 11 + i; 103 | inst.setId(String.format("%02d", id)); 104 | inst.setHostname("ec2-54-191-" + id); 105 | //Private key is encrypted form of: b87eb02f5dd7e5232d7b0fc30a5015e4 106 | inst.setPrivateKey("Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop"); 107 | inst.setPublicKey("d3aa045f71bf4d1dffd2c5f485a4bc1d"); 108 | instances1.add(inst); 109 | } 110 | appendDirectlyToJsonFile(instances1, instancesJson); 111 | 112 | jsonDBTemplate.reLoadDB(); 113 | 114 | collectionNames = jsonDBTemplate.getCollectionNames(); 115 | assertTrue(collectionNames.contains("instances")); 116 | instances = jsonDBTemplate.findAll(Instance.class); 117 | assertEquals(instances.size(), size+10); 118 | } 119 | 120 | private boolean appendDirectlyToJsonFile(List collectionData, File collectionFile) { 121 | 122 | boolean retval = false; 123 | FileWriter fw = null; 124 | try { 125 | fw = new FileWriter(collectionFile, true); 126 | for (T row : collectionData) { 127 | fw.write(objectMapper.writeValueAsString(row)); 128 | fw.write("\n"); 129 | } 130 | retval = true; 131 | } catch (IOException e) { 132 | retval = false; 133 | e.printStackTrace(); 134 | } finally { 135 | if (null != fw) { 136 | try { 137 | fw.close(); 138 | } catch (IOException e) { 139 | // do nothing 140 | } 141 | } 142 | } 143 | return retval; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/JsonDBConfigTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertFalse; 25 | import static org.junit.Assert.assertNull; 26 | import static org.junit.Assert.assertTrue; 27 | 28 | import java.io.File; 29 | import java.nio.charset.Charset; 30 | 31 | import org.junit.Test; 32 | 33 | import com.fasterxml.jackson.databind.DeserializationFeature; 34 | import com.fasterxml.jackson.databind.ObjectMapper; 35 | 36 | import io.jsondb.DefaultSchemaVersionComparator; 37 | import io.jsondb.JsonDBConfig; 38 | import io.jsondb.crypto.ICipher; 39 | 40 | /** 41 | * @version 1.0 08-Oct-2016 42 | */ 43 | public class JsonDBConfigTests { 44 | 45 | private String dbFilesLocation = "src/test/resources/dbfiles/dbConfigTests"; 46 | 47 | @Test 48 | public void testDbConfig() { 49 | JsonDBConfig dbConfig = new JsonDBConfig(dbFilesLocation, "io.jsondb.tests.model", null, false, 50 | new DefaultSchemaVersionComparator()); 51 | 52 | assertEquals("src/test/resources/dbfiles/dbConfigTests", dbConfig.getDbFilesLocationString()); 53 | assertEquals(new File("src/test/resources/dbfiles/dbConfigTests"), dbConfig.getDbFilesLocation()); 54 | assertEquals(new File("src/test/resources/dbfiles/dbConfigTests").toPath(), dbConfig.getDbFilesPath()); 55 | assertEquals(Charset.forName("UTF-8"), dbConfig.getCharset()); 56 | assertNull(dbConfig.getCipher()); 57 | assertFalse(dbConfig.isCompatibilityMode()); 58 | 59 | dbConfig.setDbFilesLocationString("myfolder"); 60 | assertEquals("myfolder", dbConfig.getDbFilesLocationString()); 61 | assertEquals(new File("myfolder"), dbConfig.getDbFilesLocation()); 62 | assertEquals(new File("myfolder").toPath(), dbConfig.getDbFilesPath()); 63 | 64 | Charset newCharset = Charset.forName("UTF-16"); 65 | dbConfig.setCharset(newCharset); 66 | assertEquals(newCharset, dbConfig.getCharset()); 67 | 68 | ICipher mCipher = new MyCipher(); 69 | dbConfig.setCipher(mCipher); 70 | assertEquals(mCipher, dbConfig.getCipher()); 71 | 72 | dbConfig.setBaseScanPackage("io.newpackage"); 73 | assertEquals("io.newpackage", dbConfig.getBaseScanPackage()); 74 | 75 | ObjectMapper mapper = dbConfig.getObjectMapper(); 76 | assertTrue(mapper.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); 77 | dbConfig.setCompatibilityMode(true); 78 | assertFalse(mapper.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); 79 | dbConfig.setCompatibilityMode(false); 80 | assertTrue(mapper.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); 81 | 82 | ObjectMapper newMapper = new ObjectMapper(); 83 | dbConfig.setObjectMapper(newMapper); 84 | assertEquals(newMapper, dbConfig.getObjectMapper()); 85 | } 86 | 87 | 88 | private class MyCipher implements ICipher { 89 | 90 | /* (non-Javadoc) 91 | * @see io.jsondb.crypto.ICipher#encrypt(java.lang.String) 92 | */ 93 | @Override 94 | public String encrypt(String plainText) { 95 | // TODO Auto-generated method stub 96 | return null; 97 | } 98 | 99 | /* (non-Javadoc) 100 | * @see io.jsondb.crypto.ICipher#decrypt(java.lang.String) 101 | */ 102 | @Override 103 | public String decrypt(String cipherText) { 104 | // TODO Auto-generated method stub 105 | return null; 106 | } 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/JsonReaderTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertNotNull; 25 | 26 | import java.io.File; 27 | import java.io.IOException; 28 | import java.io.RandomAccessFile; 29 | import java.nio.channels.FileChannel; 30 | 31 | import org.junit.After; 32 | import org.junit.Before; 33 | import org.junit.Rule; 34 | import org.junit.Test; 35 | import org.junit.rules.ExpectedException; 36 | 37 | import com.google.common.io.Files; 38 | 39 | import io.jsondb.DefaultSchemaVersionComparator; 40 | import io.jsondb.JsonDBConfig; 41 | import io.jsondb.Util; 42 | import io.jsondb.io.JsonFileLockException; 43 | import io.jsondb.io.JsonReader; 44 | 45 | /** 46 | * Unit tests for JsonReader IO utility class 47 | * @version 1.0 11-Dec-2017 48 | */ 49 | public class JsonReaderTests { 50 | 51 | private String dbFilesLocation = "src/test/resources/dbfiles/jsonReaderTests"; 52 | private File dbFilesFolder = new File(dbFilesLocation); 53 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 54 | 55 | @Rule 56 | public ExpectedException expectedException = ExpectedException.none(); 57 | 58 | /** 59 | * @throws java.lang.Exception 60 | */ 61 | @Before 62 | public void setUp() throws Exception { 63 | dbFilesFolder.mkdir(); 64 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 65 | } 66 | 67 | @After 68 | public void tearDown() throws Exception { 69 | Util.delete(dbFilesFolder); 70 | } 71 | 72 | @Test 73 | public void testReadLine() throws IOException { 74 | JsonDBConfig dbConfig = new JsonDBConfig(dbFilesLocation, "io.jsondb.tests.model", null, false, 75 | new DefaultSchemaVersionComparator()); 76 | 77 | JsonReader jr = new JsonReader(dbConfig, instancesJson); 78 | 79 | assertNotNull(jr); 80 | assertEquals("{\"schemaVersion\":\"1.0\"}", jr.readLine()); 81 | } 82 | 83 | @Test 84 | public void testLockException() throws IOException { 85 | File lockFolder = new File(dbFilesLocation, "lock"); 86 | if (!lockFolder.exists()) { 87 | lockFolder.mkdirs(); 88 | } 89 | File fileLockLocation = new File(lockFolder, "instances.json.lock"); 90 | RandomAccessFile raf = new RandomAccessFile(fileLockLocation, "rw"); 91 | raf.writeInt(0); //Will cause creation of the file 92 | 93 | FileChannel channel = raf.getChannel(); 94 | try { 95 | channel.lock(); 96 | } catch (IOException e) { 97 | //Ignore 98 | } 99 | 100 | expectedException.expect(JsonFileLockException.class); 101 | expectedException.expectMessage("JsonReader failed to obtain a file lock for file " + fileLockLocation); 102 | 103 | JsonDBConfig dbConfig = new JsonDBConfig(dbFilesLocation, "io.jsondb.tests.model", null, false, 104 | new DefaultSchemaVersionComparator()); 105 | 106 | @SuppressWarnings("unused") 107 | JsonReader jr = new JsonReader(dbConfig, instancesJson); 108 | raf.close(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/JsonWriterTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertNotNull; 24 | 25 | import java.io.File; 26 | import java.io.IOException; 27 | 28 | import org.junit.After; 29 | import org.junit.Before; 30 | import org.junit.Rule; 31 | import org.junit.Test; 32 | import org.junit.rules.ExpectedException; 33 | 34 | import com.google.common.io.Files; 35 | 36 | import io.jsondb.CollectionMetaData; 37 | import io.jsondb.DefaultSchemaVersionComparator; 38 | import io.jsondb.JsonDBConfig; 39 | import io.jsondb.Util; 40 | import io.jsondb.io.JsonWriter; 41 | import io.jsondb.tests.model.Instance; 42 | 43 | /** 44 | * Unit tests for JsonWriter IO utility class 45 | * @version 1.0 11-Dec-2017 46 | */ 47 | public class JsonWriterTests { 48 | 49 | private String dbFilesLocation = "src/test/resources/dbfiles/jsonWriterTests"; 50 | private File dbFilesFolder = new File(dbFilesLocation); 51 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 52 | 53 | @Rule 54 | public ExpectedException expectedException = ExpectedException.none(); 55 | 56 | /** 57 | * @throws java.lang.Exception 58 | */ 59 | @Before 60 | public void setUp() throws Exception { 61 | dbFilesFolder.mkdir(); 62 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 63 | } 64 | 65 | @After 66 | public void tearDown() throws Exception { 67 | Util.delete(dbFilesFolder); 68 | } 69 | 70 | @Test 71 | public void test() throws IOException { 72 | JsonDBConfig dbConfig = new JsonDBConfig(dbFilesLocation, "io.jsondb.tests.model", null, false, 73 | new DefaultSchemaVersionComparator()); 74 | 75 | CollectionMetaData cmd = new CollectionMetaData("instances", new Instance().getClass(), "1.0", null); 76 | 77 | JsonWriter jr = new JsonWriter(dbConfig, cmd, "instances", instancesJson); 78 | 79 | assertNotNull(jr); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/LoadInvalidJsonTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | 25 | import java.io.File; 26 | import java.io.IOException; 27 | import java.util.Set; 28 | 29 | import org.junit.After; 30 | import org.junit.Before; 31 | import org.junit.Test; 32 | 33 | import com.google.common.io.Files; 34 | 35 | import io.jsondb.JsonDBTemplate; 36 | import io.jsondb.Util; 37 | import io.jsondb.tests.util.TestUtils; 38 | 39 | /** 40 | * @version 1.0 19-Oct-2018 41 | */ 42 | public class LoadInvalidJsonTests { 43 | 44 | private String dbFilesLocation = "src/test/resources/dbfiles/loadInvalidJsonTests"; 45 | private File dbFilesFolder = new File(dbFilesLocation); 46 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 47 | 48 | @Before 49 | public void setup() throws IOException { 50 | dbFilesFolder.mkdir(); 51 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 52 | } 53 | 54 | @After 55 | public void tearDown() { 56 | Util.delete(dbFilesFolder); 57 | } 58 | 59 | /** 60 | * A test to ensure JsonDB does not delete the source files when a exception occurs during loading 61 | */ 62 | @Test 63 | public void testLoadForInvalidJson() { 64 | // The invalidJson has semicolon instead of a colon between the id attribute name and value 65 | String invalidJson = "{\"id\"=\"07\",\"hostname\":\"ec2-54-191-07\",\"privateKey\":\"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop\",\"publicKey\":\"\"}"; 66 | 67 | TestUtils.appendDirectToFile(instancesJson, invalidJson); 68 | 69 | JsonDBTemplate jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model"); 70 | Set collectionNames = jsonDBTemplate.getCollectionNames(); 71 | 72 | assertEquals(collectionNames.size(), 0); 73 | assertEquals(8, TestUtils.getNoOfLinesInFile(instancesJson)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/PojoWithEnumFieldsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertNotNull; 25 | 26 | import java.io.File; 27 | import java.util.List; 28 | 29 | import org.junit.After; 30 | import org.junit.Before; 31 | import org.junit.Test; 32 | 33 | import com.google.common.io.Files; 34 | 35 | import io.jsondb.JsonDBTemplate; 36 | import io.jsondb.Util; 37 | import io.jsondb.tests.model.PojoWithEnumFields; 38 | import io.jsondb.tests.model.PojoWithEnumFields.Status; 39 | 40 | /** 41 | * @author Farooq Khan 42 | * @version 1.0 06-Oct-2016 43 | */ 44 | public class PojoWithEnumFieldsTest { 45 | private String dbFilesLocation = "src/test/resources/dbfiles/pojowithenumfieldsTests"; 46 | private File dbFilesFolder = new File(dbFilesLocation); 47 | private File pojoWithEnumFieldsJson = new File(dbFilesFolder, "pojowithenumfields.json"); 48 | 49 | private JsonDBTemplate jsonDBTemplate = null; 50 | 51 | @Before 52 | public void setUp() throws Exception { 53 | dbFilesFolder.mkdir(); 54 | Files.copy(new File("src/test/resources/dbfiles/pojowithenumfields.json"), pojoWithEnumFieldsJson); 55 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model"); 56 | } 57 | 58 | @After 59 | public void tearDown() throws Exception { 60 | Util.delete(dbFilesFolder); 61 | } 62 | 63 | @Test 64 | public void testFind() { 65 | PojoWithEnumFields clazz = jsonDBTemplate.findById("0001", PojoWithEnumFields.class); 66 | 67 | assertNotNull(clazz); 68 | 69 | assertEquals(clazz.getStatus(), Status.CREATED); 70 | } 71 | 72 | @Test 73 | public void testInsert() { 74 | List clazzs = jsonDBTemplate.getCollection(PojoWithEnumFields.class); 75 | int size = clazzs.size(); 76 | 77 | PojoWithEnumFields clazz = new PojoWithEnumFields(); 78 | clazz.setId("0010"); 79 | clazz.setStatus(Status.UPDATED); 80 | jsonDBTemplate.insert(clazz); 81 | 82 | clazzs = jsonDBTemplate.getCollection(PojoWithEnumFields.class); 83 | assertNotNull(clazzs); 84 | assertEquals(clazzs.size(), size+1); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/RemoveTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertNotNull; 25 | 26 | import java.io.File; 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | import org.junit.After; 31 | import org.junit.Before; 32 | import org.junit.Rule; 33 | import org.junit.Test; 34 | import org.junit.rules.ExpectedException; 35 | 36 | import com.google.common.io.Files; 37 | 38 | import io.jsondb.InvalidJsonDbApiUsageException; 39 | import io.jsondb.JsonDBTemplate; 40 | import io.jsondb.Util; 41 | import io.jsondb.crypto.DefaultAESCBCCipher; 42 | import io.jsondb.crypto.ICipher; 43 | import io.jsondb.tests.model.Instance; 44 | import io.jsondb.tests.model.Site; 45 | 46 | /** 47 | * Junit tests for the remove() apis 48 | * 49 | * @version 1.0 08-Oct-2016 50 | */ 51 | public class RemoveTests { 52 | 53 | private String dbFilesLocation = "src/test/resources/dbfiles/removeTests"; 54 | private File dbFilesFolder = new File(dbFilesLocation); 55 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 56 | 57 | private JsonDBTemplate jsonDBTemplate = null; 58 | 59 | @Rule 60 | public ExpectedException expectedException = ExpectedException.none(); 61 | 62 | @Before 63 | public void setUp() throws Exception { 64 | dbFilesFolder.mkdir(); 65 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 66 | ICipher cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 67 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 68 | } 69 | 70 | @After 71 | public void tearDown() throws Exception { 72 | Util.delete(dbFilesFolder); 73 | } 74 | 75 | /** 76 | * Test to remove a single non-existing object from a collection 77 | */ 78 | @Test 79 | public void testRemove_NonExistingObject() { 80 | expectedException.expect(InvalidJsonDbApiUsageException.class); 81 | expectedException.expectMessage("Objects with Id 000012 not found in collection instances"); 82 | 83 | Instance instance = new Instance(); 84 | instance.setId("000012"); 85 | 86 | jsonDBTemplate.remove(instance, Instance.class); 87 | } 88 | 89 | /** 90 | * Test to remove a null object from a collection 91 | */ 92 | @Test 93 | public void testRemove_NullObject() { 94 | expectedException.expect(InvalidJsonDbApiUsageException.class); 95 | expectedException.expectMessage("Null Object cannot be removed from DB"); 96 | Object nullObject = null; 97 | jsonDBTemplate.remove(nullObject, Instance.class); 98 | } 99 | 100 | /** 101 | * Test to remove a null object from a collection 102 | */ 103 | @Test 104 | public void testRemove_NullObjectBatch() { 105 | expectedException.expect(InvalidJsonDbApiUsageException.class); 106 | expectedException.expectMessage("Null Object batch cannot be removed from DB"); 107 | 108 | jsonDBTemplate.remove(null, Instance.class); 109 | } 110 | 111 | /** 112 | * Test to remove a object from a non-existent collection 113 | */ 114 | @Test 115 | public void testRemove_FromNonExistingCollection() { 116 | expectedException.expect(InvalidJsonDbApiUsageException.class); 117 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 118 | 119 | Site s = new Site(); 120 | s.setId("000012"); 121 | 122 | jsonDBTemplate.remove(s, Site.class); 123 | } 124 | 125 | /** 126 | * Test to remove a object from a non-existent collection 127 | */ 128 | @Test 129 | public void testRemoveBatch_FromNonExistingCollection() { 130 | expectedException.expect(InvalidJsonDbApiUsageException.class); 131 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 132 | 133 | Site s = new Site(); 134 | s.setId("000012"); 135 | List ss = new ArrayList(); 136 | ss.add(s); 137 | 138 | jsonDBTemplate.remove(ss, "sites"); 139 | } 140 | 141 | /** 142 | * Test to remove a single object from a collection 143 | */ 144 | @Test 145 | public void testRemove_ValidObjectWithClass() { 146 | List instances = jsonDBTemplate.getCollection(Instance.class); 147 | int size = instances.size(); 148 | 149 | Instance instance = new Instance(); 150 | instance.setId("05"); 151 | 152 | Instance removedObject = jsonDBTemplate.remove(instance, Instance.class); 153 | 154 | instances = jsonDBTemplate.getCollection(Instance.class); 155 | assertNotNull(instances); 156 | assertEquals(size-1, instances.size()); 157 | assertNotNull(removedObject); 158 | assertEquals("05", removedObject.getId()); 159 | } 160 | 161 | /** 162 | * Test to remove a single object from a collection 163 | */ 164 | @Test 165 | public void testRemove_ValidObjectWithoutClass() { 166 | List instances = jsonDBTemplate.getCollection(Instance.class); 167 | int size = instances.size(); 168 | 169 | Instance instance = new Instance(); 170 | instance.setId("05"); 171 | 172 | Instance removedObject = jsonDBTemplate.remove(instance); 173 | 174 | instances = jsonDBTemplate.getCollection(Instance.class); 175 | assertNotNull(instances); 176 | assertEquals(size-1, instances.size()); 177 | assertNotNull(removedObject); 178 | assertEquals("05", removedObject.getId()); 179 | } 180 | 181 | /** 182 | * Test to remove a batch of objects from collection 183 | */ 184 | @Test 185 | public void testRemove_BatchOfObjects() { 186 | List instances = jsonDBTemplate.getCollection(Instance.class); 187 | int size = instances.size(); 188 | 189 | List batch = new ArrayList(); 190 | for (int i=1; i<3; i++) { 191 | Instance e = new Instance(); 192 | e.setId(String.format("%02d", i)); 193 | batch.add(e); 194 | } 195 | 196 | List removedObjects = jsonDBTemplate.remove(batch, Instance.class); 197 | 198 | instances = jsonDBTemplate.getCollection(Instance.class); 199 | assertNotNull(instances); 200 | assertEquals(size-2, instances.size()); 201 | assertNotNull(removedObjects); 202 | assertEquals(2, removedObjects.size()); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/SaveTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | 25 | import java.io.File; 26 | import java.util.HashSet; 27 | import java.util.List; 28 | 29 | import org.junit.After; 30 | import org.junit.Before; 31 | import org.junit.Rule; 32 | import org.junit.Test; 33 | import org.junit.rules.ExpectedException; 34 | 35 | import com.google.common.io.Files; 36 | 37 | import io.jsondb.InvalidJsonDbApiUsageException; 38 | import io.jsondb.JsonDBTemplate; 39 | import io.jsondb.Util; 40 | import io.jsondb.crypto.DefaultAESCBCCipher; 41 | import io.jsondb.crypto.ICipher; 42 | import io.jsondb.tests.model.Instance; 43 | import io.jsondb.tests.model.Site; 44 | 45 | /** 46 | * Junit tests for the save() apis 47 | * @version 1.0 08-Oct-2016 48 | */ 49 | public class SaveTests { 50 | private String dbFilesLocation = "src/test/resources/dbfiles/saveTests"; 51 | private File dbFilesFolder = new File(dbFilesLocation); 52 | private File instancesJson = new File(dbFilesFolder, "instances.json"); 53 | 54 | private JsonDBTemplate jsonDBTemplate = null; 55 | 56 | @Rule 57 | public ExpectedException expectedException = ExpectedException.none(); 58 | 59 | @Before 60 | public void setUp() throws Exception { 61 | dbFilesFolder.mkdir(); 62 | Files.copy(new File("src/test/resources/dbfiles/instances.json"), instancesJson); 63 | ICipher cipher = new DefaultAESCBCCipher("1r8+24pibarAWgS85/Heeg=="); 64 | jsonDBTemplate = new JsonDBTemplate(dbFilesLocation, "io.jsondb.tests.model", cipher); 65 | } 66 | 67 | @After 68 | public void tearDown() throws Exception { 69 | Util.delete(dbFilesFolder); 70 | } 71 | 72 | /** 73 | * Test to save a new object into a non-existing collection. 74 | */ 75 | @Test 76 | public void testSave_IntoNonExistingCollection() { 77 | expectedException.expect(InvalidJsonDbApiUsageException.class); 78 | expectedException.expectMessage("Collection by name 'sites' not found. Create collection first"); 79 | jsonDBTemplate.save(new Site(), "sites"); 80 | } 81 | 82 | private class SomeClass {} 83 | 84 | /** 85 | * Test to save a new object of unknown collection type. 86 | */ 87 | @Test 88 | public void testSave_IntoUnknowCollection() { 89 | expectedException.expect(InvalidJsonDbApiUsageException.class); 90 | expectedException.expectMessage("Entity 'SomeClass' is not annotated with annotation @Document"); 91 | jsonDBTemplate.save(new SomeClass(), SomeClass.class); 92 | } 93 | 94 | /** 95 | * Test to save a null object. 96 | */ 97 | @Test 98 | public void testSave_ANullObject() { 99 | expectedException.expect(InvalidJsonDbApiUsageException.class); 100 | expectedException.expectMessage("Null Object cannot be updated into DB"); 101 | jsonDBTemplate.save(null, Instance.class); 102 | } 103 | 104 | /** 105 | * Test to save a Collection object. 106 | */ 107 | @Test 108 | public void testSave_ASingleCollectionObject() { 109 | expectedException.expect(InvalidJsonDbApiUsageException.class); 110 | expectedException.expectMessage("Collection object cannot be inserted, removed, updated or upserted as a single object"); 111 | jsonDBTemplate.save(new HashSet(), Instance.class); 112 | } 113 | 114 | /** 115 | * Test to save a new object that does not exists in the collection 116 | */ 117 | @Test 118 | public void testSave_ANewObject() { 119 | expectedException.expect(InvalidJsonDbApiUsageException.class); 120 | expectedException.expectMessage("Document with Id: '15' not found in Collection by name 'instances' not found. Insert or Upsert the object first."); 121 | 122 | Instance instance = new Instance(); 123 | instance.setId("15"); 124 | instance.setHostname("ec2-54-191-15"); 125 | jsonDBTemplate.save(instance, Instance.class); 126 | } 127 | 128 | /** 129 | * Test to simply save/update a object 130 | */ 131 | @Test 132 | public void testSave_Simple() { 133 | List instances = jsonDBTemplate.getCollection(Instance.class); 134 | int size = instances.size(); 135 | 136 | Instance instance = new Instance(); 137 | instance.setId("01"); 138 | instance.setHostname("ec2-54-191-UPDTed"); 139 | jsonDBTemplate.save(instance, Instance.class); 140 | 141 | Instance instance1 = jsonDBTemplate.findById("01", Instance.class); 142 | assertEquals("ec2-54-191-UPDTed", instance1.getHostname()); 143 | assertEquals(size, instances.size()); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/Instance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import io.jsondb.annotation.Document; 24 | import io.jsondb.annotation.Id; 25 | import io.jsondb.annotation.Secret; 26 | 27 | /** 28 | * A test Pojo representing a AWS Instance. 29 | * @version 1.0 28-Sep-2016 30 | */ 31 | @Document(collection = "instances", schemaVersion= "1.0") 32 | public class Instance { 33 | @Id 34 | private String id; 35 | private String hostname; 36 | 37 | @Secret 38 | private String privateKey; 39 | private String publicKey; 40 | 41 | public String getId() { 42 | return id; 43 | } 44 | public void setId(String id) { 45 | this.id = id; 46 | } 47 | public String getHostname() { 48 | return hostname; 49 | } 50 | public void setHostname(String hostname) { 51 | this.hostname = hostname; 52 | } 53 | public String getPrivateKey() { 54 | return privateKey; 55 | } 56 | public void setPrivateKey(String privateKey) { 57 | this.privateKey = privateKey; 58 | } 59 | public String getPublicKey() { 60 | return publicKey; 61 | } 62 | public void setPublicKey(String publicKey) { 63 | this.publicKey = publicKey; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/LoadBalancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import io.jsondb.annotation.Document; 24 | import io.jsondb.annotation.Id; 25 | 26 | /** 27 | * @version 1.0 25-Oct-2016 28 | */ 29 | @Document(collection = "loadbalancer", schemaVersion= "1.0") 30 | public class LoadBalancer { 31 | @Id 32 | private String id; 33 | private String hostname; 34 | private String username; 35 | 36 | //New Field 37 | private String osName; 38 | 39 | //Just mentioned here so that is known that such a thing can happen 40 | //private int deletedField; 41 | 42 | public String getId() { 43 | return id; 44 | } 45 | public void setId(String id) { 46 | this.id = id; 47 | } 48 | public String getHostname() { 49 | return hostname; 50 | } 51 | public void setHostname(String hostname) { 52 | this.hostname = hostname; 53 | } 54 | public String getUsername() { 55 | return username; 56 | } 57 | public void setUsername(String username) { 58 | this.username = username; 59 | } 60 | public String getOsName() { 61 | return osName; 62 | } 63 | public void setOsName(String osName) { 64 | this.osName = osName; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/PojoForPrivateGetIdTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import io.jsondb.annotation.Document; 24 | import io.jsondb.annotation.Id; 25 | 26 | /** 27 | * @version 1.0 29-Oct-2016 28 | */ 29 | @Document(collection = "pojoforprivategetidtest", schemaVersion= "1.0") 30 | public class PojoForPrivateGetIdTest { 31 | @Id 32 | private String id; 33 | 34 | public PojoForPrivateGetIdTest() { 35 | super(); 36 | } 37 | 38 | public PojoForPrivateGetIdTest(String id) { 39 | super(); 40 | this.id = id; 41 | } 42 | 43 | @SuppressWarnings("unused") 44 | private String getId() { 45 | return id; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/PojoForPrivateSetIdTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import io.jsondb.annotation.Document; 24 | import io.jsondb.annotation.Id; 25 | 26 | /** 27 | * @version 1.0 29-Oct-2016 28 | */ 29 | @Document(collection = "pojoforprivatesetidtest", schemaVersion= "1.0") 30 | public class PojoForPrivateSetIdTest { 31 | @Id 32 | private String id; 33 | 34 | public String getId() { 35 | return id; 36 | } 37 | 38 | @SuppressWarnings("unused") 39 | private void setId(String id) { 40 | this.id = id; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/PojoWithEnumFields.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import io.jsondb.annotation.Document; 24 | import io.jsondb.annotation.Id; 25 | 26 | /** 27 | * A test POJO to represent a PojoWithEnumFields 28 | * Used to test that JsonDB can handle POJOs which have Enum fields. 29 | * 30 | * @author Farooq Khan 31 | * @version 1.0 06-Oct-2016 32 | */ 33 | @Document(collection = "pojowithenumfields", schemaVersion= "1.0") 34 | public class PojoWithEnumFields { 35 | public enum Status { 36 | CREATED, COMPLETED, CONSUMED, UPDATED 37 | } 38 | 39 | @Id 40 | private String id; 41 | private Status status; 42 | 43 | public String getId() { 44 | return id; 45 | } 46 | public void setId(String id) { 47 | this.id = id; 48 | } 49 | public Status getStatus() { 50 | return status; 51 | } 52 | public void setStatus(Status status) { 53 | this.status = status; 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/PojoWithList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import java.util.List; 24 | import java.util.UUID; 25 | 26 | import io.jsondb.annotation.Document; 27 | import io.jsondb.annotation.Id; 28 | 29 | /** 30 | * @version 1.0 10-Dec-2017 31 | */ 32 | @Document(collection = "pojowithlist", schemaVersion = "1.0") 33 | public class PojoWithList { 34 | @Id 35 | private String id; 36 | 37 | private List stuff; 38 | 39 | public PojoWithList() { 40 | this.id = UUID.randomUUID().toString(); 41 | } 42 | 43 | public String getId() { 44 | return id; 45 | } 46 | public void setId(String id) { 47 | this.id = id; 48 | } 49 | 50 | public List getStuff() { 51 | return stuff; 52 | } 53 | public void setStuff(List stuff) { 54 | this.stuff = stuff; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/SecureVolume.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import io.jsondb.annotation.Document; 24 | import io.jsondb.annotation.Id; 25 | import io.jsondb.annotation.Secret; 26 | 27 | /** 28 | * A test Pojo representing a AWS EC3 Secure Volume 29 | * @version 1.0 06-Oct-2016 30 | */ 31 | @Document(collection = "securevolumes", schemaVersion= "1.0") 32 | public class SecureVolume { 33 | @Id 34 | private String id; 35 | private String name; 36 | @Secret 37 | private long encryptionKey; 38 | 39 | public String getId() { 40 | return id; 41 | } 42 | public void setId(String id) { 43 | this.id = id; 44 | } 45 | public String getName() { 46 | return name; 47 | } 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | public long getEncryptionKey() { 52 | return encryptionKey; 53 | } 54 | public void setEncryptionKey(long encryptionKey) { 55 | this.encryptionKey = encryptionKey; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/Site.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import io.jsondb.annotation.Document; 24 | import io.jsondb.annotation.Id; 25 | 26 | /** 27 | * A test Pojo representing a AWS Site. 28 | * Used to test JsonDB - createCollection() and dropCollection() operations 29 | * @version 1.0 06-Oct-2016 30 | */ 31 | @Document(collection = "sites", schemaVersion= "1.0") 32 | public class Site { 33 | @Id 34 | private String id; 35 | private String location; 36 | public String getId() { 37 | return id; 38 | } 39 | public void setId(String id) { 40 | this.id = id; 41 | } 42 | public String getLocation() { 43 | return location; 44 | } 45 | public void setLocation(String location) { 46 | this.location = location; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/model/Volume.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.model; 22 | 23 | import io.jsondb.annotation.Document; 24 | import io.jsondb.annotation.Id; 25 | 26 | /** 27 | * A test Pojo representing a AWS EC3 Volume 28 | * @version 1.0 06-Oct-2016 29 | */ 30 | @Document(collection = "volumes", schemaVersion= "1.0") 31 | public class Volume { 32 | @Id 33 | private String id; 34 | private String name; 35 | private long size; 36 | public boolean flash; 37 | 38 | public String getId() { 39 | return id; 40 | } 41 | public void setId(String id) { 42 | this.id = id; 43 | } 44 | public String getName() { 45 | return name; 46 | } 47 | public void setName(String name) { 48 | this.name = name; 49 | } 50 | public long getSize() { 51 | return size; 52 | } 53 | public void setSize(long size) { 54 | this.size = size; 55 | } 56 | public boolean isFlash() { 57 | return flash; 58 | } 59 | public void setFlash(boolean flash) { 60 | this.flash = flash; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/io/jsondb/tests/util/TestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 - 2018 Farooq Khan 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | package io.jsondb.tests.util; 22 | 23 | import java.io.BufferedReader; 24 | import java.io.File; 25 | import java.io.FileNotFoundException; 26 | import java.io.FileReader; 27 | import java.io.FileWriter; 28 | import java.io.IOException; 29 | import java.util.LinkedList; 30 | import java.util.Scanner; 31 | 32 | import org.hamcrest.MatcherAssert; 33 | import org.hamcrest.collection.IsIterableContainingInOrder; 34 | 35 | /** 36 | * @author Farooq Khan 37 | * @version 1.0 06-Oct-2016 38 | */ 39 | public class TestUtils { 40 | public static void checkLastLines(File jsonFile, String[] expectedLinesAtEnd) { 41 | CircularQueue queue = new CircularQueue(expectedLinesAtEnd.length); 42 | 43 | Scanner sc = null; 44 | try { 45 | sc = new Scanner(jsonFile, "UTF-8"); 46 | while (sc.hasNextLine()) { 47 | queue.add(sc.nextLine()); 48 | } 49 | } catch (FileNotFoundException e) { 50 | e.printStackTrace(); 51 | } finally { 52 | if (null != sc) { 53 | sc.close(); 54 | } 55 | } 56 | MatcherAssert.assertThat(queue, IsIterableContainingInOrder.contains(expectedLinesAtEnd)); 57 | } 58 | 59 | public static boolean appendDirectToFile(File file, String data) { 60 | boolean retval = false; 61 | FileWriter fw = null; 62 | try { 63 | fw = new FileWriter(file, true); 64 | fw.write(data); 65 | fw.write("\n"); 66 | retval = true; 67 | } catch (IOException e) { 68 | retval = false; 69 | e.printStackTrace(); 70 | } finally { 71 | if (null != fw) { 72 | try { 73 | fw.close(); 74 | } catch (IOException e) { 75 | System.out.println(e); 76 | } 77 | } 78 | } 79 | return retval; 80 | } 81 | 82 | public static int getNoOfLinesInFile(File file) { 83 | int lines = 0; 84 | FileReader f = null; 85 | BufferedReader reader = null; 86 | try { 87 | f = new FileReader(file); 88 | reader = new BufferedReader(f); 89 | while (reader.readLine() != null) { 90 | lines++; 91 | } 92 | } catch (FileNotFoundException e) { 93 | e.printStackTrace(); 94 | } catch (IOException e) { 95 | e.printStackTrace(); 96 | } finally { 97 | if (null != reader) { 98 | try { 99 | reader.close(); 100 | } catch (IOException e) { 101 | e.printStackTrace(); 102 | } 103 | } 104 | if (null != f) { 105 | try { 106 | f.close(); 107 | } catch (IOException e) { 108 | e.printStackTrace(); 109 | } 110 | } 111 | } 112 | return lines; 113 | } 114 | 115 | @SuppressWarnings("serial") 116 | public static class CircularQueue extends LinkedList { 117 | private int limit; 118 | 119 | public CircularQueue(int limit) { 120 | this.limit = limit; 121 | } 122 | 123 | @Override 124 | public boolean add(E o) { 125 | super.add(o); 126 | while (size() > limit) { super.remove(); } 127 | return true; 128 | } 129 | } 130 | 131 | public static boolean isMac() { 132 | String OS = System.getProperty("os.name").toLowerCase(); 133 | return (OS.indexOf("mac") >= 0); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/test/resources/dbfiles/instances.json: -------------------------------------------------------------------------------- 1 | {"schemaVersion":"1.0"} 2 | {"id":"01","hostname":"ec2-54-191-01","privateKey":"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop","publicKey":"d3aa045f71bf4d1dffd2c5f485a4bc1d"} 3 | {"id":"02","hostname":"ec2-54-191-05","privateKey":"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop","publicKey":"d3aa045f71bf4d1dffd2c5f485a4bc1d"} 4 | {"id":"03","hostname":"ec2-54-191-04","privateKey":"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop","publicKey":"d3aa045f71bf4d1dffd2c5f485a4bc1d"} 5 | {"id":"04","hostname":"ec2-54-191-03","privateKey":"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop","publicKey":"d3aa045f71bf4d1dffd2c5f485a4bc1d"} 6 | {"id":"05","hostname":"ec2-54-191-02","privateKey":"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop","publicKey":"d3aa045f71bf4d1dffd2c5f485a4bc1d"} 7 | {"id":"06","hostname":"ec2-54-191-06","privateKey":"Zf9vl5K6WV6BA3eL7JbnrfPMjfJxc9Rkoo0zlROQlgTslmcp9iFzos+MP93GZqop","publicKey":""} 8 | -------------------------------------------------------------------------------- /src/test/resources/dbfiles/loadbalancer.json: -------------------------------------------------------------------------------- 1 | {"schemaVersion":"0.5"} 2 | {"id":"001","hostname":"eclb-54-01","username":"admin","deletedField":"yes"} 3 | {"id":"002","hostname":"eclb-54-02","username":"admin","deletedField":"yes"} 4 | {"id":"003","hostname":"eclb-54-03","username":"admin","deletedField":"yes"} 5 | {"id":"004","hostname":"eclb-54-04","username":"admin","deletedField":"yes"} 6 | {"id":"005","hostname":"eclb-54-05","username":"admin","deletedField":"yes"} 7 | {"id":"006","hostname":"eclb-54-06","username":"admin","deletedField":"yes"} 8 | {"id":"007","hostname":"eclb-54-07","username":"admin","deletedField":"yes"} 9 | {"id":"008","hostname":"eclb-54-08","username":"admin","deletedField":"yes"} 10 | {"id":"009","hostname":"eclb-54-09","username":"admin","deletedField":"yes"} 11 | {"id":"010","hostname":"eclb-54-10","username":"admin","deletedField":"yes"} -------------------------------------------------------------------------------- /src/test/resources/dbfiles/pojowithenumfields.json: -------------------------------------------------------------------------------- 1 | {"schemaVersion":"1.0"} 2 | {"id":"0001","status":"CREATED"} 3 | {"id":"0002","status":"COMPLETED"} 4 | {"id":"0003","status":"CONSUMED"} 5 | {"id":"0004","status":"UPDATED"} --------------------------------------------------------------------------------