├── .ci ├── release.sh └── secring.gpg.enc ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle ├── gradle ├── HEADER ├── code-quality.gradle ├── mavenPublish.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main └── java │ ├── com │ └── gluonhq │ │ ├── connect │ │ ├── ConnectState.java │ │ ├── ConnectStateEvent.java │ │ ├── GluonObservable.java │ │ ├── GluonObservableList.java │ │ ├── GluonObservableObject.java │ │ ├── MultiValuedMap.java │ │ ├── converter │ │ │ ├── InputConverter.java │ │ │ ├── InputStreamInputConverter.java │ │ │ ├── InputStreamIterableInputConverter.java │ │ │ ├── IterableInputConverter.java │ │ │ ├── JsonConverter.java │ │ │ ├── JsonInputConverter.java │ │ │ ├── JsonIterableInputConverter.java │ │ │ ├── JsonOutputConverter.java │ │ │ ├── OutputConverter.java │ │ │ ├── OutputStreamOutputConverter.java │ │ │ ├── StringInputConverter.java │ │ │ ├── StringOutputConverter.java │ │ │ ├── VoidInputConverter.java │ │ │ ├── VoidOutputConverter.java │ │ │ ├── XmlInputConverter.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── provider │ │ │ ├── BaseRestProvider.java │ │ │ ├── DataProvider.java │ │ │ ├── FileClient.java │ │ │ ├── InputStreamListDataReader.java │ │ │ ├── InputStreamObjectDataReader.java │ │ │ ├── ListDataReader.java │ │ │ ├── ObjectDataReader.java │ │ │ ├── ObjectDataRemover.java │ │ │ ├── ObjectDataWriter.java │ │ │ ├── OutputStreamObjectDataWriter.java │ │ │ ├── RestClient.java │ │ │ ├── RestListDataReader.java │ │ │ ├── RestObjectDataReader.java │ │ │ ├── RestObjectDataWriterAndRemover.java │ │ │ └── package-info.java │ │ └── source │ │ │ ├── BasicInputDataSource.java │ │ │ ├── BasicOutputDataSource.java │ │ │ ├── FileDataSource.java │ │ │ ├── IODataSource.java │ │ │ ├── InputDataSource.java │ │ │ ├── OutputDataSource.java │ │ │ ├── RestDataSource.java │ │ │ └── package-info.java │ │ └── impl │ │ └── connect │ │ ├── EventHelper.java │ │ ├── OAuth.java │ │ ├── converter │ │ ├── ClassInspector.java │ │ └── JsonUtil.java │ │ └── event │ │ ├── ConnectEventDispatcher.java │ │ └── ConnectEventHandler.java │ └── module-info.java └── test └── java └── com └── gluonhq └── connect ├── HttpServerManager.java ├── converter ├── JsonConverterMathBigTest.java ├── JsonConverterTest.java └── StringInputConverterTest.java ├── provider └── RestClientContentTypeTest.java └── source └── RestDataSourceTest.java /.ci/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Exit immediately if any command in the script fails 4 | set -e 5 | 6 | # Configure GIT 7 | git config --global user.email "githubbot@gluonhq.com" 8 | git config --global user.name "Gluon Bot" 9 | 10 | # Decrypt encrypted files 11 | openssl aes-256-cbc -K $encrypted_dc87922a4c8c_key -iv $encrypted_dc87922a4c8c_iv -in .ci/secring.gpg.enc -out secring.gpg -d 12 | if [[ ! -s secring.gpg ]] 13 | then echo "Decryption failed." 14 | exit 1 15 | fi 16 | 17 | # Generate and upload jars 18 | ./gradlew publish closeAndReleaseRepository -i -PsonatypeUsername=$SONATYPE_USERNAME -PsonatypePassword=$SONATYPE_PASSWORD -Psigning.keyId=$GPG_KEYNAME -Psigning.password=$GPG_PASSPHRASE -Psigning.secretKeyRingFile=$TRAVIS_BUILD_DIR/secring.gpg 19 | 20 | # Upload to S3 21 | touch ~/.s3cfg 22 | s3cmd --no-mime-magic --guess-mime-type --access_key "$AWS_ACCESS_KEY" --secret_key "$AWS_SECRET_KEY" put -P --recursive build/docs/javadoc/ s3://docs.gluonhq.com/connect/javadoc/$TRAVIS_TAG/ 23 | 24 | # Get index.html 25 | s3cmd --access_key "$AWS_ACCESS_KEY" --secret_key "$AWS_SECRET_KEY" get s3://docs.gluonhq.com/connect/javadoc/index.html 26 | # Replace current version with new released version 27 | sed -i "s,url=.*\",url=/connect/javadoc/$TRAVIS_TAG\",g" index.html 28 | # Update index.html to latest release version 29 | s3cmd --no-mime-magic --guess-mime-type --access_key "$AWS_ACCESS_KEY" --secret_key "$AWS_SECRET_KEY" put -P index.html s3://docs.gluonhq.com/connect/javadoc/ 30 | 31 | # Update version by 1 32 | newVersion=${TRAVIS_TAG%.*}.$((${TRAVIS_TAG##*.} + 1)) 33 | # Replace first occurrence of 34 | # version = 'TRAVIS_TAG' 35 | # with 36 | # version = 'newVersion-SNAPSHOT' 37 | sed -i "0,/^version = '$TRAVIS_TAG'/s//version = '$newVersion-SNAPSHOT'/" build.gradle 38 | 39 | git commit build.gradle -m "Upgrade version to $newVersion-SNAPSHOT" 40 | git push https://gluon-bot:$GITHUB_PASSWORD@github.com/gluonhq/connect HEAD:master -------------------------------------------------------------------------------- /.ci/secring.gpg.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluonhq/connect/88a6d8baa41a2fb8a0433177646d6a8d6ac470a2/.ci/secring.gpg.enc -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle 2 | .gradle/ 3 | build/ 4 | 5 | # IntelliJ IDEA 6 | .idea/ 7 | out/ 8 | 9 | # Netbeans 10 | .nb-gradle/ 11 | .nb-gradle-properties 12 | 13 | # Eclipse 14 | .settings/ 15 | bin/ 16 | 17 | # MacOS 18 | .DS_Store 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # use java support 2 | language: java 3 | jdk: 4 | - openjdk11 5 | 6 | # run in container 7 | sudo: false 8 | 9 | # use linux as operating system 10 | os: 11 | - linux 12 | 13 | addons: 14 | apt: 15 | packages: 16 | - s3cmd 17 | 18 | # run maven build 19 | script: 20 | - ./gradlew clean build 21 | 22 | cache: 23 | directories: 24 | - $HOME/.gradle/caches/ 25 | 26 | # Deploy snapshots on every commit made to master branch 27 | # Deploy releases on every tag push 28 | deploy: 29 | - provider: script 30 | script: ./gradlew publish -PsonatypeUsername=$SONATYPE_USERNAME -PsonatypePassword=$SONATYPE_PASSWORD 31 | skip_cleanup: true 32 | on: 33 | branch: master 34 | 35 | - provider: script 36 | script: bash .ci/release.sh 37 | skip_cleanup: true 38 | on: 39 | tags: true 40 | 41 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [2.0.0-SNAPSHOT] 4 | 5 | ### Additions 6 | 7 | - Modularize project with support for Java 11 and JavaFX 11 8 | 9 | ### Changes 10 | 11 | - Moved `BaseRestProvider`, `RestListDataReader`, `RestObjectDataReader`, `RestObjectDataWriterAndRemover` to public API -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Gluon 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of Gluon, any associated website, nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gluon Connect 2 | 3 | ## Introduction 4 | 5 | Gluon Connect is a client-side library that simplifies binding your data from any source and format to your 6 | JavaFX UI controls. It works by retrieving data from a data source and converting that data from a specific format 7 | into JavaFX observable lists and observable objects that can be used directly in JavaFX UI controls. It is designed to 8 | allow developers to easily add support for custom data sources and data formats. 9 | 10 | * Reference Documentation: http://docs.gluonhq.com/connect 11 | * JavaDoc: http://docs.gluonhq.com/connect/javadoc 12 | 13 | ## Dependency 14 | 15 | ### Together with Gluon Mobile 16 | 17 | A dependency to Gluon Connect is automatically added when using the [Gluon Mobile](http://gluonhq.com/products/mobile/) dependency. 18 | You also need to configure the four required Charm Down plugins that are used in Gluon Mobile. 19 | 20 | dependencies { 21 | compile 'com.gluonhq:charm:4.3.2' 22 | } 23 | 24 | jfxmobile { 25 | downConfig { 26 | version '3.2.4' 27 | plugins 'display', 'lifecycle', 'statusbar', 'storage' 28 | } 29 | } 30 | 31 | ### Standalone 32 | 33 | You can also use the library as a standalone dependency. You only need to define the following dependency: 34 | 35 | ##### Gradle 36 | 37 | dependencies { 38 | compile 'com.gluonhq:connect:1.4.3' 39 | } 40 | 41 | ##### Maven 42 | 43 | 44 | com.gluonhq 45 | connect 46 | 1.4.3 47 | 48 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "java-library" 3 | id 'signing' 4 | id "com.github.hierynomus.license" version "0.15.0" 5 | id "org.openjfx.javafxplugin" version "0.0.9" 6 | id 'io.codearte.nexus-staging' version '0.22.0' 7 | id 'de.marcphilipp.nexus-publish' version '0.4.0' 8 | } 9 | 10 | apply from: rootProject.file('gradle/mavenPublish.gradle') 11 | apply from: rootProject.file('gradle/code-quality.gradle') 12 | 13 | sourceCompatibility = 11 14 | targetCompatibility = 11 15 | 16 | group = 'com.gluonhq' 17 | version = '2.0.2-SNAPSHOT' 18 | 19 | repositories { 20 | jcenter() 21 | } 22 | 23 | dependencies { 24 | api 'jakarta.json:jakarta.json-api:1.1.5' 25 | implementation 'javax.xml.bind:jaxb-api:2.3.1' 26 | 27 | testImplementation 'io.vertx:vertx-core:3.6.0' 28 | testImplementation 'org.testng:testng:6.9.10' 29 | testRuntimeOnly 'org.glassfish:jakarta.json:1.1.5:module' 30 | } 31 | 32 | compileJava { 33 | options.compilerArgs += [ 34 | '--add-exports', 35 | 'javafx.base/com.sun.javafx.event=com.gluonhq.connect' 36 | ] 37 | } 38 | 39 | javafx { 40 | version '15' 41 | modules 'javafx.graphics' 42 | } 43 | 44 | test { 45 | useTestNG() 46 | } 47 | 48 | javadoc { 49 | exclude("com/gluonhq/impl/**/*") 50 | options.addStringOption("-source-path", "src/main/java") 51 | options.addBooleanOption("javafx").setValue(true) 52 | options.links("https://openjfx.io/javadoc/" + "${javafx.version}".substring(0,2)) 53 | options.links("https://docs.oracle.com/en/java/javase/" + JavaVersion.current().majorVersion + "/docs/api") 54 | } 55 | -------------------------------------------------------------------------------- /gradle/HEADER: -------------------------------------------------------------------------------- 1 | Copyright (c) ${year} ${author} 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of ${author}, any associated website, nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /gradle/code-quality.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.github.hierynomus.license' 2 | 3 | license { 4 | header = rootProject.file('gradle/HEADER') 5 | strictCheck = true 6 | skipExistingHeaders = true 7 | ignoreFailures = false 8 | mapping { 9 | java = 'SLASHSTAR_STYLE' 10 | fxml = 'XML_STYLE' 11 | } 12 | ext.year = Calendar.getInstance().get(Calendar.YEAR) 13 | ext.author = 'Gluon' 14 | } -------------------------------------------------------------------------------- /gradle/mavenPublish.gradle: -------------------------------------------------------------------------------- 1 | import java.time.Duration 2 | 3 | task sourcesJar(type: Jar) { 4 | from sourceSets.main.allJava 5 | archiveClassifier.set('sources') 6 | } 7 | 8 | task javadocJar(type: Jar, dependsOn: javadoc) { 9 | from javadoc.destinationDir 10 | archiveClassifier.set('javadoc') 11 | } 12 | 13 | publishing { 14 | publications { 15 | maven(MavenPublication) { 16 | from components.java 17 | artifact sourcesJar 18 | artifact javadocJar 19 | 20 | pom { 21 | name = 'Gluon Connect' 22 | description = "Gluon Connect" 23 | url = 'https://gluonhq.com/products/mobile/connect/' 24 | 25 | developers { 26 | developer { 27 | name = 'Joeri Sykora' 28 | email = 'joeri.sykora@gluonhq.com' 29 | organization = 'Gluon' 30 | organizationUrl = 'https://gluonhq.com' 31 | } 32 | } 33 | 34 | licenses { 35 | license { 36 | name = 'The 3-Clause BSD License' 37 | url = 'http://www.opensource.org/licenses/bsd-license.php' 38 | distribution = 'repo' 39 | } 40 | } 41 | 42 | scm { 43 | connection = 'scm:git:https://github.com/gluonhq/connect.git' 44 | developerConnection = 'scm:git:ssh://git@github.com/gluonhq/connect.git' 45 | url = 'https://github.com/gluonhq/connect' 46 | } 47 | } 48 | 49 | pom.withXml { 50 | Node pomNode = asNode() 51 | pomNode.dependencies.'*'.findAll() { 52 | it.groupId.text() == 'org.openjfx' 53 | }.each { 54 | it.parent().remove(it) 55 | } 56 | } 57 | } 58 | } 59 | } 60 | 61 | signing { 62 | sign publishing.publications.maven 63 | required = { gradle.taskGraph.hasTask(publish) && !version.endsWith("SNAPSHOT") } 64 | } 65 | 66 | nexusPublishing { 67 | repositories { 68 | sonatype() 69 | } 70 | // credentials are shared from staging plugin 71 | clientTimeout = Duration.ofMinutes(5) 72 | connectTimeout = Duration.ofMinutes(5) 73 | } 74 | 75 | nexusStaging { 76 | username = project.hasProperty('sonatypeUsername') ? project.property('sonatypeUsername') : '' 77 | password = project.hasProperty('sonatypePassword') ? project.property('sonatypePassword') : '' 78 | numberOfRetries = 30 79 | delayBetweenRetriesInMillis = 5000 80 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluonhq/connect/88a6d8baa41a2fb8a0433177646d6a8d6ac470a2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu May 19 20:53:14 CEST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'connect' 2 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/ConnectState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect; 28 | 29 | import com.gluonhq.connect.provider.DataProvider; 30 | import com.gluonhq.connect.provider.ObjectDataRemover; 31 | 32 | /** 33 | * The possible states a {@link GluonObservable} can be in while a {@link DataProvider} operation is in progress. All 34 | * observables begin in the READY state. When the operation is started, the observable will enter the 35 | * RUNNING state. Finally, depending on the operation outcome, the observable will always enter one of the 36 | * following states: SUCCEEDED, FAILED, REMOVED or CANCELLED. When 37 | * an exception was thrown during the operation, it will enter the FAILED state. When the observable is a 38 | * {@link GluonObservableObject} and it is passed in as a parameter to the {@link DataProvider#removeObject(GluonObservableObject, ObjectDataRemover) remove method}, 39 | * then the object will enter the REMOVED state when the remove operation succeeded successfully. When the 40 | * operation was cancelled, the state of the observable will be changed to CANCELLED. Signaling the 41 | * cancellation of an operation is done by throwing a {@link java.util.concurrent.CancellationException}. In all other 42 | * cases, the state will become SUCCEEDED. 43 | */ 44 | public enum ConnectState { 45 | /** 46 | * This is the initial state of a new GluonObservable object. It will remain 47 | * in the READY state until the first synchronization operation is started. 48 | */ 49 | READY, 50 | /** 51 | * A GluonObservable object in the RUNNING state means that a 52 | * synchronization operation is currently in progress. 53 | */ 54 | RUNNING, 55 | /** 56 | * A GluonObservable object in the FAILED state signals that the last 57 | * executed synchronization operation failed. You can check the {@link GluonObservable#getException() exception} 58 | * to find out more about the reason of the failure. 59 | */ 60 | FAILED, 61 | /** 62 | * A GluonObservable object in the SUCCEEDED state signals that the last 63 | * executed synchronization operation completed successfully. 64 | */ 65 | SUCCEEDED, 66 | /** 67 | * A GluonObservable object in the CANCELLED state signals that the last 68 | * executed synchronization operation was cancelled. Cancellation is most likely caused 69 | * by a user that cancels an action that is required to proceed with the operation. For 70 | * example, when an operation requires an authenticated user, that operation is cancelled 71 | * when the user aborts the authentication process. 72 | */ 73 | CANCELLED, 74 | /** 75 | * A GluonObservable object in the REMOVED state signals that it is 76 | * successfully removed after executing the {@link DataProvider#removeObject(GluonObservableObject, ObjectDataRemover)} remove operation}. 77 | * The REMOVED state is only applicable to {@link GluonObservableObject} because 78 | * a {@link GluonObservableList} can not be removed. 79 | */ 80 | REMOVED 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/ConnectStateEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect; 28 | 29 | import javafx.beans.NamedArg; 30 | import javafx.event.Event; 31 | import javafx.event.EventType; 32 | 33 | public class ConnectStateEvent extends Event { 34 | 35 | /** 36 | * Common supertype for all worker state event types. 37 | */ 38 | public static final EventType ANY = 39 | new EventType<>(Event.ANY, "CONNECT_STATE"); 40 | 41 | /** 42 | * This event occurs when the state of a GluonObservable implementation has 43 | * transitioned to the READY state. 44 | */ 45 | public static final EventType CONNECT_STATE_READY = 46 | new EventType<>(ConnectStateEvent.ANY, "CONNECT_STATE_READY"); 47 | 48 | /** 49 | * This event occurs when the state of a GluonObservable implementation has 50 | * transitioned to the RUNNING state. 51 | */ 52 | public static final EventType CONNECT_STATE_RUNNING = 53 | new EventType<>(ConnectStateEvent.ANY, "CONNECT_STATE_RUNNING"); 54 | 55 | /** 56 | * This event occurs when the state of a GluonObservable implementation has 57 | * transitioned to the FAILED state. 58 | */ 59 | public static final EventType CONNECT_STATE_FAILED = 60 | new EventType<>(ConnectStateEvent.ANY, "CONNECT_STATE_FAILED"); 61 | 62 | /** 63 | * This event occurs when the state of a GluonObservable implementation has 64 | * transitioned to the SUCCEEDED state. 65 | */ 66 | public static final EventType CONNECT_STATE_SUCCEEDED = 67 | new EventType<>(ConnectStateEvent.ANY, "CONNECT_STATE_SUCCEEDED"); 68 | 69 | /** 70 | * This event occurs when the state of a GluonObservable implementation has 71 | * transitioned to the CANCELLED state. 72 | */ 73 | public static final EventType CONNECT_STATE_CANCELLED = 74 | new EventType<>(ConnectStateEvent.ANY, "CONNECT_STATE_CANCELLED"); 75 | 76 | /** 77 | * This event occurs when the state of a GluonObservable implementation has 78 | * transitioned to the REMOVED state. 79 | */ 80 | public static final EventType CONNECT_STATE_REMOVED = 81 | new EventType<>(ConnectStateEvent.ANY, "CONNECT_STATE_REMOVED"); 82 | 83 | /** 84 | * Create a new ConnectStateEvent. Specify the gluon observable and the event type. 85 | * 86 | * @param gluonObservable The GluonObservable which is firing the event. The 87 | * GluonObservable really should be an EventTarget, otherwise the 88 | * EventTarget for the event will be null. 89 | * @param eventType The type of event. This should not be null. 90 | */ 91 | public ConnectStateEvent(@NamedArg("gluonObservable") GluonObservable gluonObservable, @NamedArg("eventType") EventType eventType) { 92 | super(gluonObservable, gluonObservable, eventType); 93 | } 94 | 95 | @Override 96 | public GluonObservable getSource() { 97 | return (GluonObservable) super.getSource(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/GluonObservable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect; 28 | 29 | import javafx.beans.property.ReadOnlyBooleanProperty; 30 | import javafx.beans.property.ReadOnlyObjectProperty; 31 | import javafx.event.EventHandler; 32 | import javafx.event.EventTarget; 33 | 34 | /** 35 | * This is the common interface for both GluonObservableObject and GluonObservableList. All operations on the 36 | * {@link com.gluonhq.connect.provider.DataProvider} class happen in an asynchronous background thread. This interface 37 | * can therefor be used to get information about the current state of the observable entity while the operation is 38 | * running as well as the final state of the entity when the operation has completed. 39 | */ 40 | public interface GluonObservable extends EventTarget { 41 | 42 | /** 43 | * Return the initialized state of this observable. 44 | * 45 | * @return true when the observable is initialized; false otherwise. 46 | */ 47 | boolean isInitialized(); 48 | 49 | /** 50 | * A boolean property that is true when the observable has been initialized successfully after its initial 51 | * retrieval. 52 | * 53 | * @return true when the observable is initialized; false otherwise. 54 | */ 55 | ReadOnlyBooleanProperty initializedProperty(); 56 | 57 | /** 58 | * Return the current state of this observable. 59 | * 60 | * @return the current state 61 | */ 62 | ConnectState getState(); 63 | 64 | /** 65 | * Holds the current state of this observable. This property can be used to listen 66 | * for changes in the synchronization process. 67 | * 68 | * @return the current state 69 | */ 70 | ReadOnlyObjectProperty stateProperty(); 71 | 72 | /** 73 | * In case an exception occurred during processing, this method will 74 | * return the exception. Otherwise, null will be returned. 75 | * 76 | * @return the exception, if one has occurred; otherwise null. 77 | */ 78 | Throwable getException(); 79 | 80 | /** 81 | * Holds the exception that was thrown when a synchronization operation failed. 82 | * 83 | * @return the exception, if one has occurred; otherwise null. 84 | */ 85 | ReadOnlyObjectProperty exceptionProperty(); 86 | 87 | /** 88 | * The onReady event handler is called whenever the GluonObservable state 89 | * transitions to the READY state. 90 | * 91 | * @param value the event handler, can be null to clear it 92 | */ 93 | void setOnReady(EventHandler value); 94 | 95 | /** 96 | * The onRunning event handler is called whenever the GluonObservable state 97 | * transitions to the RUNNING state. 98 | * 99 | * @param value the event handler, can be null to clear it 100 | */ 101 | void setOnRunning(EventHandler value); 102 | 103 | /** 104 | * The onFailed event handler is called whenever the GluonObservable state 105 | * transitions to the FAILED state. 106 | * 107 | * @param value the event handler, can be null to clear it 108 | */ 109 | void setOnFailed(EventHandler value); 110 | 111 | /** 112 | * The onSucceeded event handler is called whenever the GluonObservable state 113 | * transitions to the SUCCEEDED state. 114 | * 115 | * @param value the event handler, can be null to clear it 116 | */ 117 | void setOnSucceeded(EventHandler value); 118 | 119 | /** 120 | * The onCancelled event handler is called whenever the GluonObservable state 121 | * transitions to the CANCELLED state. 122 | * 123 | * @param value the event handler, can be null to clear it 124 | */ 125 | void setOnCancelled(EventHandler value); 126 | 127 | /** 128 | * The onRemoved event handler is called whenever the GluonObservable state 129 | * transitions to the REMOVED state. 130 | * 131 | * @param value the event handler, can be null to clear it 132 | */ 133 | void setOnRemoved(EventHandler value); 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/GluonObservableObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect; 28 | 29 | import com.gluonhq.connect.provider.DataProvider; 30 | import com.gluonhq.connect.provider.ObjectDataReader; 31 | import com.gluonhq.impl.connect.EventHelper; 32 | import javafx.beans.property.BooleanProperty; 33 | import javafx.beans.property.ObjectProperty; 34 | import javafx.beans.property.ReadOnlyBooleanProperty; 35 | import javafx.beans.property.ReadOnlyObjectProperty; 36 | import javafx.beans.property.SimpleBooleanProperty; 37 | import javafx.beans.property.SimpleObjectProperty; 38 | import javafx.beans.value.WritableObjectValue; 39 | import javafx.event.EventDispatchChain; 40 | import javafx.event.EventHandler; 41 | 42 | import static com.gluonhq.connect.ConnectState.CANCELLED; 43 | import static com.gluonhq.connect.ConnectState.READY; 44 | import static com.gluonhq.connect.ConnectStateEvent.*; 45 | 46 | /** 47 | * A GluonObservableObject is an ObservableObject that is linked with a data source. 48 | * 49 | * @param the type of the object that is held in this observable 50 | * @see DataProvider#retrieveObject(ObjectDataReader) 51 | */ 52 | public class GluonObservableObject extends SimpleObjectProperty implements GluonObservable, WritableObjectValue { 53 | 54 | private final BooleanProperty initialized = new SimpleBooleanProperty(this, "initialized", false); 55 | private final ObjectProperty state = new SimpleObjectProperty<>(this, "state", READY); 56 | private final ObjectProperty exception = new SimpleObjectProperty<>(this, "exception"); 57 | 58 | @Override 59 | public boolean isInitialized() { 60 | return initialized.get(); 61 | } 62 | 63 | @Override 64 | public ReadOnlyBooleanProperty initializedProperty() { 65 | return initialized; 66 | } 67 | 68 | @Override 69 | public ConnectState getState() { 70 | return state.get(); 71 | } 72 | 73 | public void setState(ConnectState state) { 74 | final ConnectState s = getState(); 75 | if (s != CANCELLED) { 76 | this.state.set(state); 77 | 78 | // Invoke the event handlers 79 | switch (this.state.get()) { 80 | case CANCELLED: 81 | fireEvent(new ConnectStateEvent(this, CONNECT_STATE_CANCELLED)); 82 | break; 83 | case FAILED: 84 | fireEvent(new ConnectStateEvent(this, CONNECT_STATE_FAILED)); 85 | break; 86 | case READY: 87 | // This event can never meaningfully occur, because the 88 | // GluonObservable begins life as ready and can never go back to it! 89 | break; 90 | case RUNNING: 91 | fireEvent(new ConnectStateEvent(this, CONNECT_STATE_RUNNING)); 92 | break; 93 | case REMOVED: 94 | fireEvent(new ConnectStateEvent(this, CONNECT_STATE_REMOVED)); 95 | break; 96 | case SUCCEEDED: 97 | fireEvent(new ConnectStateEvent(this, CONNECT_STATE_SUCCEEDED)); 98 | break; 99 | default: 100 | throw new AssertionError("Should be unreachable"); 101 | } 102 | } 103 | } 104 | 105 | @Override 106 | public ReadOnlyObjectProperty stateProperty() { 107 | return state; 108 | } 109 | 110 | @Override 111 | public Throwable getException() { 112 | return exception.get(); 113 | } 114 | 115 | public void setException(Throwable exception) { 116 | this.exception.set(exception); 117 | } 118 | 119 | @Override 120 | public ReadOnlyObjectProperty exceptionProperty() { 121 | return exception; 122 | } 123 | 124 | @Override 125 | public void setOnReady(EventHandler value) { 126 | getEventHelper().setOnReady(value); 127 | } 128 | 129 | @Override 130 | public void setOnRunning(EventHandler value) { 131 | getEventHelper().setOnRunning(value); 132 | } 133 | 134 | @Override 135 | public void setOnFailed(EventHandler value) { 136 | getEventHelper().setOnFailed(value); 137 | } 138 | 139 | @Override 140 | public void setOnSucceeded(EventHandler value) { 141 | getEventHelper().setOnSucceeded(value); 142 | } 143 | 144 | @Override 145 | public void setOnCancelled(EventHandler value) { 146 | getEventHelper().setOnCancelled(value); 147 | } 148 | 149 | @Override 150 | public void setOnRemoved(EventHandler value) { 151 | getEventHelper().setOnRemoved(value); 152 | } 153 | 154 | @Override 155 | public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) { 156 | return getEventHelper().buildEventDispatchChain(tail); 157 | } 158 | 159 | private void fireEvent(ConnectStateEvent event) { 160 | getEventHelper().fireEvent(event); 161 | } 162 | 163 | private EventHelper eventHelper = null; 164 | private EventHelper getEventHelper() { 165 | if (eventHelper == null) { 166 | eventHelper = new EventHelper(this); 167 | } 168 | return eventHelper; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/MultiValuedMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect; 28 | 29 | import java.util.HashMap; 30 | import java.util.LinkedList; 31 | import java.util.List; 32 | import java.util.Map; 33 | 34 | /** 35 | * A Map of key-value pairs where a key can contain multiple values. 36 | * 37 | * @param the type of keys maintained by this map 38 | * @param the type of mapped values 39 | */ 40 | public class MultiValuedMap extends HashMap> { 41 | 42 | /** 43 | * Add the provided value to the list of values associated with this key. 44 | * 45 | * @param key the key 46 | * @param value the new (additional) value belonging to this key. 47 | * @return the list associated with this key 48 | */ 49 | public List putSingle(K key, V value) { 50 | List list = super.get(key); 51 | if (list == null) { 52 | list = new LinkedList<>(); 53 | super.put(key, list); 54 | } 55 | list.add(value); 56 | return list; 57 | } 58 | 59 | /** 60 | * Copies all of the mappings from the specified map into this map. 61 | * 62 | * @param map mappings to be stored in this map 63 | */ 64 | public void putMap(Map map) { 65 | for (Entry entry : map.entrySet()) { 66 | putSingle(entry.getKey(), entry.getValue()); 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/InputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | /** 30 | * An InputConverter is a Converter that is able to read an object from a certain input source. The actual source is not 31 | * defined on this interface and is thus completely left open for the implementations to define. 32 | * 33 | * @param the type of the object that is read by this InputConverter 34 | */ 35 | public interface InputConverter { 36 | 37 | /** 38 | * Reads an object from a certain input source and returns it. 39 | * 40 | * @return An object read from a certain input source. 41 | */ 42 | T read(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/InputStreamInputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import java.io.InputStream; 30 | 31 | /** 32 | * An abstract helper class that defines an InputConverter of which the input source is a standard 33 | * {@link java.io.InputStream}. This class can be extended by an implementation of InputConverter that makes use of an 34 | * InputStream as its input source. The data that is being read from the InputStream can be used to convert it into an 35 | * actual object. 36 | * 37 | * @param the type of the object that is read by this InputConverter 38 | */ 39 | public abstract class InputStreamInputConverter implements InputConverter { 40 | 41 | private InputStream inputStream; 42 | 43 | /** 44 | * Returns the InputStream where this InputConverter will read its data from. 45 | * 46 | * @return The InputStream to use as the input source for this InputConverter. 47 | */ 48 | public InputStream getInputStream() { 49 | return inputStream; 50 | } 51 | 52 | /** 53 | * Sets the InputStream to be used as the input source for this InputConverter. 54 | * 55 | * @param inputStream The InputStream to use as the input source for this InputConverter. 56 | */ 57 | public void setInputStream(InputStream inputStream) { 58 | this.inputStream = inputStream; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/InputStreamIterableInputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import java.io.InputStream; 30 | 31 | /** 32 | * An abstract helper class that defines an IterableInputConverter of which the input source is a standard 33 | * {@link java.io.InputStream}. This class can be extended by an implementation of IterableInputConverter that makes use 34 | * of an InputStream as its input source. The created Iterator can then iterate over the list of objects that are being 35 | * converted from the data that is being read from the InputStream. 36 | * 37 | * @param the type of the objects that are read by this IterableInputConverter 38 | */ 39 | public abstract class InputStreamIterableInputConverter implements IterableInputConverter { 40 | 41 | private InputStream inputStream; 42 | 43 | /** 44 | * Returns the InputStream where this IterableInputConverter will read its data from. 45 | * 46 | * @return The InputStream to use as the input source for this IterableInputConverter. 47 | */ 48 | public InputStream getInputStream() { 49 | return inputStream; 50 | } 51 | 52 | /** 53 | * Sets the InputStream to be used as the input source for this IterableInputConverter. 54 | * 55 | * @param inputStream The InputStream to use as the input source for this IterableInputConverter. 56 | */ 57 | public void setInputStream(InputStream inputStream) { 58 | this.inputStream = inputStream; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/IterableInputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import java.util.Iterator; 30 | 31 | /** 32 | * An IterableInputConverter is a Converter that is able to read a list of objects from a certain input source by 33 | * creating an {@link java.util.Iterator} to provide that list. The actual source is not defined on this interface and 34 | * is thus completely left open for the implementations to define. 35 | * 36 | * @param the type of the objects that are read by this IterableInputConverter 37 | */ 38 | public interface IterableInputConverter { 39 | 40 | /** 41 | * Creates an Iterator that is used to iterate over a list of objects that are read from a certain input source. 42 | * 43 | * @return An Iterator to iterate over a list of objects read from a certain input source. 44 | */ 45 | Iterator iterator(); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/JsonInputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import com.gluonhq.impl.connect.converter.JsonUtil; 30 | 31 | import javax.json.JsonObject; 32 | import javax.json.JsonReader; 33 | 34 | /** 35 | * An InputConverter that converts a JSON Object read from an InputStream into an object. The actual conversion from 36 | * JSON to an object is handled by an instance of {@link JsonConverter}. 37 | * 38 | * @param the type of the object to convert the JSON Object into 39 | */ 40 | public class JsonInputConverter extends InputStreamInputConverter { 41 | 42 | private final JsonConverter converter; 43 | 44 | /** 45 | * Construct a new instance of a JsonInputConverter that is able to convert the data read from the InputStream into 46 | * objects of the specified targetClass. 47 | * 48 | * @param targetClass The class defining the objects being converted from JSON. 49 | */ 50 | public JsonInputConverter(Class targetClass) { 51 | this.converter = new JsonConverter<>(targetClass); 52 | } 53 | 54 | /** 55 | * Converts a JSON Object that is read from the InputStream into an object and returns it. If the specified 56 | * targetClass in the constructor equals to JsonObject.class, then this method will just return the 57 | * read JSON object directly instead of running the conversion. Otherwise, a {@link JsonConverter} will be used to 58 | * convert the JSON Object into the final object to return. 59 | * 60 | * @return An object converted from the JSON Object that was read from the InputStream. 61 | */ 62 | @Override 63 | public T read() { 64 | try (JsonReader reader = JsonUtil.createJsonReader(getInputStream())) { 65 | JsonObject jsonObject = reader.readObject(); 66 | if (JsonObject.class.isAssignableFrom(converter.getTargetClass())) { 67 | return (T) jsonObject; 68 | } else { 69 | return converter.readFromJson(jsonObject); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/JsonIterableInputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import com.gluonhq.impl.connect.converter.JsonUtil; 30 | 31 | import javax.json.JsonArray; 32 | import javax.json.JsonObject; 33 | import javax.json.JsonReader; 34 | import java.util.Iterator; 35 | 36 | /** 37 | * An IterableInputConverter that converts a JSON Array read from an InputStream into an Iterator that can be used to 38 | * iterate over a list of objects. The actual conversion from JSON to an object is handled by an instance of 39 | * {@link JsonConverter}. 40 | * 41 | * @param the type of the object that the items in the JSON Array are converted into 42 | */ 43 | public class JsonIterableInputConverter extends InputStreamIterableInputConverter implements Iterator { 44 | 45 | private final Class targetClass; 46 | 47 | private JsonArray jsonArray; 48 | private int index; 49 | private JsonConverter converter; 50 | 51 | /** 52 | * Construct a new instance of a JsonIterableInputConverter that is able to convert the data read from the 53 | * InputStream into objects of the specified targetClass. 54 | * 55 | *

The targetClass can be any of the types listed below. All other types will be converted from 56 | * JSON by using a {@link JsonConverter}.

57 | * 58 | *
    59 | *
  • java.lang.Boolean: read from the JSON value as JsonValue.TRUE or JsonValue.FALSE
  • 60 | *
  • java.lang.Byte: read from the JSON value as an int and converted into a byte
  • 61 | *
  • java.lang.Double: read from the JSON value as a JSON number from which the double value is taken
  • 62 | *
  • java.lang.Float: read from the JSON value as a JSON number from which the double value is taken that is converted to a float
  • 63 | *
  • java.lang.Integer: read from the JSON value as an int
  • 64 | *
  • java.lang.Long: read from the JSON value as a JSON number from which the long value is taken
  • 65 | *
  • java.lang.Short: read from the JSON value as an int and converted into a short
  • 66 | *
  • java.lang.String: read from the JSON value as a JSON String
  • 67 | *
  • javax.json.JsonObject: the returned objects will be the actual JSON Object that is read from the JSON Array
  • 68 | *
69 | * 70 | * @param targetClass The class defining the objects being converted from JSON. 71 | */ 72 | public JsonIterableInputConverter(Class targetClass) { 73 | this.targetClass = targetClass; 74 | } 75 | 76 | /** 77 | * Returns the next element in the iteration. In this case, it will be an object that is converted from the next 78 | * available element in the JSON Array that was read from the InputStream. 79 | * 80 | * @return An object converted from the JSON Value that is taken from the next element in the JSON Array. 81 | */ 82 | @Override 83 | public E next() { 84 | if (Boolean.class.isAssignableFrom(targetClass)) { 85 | return (E) (Boolean) jsonArray.getBoolean(index++); 86 | } else if (Byte.class.isAssignableFrom(targetClass)) { 87 | return (E) (Byte) ((Integer) jsonArray.getInt(index++)).byteValue(); 88 | } else if (Double.class.isAssignableFrom(targetClass)) { 89 | return (E) (Double) jsonArray.getJsonNumber(index++).doubleValue(); 90 | } else if (Float.class.isAssignableFrom(targetClass)) { 91 | return (E) (Float) ((Double) jsonArray.getJsonNumber(index++).doubleValue()).floatValue(); 92 | } else if (Integer.class.isAssignableFrom(targetClass)) { 93 | return (E) (Integer) jsonArray.getInt(index++); 94 | } else if (Long.class.isAssignableFrom(targetClass)) { 95 | return (E) (Long) jsonArray.getJsonNumber(index++).longValue(); 96 | } else if (Short.class.isAssignableFrom(targetClass)) { 97 | return (E) (Short) ((Integer) jsonArray.getInt(index++)).shortValue(); 98 | } else if (String.class.isAssignableFrom(targetClass)) { 99 | return (E) jsonArray.getString(index++); 100 | } else { 101 | JsonObject jsonObject = jsonArray.getJsonObject(index++); 102 | if (JsonObject.class.isAssignableFrom(targetClass)) { 103 | return (E) jsonObject; 104 | } else { 105 | if (converter == null) { 106 | converter = new JsonConverter<>(targetClass); 107 | } 108 | return converter.readFromJson(jsonObject); 109 | } 110 | } 111 | } 112 | 113 | /** 114 | * Returns true if the iteration has more elements, in this case if there are more elements to be 115 | * returned from the JSON Array that was read from the InputStream. 116 | * 117 | * @return true if there are more items available in the Iterator, false otherwise. 118 | */ 119 | @Override 120 | public boolean hasNext() { 121 | return index < jsonArray.size(); 122 | } 123 | 124 | /** 125 | * Returns an Iterator that loops over the items in the JSON Array that is read from the InputStream. This 126 | * implementation returns itself as the Iterator. Each element inside the JSON Array will be converted into the 127 | * correct object when the {@link #next} method is called. 128 | * 129 | * @return An Iterator that can be used to loop over the objects that are contained in the JSON Array that was read 130 | * from the InputStream. 131 | */ 132 | @Override 133 | public Iterator iterator() { 134 | index = 0; 135 | 136 | try (JsonReader reader = JsonUtil.createJsonReader(getInputStream())) { 137 | jsonArray = reader.readArray(); 138 | } 139 | 140 | return this; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/JsonOutputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import javax.json.Json; 30 | import javax.json.JsonObject; 31 | import javax.json.JsonWriter; 32 | import javax.json.JsonWriterFactory; 33 | import java.io.StringWriter; 34 | import java.util.logging.Level; 35 | import java.util.logging.Logger; 36 | 37 | /** 38 | * An OutputConverter that converts an object into a JSON Object that is written to an OutputStream. The actual 39 | * conversion to JSON is handled by using an instance of {@link JsonConverter}. 40 | * 41 | * @param the type of the object to convert to a JSON Object 42 | */ 43 | public class JsonOutputConverter extends OutputStreamOutputConverter implements OutputConverter { 44 | 45 | private static final Logger LOG = Logger.getLogger(JsonOutputConverter.class.getName()); 46 | 47 | private static final JsonWriterFactory writerFactory = Json.createWriterFactory(null); 48 | 49 | private final JsonConverter converter; 50 | 51 | /** 52 | * Construct a new instance of a JsonOutputConverter that is able to convert objects of the specified 53 | * targetClass into JSON Objects and write them into the OutputStream. 54 | * 55 | * @param targetClass The class defining the objects being converted into JSON. 56 | */ 57 | public JsonOutputConverter(Class targetClass) { 58 | converter = new JsonConverter<>(targetClass); 59 | } 60 | 61 | /** 62 | * Converts an object into a JSON Object that is written to the InputStream. If the specified 63 | * targetClass in the constructor equals to JsonObject.class, then this method will cast the provided 64 | * object into a JsonObject instance and write it directly to the OutputStream. Otherwise, a {@link JsonConverter} 65 | * will be used to convert the object into a JSON Object. 66 | * 67 | * @param t The object to convert into a JSON Object that will be written to the OutputStream. 68 | */ 69 | @Override 70 | public void write(T t) { 71 | try (JsonWriter writer = writerFactory.createWriter(getOutputStream())) { 72 | JsonObject jsonObject; 73 | if (JsonObject.class.isAssignableFrom(converter.getTargetClass())) { 74 | jsonObject = (JsonObject) t; 75 | } else { 76 | jsonObject = converter.writeToJson(t); 77 | } 78 | 79 | if (LOG.isLoggable(Level.FINE)) { 80 | StringWriter stringWriter = new StringWriter(); 81 | try (JsonWriter writer2 = writerFactory.createWriter(stringWriter)) { 82 | writer2.writeObject(jsonObject); 83 | LOG.log(Level.FINE, "Written JSON data: " + stringWriter.toString()); 84 | } 85 | } 86 | 87 | writer.writeObject(jsonObject); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/OutputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | /** 30 | * An OutputConverter is a Converter that is able to write an object to a certain output source. The actual source is 31 | * not defined on this interface and is thus completely left open for the implementations to define. 32 | * 33 | * @param the type of the object that is written by this OutputConverter 34 | */ 35 | public interface OutputConverter { 36 | 37 | /** 38 | * Writes an object to a certain output source. 39 | * 40 | * @param t The object to write to a certain output source. 41 | */ 42 | void write(T t); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/OutputStreamOutputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import java.io.OutputStream; 30 | 31 | /** 32 | * An abstract helper class that defines an OutputConverter of which the output source is a standard 33 | * {@link java.io.OutputStream}. This class can be extended by an implementation of OutputConverter that makes use of an 34 | * OutputStream as its output source. The object can then be converted into data that is written directly into the 35 | * OutputStream. 36 | * 37 | * @param the type of the object that is written by this OutputConverter 38 | */ 39 | public abstract class OutputStreamOutputConverter implements OutputConverter { 40 | 41 | private OutputStream outputStream; 42 | 43 | /** 44 | * Returns the OutputStream where this OutputConverter will write the converted object to. 45 | * 46 | * @return The OutputStream to use as the output source for this OutputConverter. 47 | */ 48 | public OutputStream getOutputStream() { 49 | return outputStream; 50 | } 51 | 52 | /** 53 | * Sets the OutputStream to be used as the output source for this OutputConverter. 54 | * 55 | * @param outputStream The OutputStream to use as the output source for this OutputConverter. 56 | */ 57 | public void setOutputStream(OutputStream outputStream) { 58 | this.outputStream = outputStream; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/StringInputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import java.io.BufferedReader; 30 | import java.io.BufferedWriter; 31 | import java.io.IOException; 32 | import java.io.InputStreamReader; 33 | import java.io.StringWriter; 34 | import java.util.logging.Level; 35 | import java.util.logging.Logger; 36 | 37 | /** 38 | * An InputConverter that reads a string from an InputStream. 39 | */ 40 | public class StringInputConverter extends InputStreamInputConverter { 41 | 42 | private static final Logger LOGGER = Logger.getLogger(StringInputConverter.class.getName()); 43 | 44 | /** 45 | * Reads a string from an InputStream. 46 | * 47 | * @return A string object that was read from the InputStream. 48 | */ 49 | @Override 50 | public String read() { 51 | try (StringWriter stringWriter = new StringWriter()) { 52 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(getInputStream())); BufferedWriter writer = new BufferedWriter(stringWriter)) { 53 | boolean firstWrite = true; 54 | String line; 55 | while ((line = reader.readLine()) != null) { 56 | if (firstWrite) { 57 | firstWrite = false; 58 | } else { 59 | writer.newLine(); 60 | } 61 | writer.write(line); 62 | } 63 | } 64 | 65 | return stringWriter.toString(); 66 | } catch (IOException ex) { 67 | LOGGER.log(Level.SEVERE, "Something went wrong while reading string from InputStream.", ex); 68 | return null; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/StringOutputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import java.io.BufferedWriter; 30 | import java.io.IOException; 31 | import java.io.OutputStreamWriter; 32 | import java.util.logging.Level; 33 | import java.util.logging.Logger; 34 | 35 | /** 36 | * An OutputConverter that writes a string to an OutputStream. 37 | */ 38 | public class StringOutputConverter extends OutputStreamOutputConverter { 39 | 40 | private static final Logger LOGGER = Logger.getLogger(StringOutputConverter.class.getName()); 41 | 42 | /** 43 | * 44 | * 45 | * @param string the string to write to the OutputStream. 46 | */ 47 | @Override 48 | public void write(String string) { 49 | try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(getOutputStream()))) { 50 | writer.write(string); 51 | } catch (IOException ex) { 52 | LOGGER.log(Level.SEVERE, "Something went wrong while writing string to OutputStream.", ex); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/VoidInputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | import java.util.logging.Level; 32 | import java.util.logging.Logger; 33 | 34 | /** 35 | * An InputConverter that reads the entire InputStream, while discarding its contents. 36 | */ 37 | public class VoidInputConverter extends InputStreamInputConverter { 38 | 39 | private static final Logger LOGGER = Logger.getLogger(StringInputConverter.class.getName()); 40 | 41 | /** 42 | * Reads from an InputStream and always returns null. 43 | * 44 | * @return A null object. 45 | */ 46 | @Override 47 | public Void read() { 48 | try (InputStream inputStream = getInputStream()) { 49 | int read; 50 | byte[] bytes = new byte[4096]; 51 | while ((read = inputStream.read(bytes)) != -1) { 52 | // ignore read bytes 53 | } 54 | } catch (IOException ex) { 55 | LOGGER.log(Level.SEVERE, "Something went wrong while reading data from InputStream.", ex); 56 | } 57 | 58 | return null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/VoidOutputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import java.io.IOException; 30 | import java.io.OutputStream; 31 | import java.util.logging.Level; 32 | import java.util.logging.Logger; 33 | 34 | /** 35 | * An OutputConverter that doesn't write anything to an OutputStream. 36 | */ 37 | public class VoidOutputConverter extends OutputStreamOutputConverter { 38 | 39 | private static final Logger LOGGER = Logger.getLogger(StringOutputConverter.class.getName()); 40 | 41 | /** 42 | * Just closes the provided OutputStream. 43 | * 44 | * @param v the void instance, which is always null. 45 | */ 46 | @Override 47 | public void write(Void v) { 48 | try (OutputStream outputStream = getOutputStream()) { 49 | outputStream.close(); 50 | } catch (IOException ex) { 51 | LOGGER.log(Level.SEVERE, "Something went wrong while closing OutputStream.", ex); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/XmlInputConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import com.gluonhq.impl.connect.converter.ClassInspector; 30 | import java.io.IOException; 31 | import java.io.InputStream; 32 | import java.lang.reflect.InvocationTargetException; 33 | import java.lang.reflect.Method; 34 | import java.util.Map; 35 | import java.util.Set; 36 | import java.util.logging.Level; 37 | import java.util.logging.Logger; 38 | import javax.xml.parsers.DocumentBuilder; 39 | import javax.xml.parsers.DocumentBuilderFactory; 40 | import javax.xml.parsers.ParserConfigurationException; 41 | import org.w3c.dom.Document; 42 | import org.w3c.dom.Node; 43 | import org.w3c.dom.NodeList; 44 | import org.xml.sax.SAXException; 45 | 46 | /** 47 | * An InputConverter that converts a XML Object read from an InputStream into an object. 48 | * 49 | * @param the type of the object to convert the XML Object into 50 | */ 51 | public class XmlInputConverter extends InputStreamInputConverter { 52 | 53 | private Class clazz; 54 | private final ClassInspector inspector; 55 | private String tag; 56 | 57 | /** 58 | * Construct a new instance of a XmlInputConverter that is able to convert the data read from the InputStream into 59 | * objects of the specified targetClass. 60 | * 61 | * @param targetClass The class defining the objects being converted from XML. 62 | */ 63 | public XmlInputConverter(Class targetClass) { 64 | this(targetClass, null); 65 | } 66 | 67 | /** 68 | * Construct a new instance of a XmlInputConverter that is able to convert the data read from the InputStream into 69 | * objects of the specified targetClass. 70 | * Often, the XML returned by web services has the relevant information nested or wrapped in rootnodes. 71 | * If there is a 1-1 mapping between the data and the Object, we would end up with unused wrapper classes. 72 | * By specifying the name of the node that contains the relevant information, the wrapping data is ignored. 73 | * 74 | * @param targetClass The class defining the objects being converted from XML. 75 | * @param tag the nodename of the rootnode containing the relevant information. 76 | */ 77 | public XmlInputConverter(Class targetClass, String tag) { 78 | this.clazz = targetClass; 79 | this.inspector = ClassInspector.resolve(targetClass); 80 | this.tag = tag; 81 | } 82 | 83 | @Override 84 | public T read() { 85 | try { 86 | DocumentBuilderFactory factory = 87 | DocumentBuilderFactory.newInstance(); 88 | DocumentBuilder builder = factory.newDocumentBuilder(); 89 | InputStream is = getInputStream(); 90 | T answer = clazz.newInstance(); 91 | Document doc = builder.parse(is); 92 | Node rootNode = doc.getDocumentElement(); 93 | if (tag != null) { 94 | NodeList nodeList = doc.getElementsByTagName(tag); 95 | if (nodeList.getLength() > 0) rootNode = nodeList.item(0); 96 | parseDom (rootNode.getChildNodes(), answer); 97 | } 98 | return answer; 99 | } catch (InstantiationException ex) { 100 | Logger.getLogger(XmlInputConverter.class.getName()).log(Level.SEVERE, null, ex); 101 | } catch (IllegalAccessException ex) { 102 | Logger.getLogger(XmlInputConverter.class.getName()).log(Level.SEVERE, null, ex); 103 | } catch (ParserConfigurationException ex) { 104 | Logger.getLogger(XmlInputConverter.class.getName()).log(Level.SEVERE, null, ex); 105 | } catch (SAXException ex) { 106 | Logger.getLogger(XmlInputConverter.class.getName()).log(Level.SEVERE, null, ex); 107 | } catch (IOException ex) { 108 | Logger.getLogger(XmlInputConverter.class.getName()).log(Level.SEVERE, null, ex); 109 | } 110 | return null; 111 | } 112 | 113 | private void parseDom(NodeList childNodes, T answer) { 114 | Map setters = this.inspector.getSetters(); 115 | Set keySet = setters.keySet(); 116 | for (int i = 0; i < childNodes.getLength(); i++) { 117 | Node item = childNodes.item(i); 118 | if (keySet.contains(item.getNodeName())) { 119 | try { 120 | Method setter = setters.get(item.getNodeName()); 121 | Class parameterType = setter.getParameterTypes()[0]; 122 | if (parameterType.isAssignableFrom(String.class)) { 123 | setter.invoke(answer, item.getTextContent()); 124 | } 125 | } catch (IllegalAccessException ex) { 126 | Logger.getLogger(XmlInputConverter.class.getName()).log(Level.SEVERE, null, ex); 127 | } catch (IllegalArgumentException ex) { 128 | Logger.getLogger(XmlInputConverter.class.getName()).log(Level.SEVERE, null, ex); 129 | } catch (InvocationTargetException ex) { 130 | Logger.getLogger(XmlInputConverter.class.getName()).log(Level.SEVERE, null, ex); 131 | } 132 | } 133 | } 134 | } 135 | 136 | 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/converter/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /** 28 | * The com.gluonhq.connect.converter package contains classes that describe how to convert between Java 29 | * objects and a certain data format. 30 | */ 31 | package com.gluonhq.connect.converter; -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /** 28 | * The package containing the base classes of the Gluon Connect framework. 29 | */ 30 | package com.gluonhq.connect; -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/BaseRestProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.source.RestDataSource; 30 | 31 | import java.util.List; 32 | import java.util.Map; 33 | import java.util.logging.Level; 34 | import java.util.logging.Logger; 35 | 36 | public class BaseRestProvider { 37 | 38 | private static final Logger LOG = Logger.getLogger(BaseRestProvider.class.getName()); 39 | 40 | private static final String RESPONSE_HEADER_CONTENT_TYPE = "Content-Type"; 41 | 42 | protected static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; 43 | protected static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain"; 44 | 45 | protected final RestDataSource dataSource; 46 | 47 | public BaseRestProvider(RestDataSource dataSource) { 48 | this.dataSource = dataSource; 49 | } 50 | 51 | /** 52 | * Returns the rest data source that is used as the input and output data source. 53 | * 54 | * @return the rest data source being used as the input and output data source 55 | */ 56 | public RestDataSource getRestDataSource() { 57 | return dataSource; 58 | } 59 | 60 | /** 61 | * Returns the first Content-Type response header from the rest data source. The value of the content type 62 | * can be null when the response header is not provided by the HTTP response. Note that the method 63 | * {@link RestDataSource#getInputStream()} should already be called before calling this method. 64 | * 65 | * @return the Content-Type response header or null if the response header is not provided 66 | */ 67 | String getContentType() { 68 | String contentType = null; 69 | 70 | Map> responseHeaders = dataSource.getResponseHeaders(); 71 | if (responseHeaders.containsKey(RESPONSE_HEADER_CONTENT_TYPE)) { 72 | List contentTypes = responseHeaders.get(RESPONSE_HEADER_CONTENT_TYPE); 73 | if (! contentTypes.isEmpty()) { 74 | contentType = contentTypes.get(0); 75 | } 76 | } 77 | 78 | LOG.log(Level.FINE, "Detected Content-Type from response headers: " + contentType); 79 | 80 | return contentType; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/FileClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableObject; 30 | import com.gluonhq.connect.converter.InputStreamInputConverter; 31 | import com.gluonhq.connect.converter.InputStreamIterableInputConverter; 32 | import com.gluonhq.connect.converter.OutputStreamOutputConverter; 33 | import com.gluonhq.connect.source.FileDataSource; 34 | 35 | import java.io.File; 36 | import java.io.IOException; 37 | import java.util.Optional; 38 | 39 | /** 40 | *

The FileClient assists in using the {@link DataProvider} with files, that are located on the local file system, as 41 | * the data source. For instance, to read a file that contains json data, you can use the following code:

42 | * 43 | *
 44 |  *     FileClient fileClient = FileClient.create(new File("sample.json"));
 45 |  *     JsonInputConverter<Sample> converter = new JsonInputConverter<>(Sample.class);
 46 |  *     GluonObservableObject<Sample> sample = DataProvider.retrieveObject(fileClient.createObjectDataReader(converter));
 47 |  * 
48 | */ 49 | public class FileClient { 50 | 51 | private File file; 52 | 53 | private FileClient(File file) { 54 | this.file = file; 55 | } 56 | 57 | /** 58 | * Create a FileClient builder using the specified file as a data source. 59 | * 60 | * @param file the file to be used as the data source 61 | * @return a FileClient that can be used together with the {@link DataProvider} 62 | */ 63 | public static FileClient create(File file) { 64 | return new FileClient(file); 65 | } 66 | 67 | /** 68 | * Build a FileDataSource that can be used as an InputDataSource to read from the file or an OutputDataSource to 69 | * write to the file. 70 | * 71 | * @return a FileDataSource that works with the file that was specified on this FileClient 72 | */ 73 | public FileDataSource createFileDataSource() { 74 | return new FileDataSource(file); 75 | } 76 | 77 | /** 78 | * Creates an instance of {@link ObjectDataReader} that can be passed directly in the 79 | * {@link DataProvider#retrieveObject(ObjectDataReader)} method. The object data reader will read the data from 80 | * the file that was specified on this FileClient and convert it into an object by using the specified 81 | * converter. 82 | * 83 | * @param converter the converter to use to convert the data read from the file into an object 84 | * @param the type of the object to read 85 | * @return an ObjectDataReader instance that constructs an object from the file with the specified converter 86 | */ 87 | public ObjectDataReader createObjectDataReader(InputStreamInputConverter converter) { 88 | return new InputStreamObjectDataReader<>(createFileDataSource(), converter); 89 | } 90 | 91 | /** 92 | * Creates an instance of {@link ObjectDataWriter} that can be passed directly in the 93 | * {@link DataProvider#storeObject(Object, ObjectDataWriter)} method. The object data writer will convert an object 94 | * by using the specified converter and writes the converted data into the file that was specified on 95 | * this FileClient. 96 | * 97 | * @param converter the converter to use to convert the object into data to write to the file 98 | * @param the type of the object to write 99 | * @return an ObjectDataWriter instance that writes an object into the file with the specified converter 100 | */ 101 | public ObjectDataWriter createObjectDataWriter(OutputStreamOutputConverter converter) { 102 | return new OutputStreamObjectDataWriter<>(createFileDataSource(), converter); 103 | } 104 | 105 | /** 106 | * Creates an instance of {@link ObjectDataRemover} that can be passed directly in the 107 | * {@link DataProvider#removeObject(GluonObservableObject, ObjectDataRemover)} method. The actual observable object 108 | * that is passed in with the removeObject method is ignored. The ObjectDataRemover will just remove the file that 109 | * was specified on this FileClient. 110 | * 111 | * @param the type of the object to remove 112 | * @return an ObjectDataRemover instance that removes the file 113 | */ 114 | public ObjectDataRemover createObjectDataRemover() { 115 | return observable -> { 116 | if (file.exists() && file.isFile()) { 117 | if (!file.delete()) { 118 | throw new IOException("Failed to delete file: " + file); 119 | } 120 | } 121 | 122 | return Optional.empty(); 123 | }; 124 | } 125 | 126 | /** 127 | * Creates an instance of {@link ListDataReader} that can be passed directly in the 128 | * {@link DataProvider#retrieveList(ListDataReader)} method. The list data reader will read the data from the file 129 | * that was specified on this FileClient and convert it into a list of objects by using the specified 130 | * converter. 131 | * 132 | * @param converter the converter to use to convert the data read from the file into a list of objects 133 | * @param the type of the objects contained in the list to read 134 | * @return a ListDataReader instance that constructs a list of objects from the file with the specified converter 135 | */ 136 | public ListDataReader createListDataReader(InputStreamIterableInputConverter converter) { 137 | return new InputStreamListDataReader<>(createFileDataSource(), converter); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/InputStreamListDataReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableList; 30 | import com.gluonhq.connect.converter.InputStreamIterableInputConverter; 31 | import com.gluonhq.connect.source.InputDataSource; 32 | 33 | import java.io.IOException; 34 | import java.util.Iterator; 35 | 36 | /** 37 | * A helper class that represents a {@link ListDataReader} that reads objects by reading from a specific 38 | * {@link InputDataSource} and converts the read data with a specific 39 | * {@link InputStreamIterableInputConverter}. 40 | * 41 | * @param the type of the objects contained in the list to read 42 | */ 43 | public class InputStreamListDataReader implements ListDataReader { 44 | 45 | private final InputDataSource dataSource; 46 | private final InputStreamIterableInputConverter converter; 47 | 48 | /** 49 | * Construct an instance that will use the specified data source to read data from and convert it to a list of 50 | * objects with the specified converter. The InputStream of the InputDataSource will be set on the Converter before 51 | * calling its {@link InputStreamIterableInputConverter#iterator() iterator} method. 52 | * 53 | * @param dataSource the data source where the data will be read from 54 | * @param converter the converter that is used for converting the data into a list of object 55 | */ 56 | public InputStreamListDataReader(InputDataSource dataSource, InputStreamIterableInputConverter converter) { 57 | this.dataSource = dataSource; 58 | this.converter = converter; 59 | } 60 | 61 | @Override 62 | public GluonObservableList newGluonObservableList() { 63 | return new GluonObservableList<>(); 64 | } 65 | 66 | /** 67 | * Returns an iterator that is able to iterate over the read objects from the list. This implementation uses the 68 | * specified converter to convert the data that is read from the specified data source into a list of objects. The 69 | * InputStream of the specified data source will be set on the converter, before calling the 70 | * {@link InputStreamIterableInputConverter#iterator() iterator} method on the converter. 71 | * 72 | * @return an iterator that is able to read over the objects from the list 73 | * @throws IOException when something went wrong during the process of reading the objects 74 | */ 75 | @Override 76 | public Iterator iterator() throws IOException { 77 | converter.setInputStream(dataSource.getInputStream()); 78 | return converter.iterator(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/InputStreamObjectDataReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableObject; 30 | import com.gluonhq.connect.converter.InputStreamInputConverter; 31 | import com.gluonhq.connect.source.InputDataSource; 32 | 33 | import java.io.IOException; 34 | 35 | /** 36 | * A helper class that represents an {@link ObjectDataReader} that reads an object by reading from a specific 37 | * {@link InputDataSource} and converting the read data with a specific 38 | * {@link com.gluonhq.connect.converter.InputStreamInputConverter}. 39 | * 40 | * @param the type of the object to read 41 | */ 42 | public class InputStreamObjectDataReader implements ObjectDataReader { 43 | 44 | private final InputDataSource dataSource; 45 | private final InputStreamInputConverter converter; 46 | 47 | /** 48 | * Construct an instance that will use the specified data source to read data from and convert it to an object with 49 | * the specified converter. The InputStream of the InputDataSource will be set on the Converter before calling its 50 | * {@link InputStreamInputConverter#read() read} method. 51 | * 52 | * @param dataSource the data source where the data will be read from 53 | * @param converter the converter that is used for converting the data into an object 54 | */ 55 | public InputStreamObjectDataReader(InputDataSource dataSource, InputStreamInputConverter converter) { 56 | this.dataSource = dataSource; 57 | this.converter = converter; 58 | } 59 | 60 | @Override 61 | public GluonObservableObject newGluonObservableObject() { 62 | return new GluonObservableObject<>(); 63 | } 64 | 65 | /** 66 | * Reads the object from the specified data source. This implementation uses the specified converter to convert 67 | * the data that is read from the specified data source into an object. The InputStream of the specified data source 68 | * will be set on the converter, before calling the {@link InputStreamInputConverter#read() read} method on the 69 | * converter. 70 | * 71 | * @return the read object 72 | * @throws IOException when an exception occurred during the read process 73 | */ 74 | @Override 75 | public T readObject() throws IOException { 76 | converter.setInputStream(dataSource.getInputStream()); 77 | return converter.read(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/ListDataReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableList; 30 | 31 | import java.io.IOException; 32 | import java.util.Iterator; 33 | 34 | /** 35 | * A ListDataReader is an entity that has the ability to read a list of objects. The actual source and method that 36 | * are used for reading the objects is completely up to the implementation. Typically, a the reader will read its 37 | * data by using an {@link com.gluonhq.connect.source.InputDataSource} and converts the read bytes into objects by 38 | * using an {@link com.gluonhq.connect.converter.IterableInputConverter}. 39 | * 40 | * @param the type of the objects contained in the list to read 41 | */ 42 | public interface ListDataReader { 43 | 44 | /** 45 | * Provide an instance of a GluonObservableList. This method will be called by {@link DataProvider#retrieveList(ListDataReader)} 46 | * to get a GluonObservableList that can be populated. Most implementations will just return an instance of 47 | * GluonObservableList itself. Note that it is perfectly valid to return existing instances of 48 | * GluonObservableList. 49 | * 50 | * @return an instance of GluonObservableList 51 | */ 52 | GluonObservableList newGluonObservableList(); 53 | 54 | /** 55 | * Returns an iterator that is able to iterate over the read objects from the list. This method will be 56 | * called by {@link DataProvider#retrieveList(ListDataReader)} to initiate the read process. The returned 57 | * iterator will be used to populate the GluonObservableList that is returned in the {@link #newGluonObservableList()} 58 | * method. 59 | * 60 | * @return an iterator that is able to read over the objects from the list 61 | * @throws IOException when something went wrong during the process of reading the objects 62 | */ 63 | Iterator iterator() throws IOException; 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/ObjectDataReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableObject; 30 | 31 | import java.io.IOException; 32 | 33 | /** 34 | * An ObjectDataReader is an entity that has the ability to read an object. The actual source and method that are used 35 | * for reading the object is completely up to the implementation. The most common scenario is that the reader reads 36 | * its data using a {@link com.gluonhq.connect.source.InputDataSource} and converts the read bytes by using an 37 | * {@link com.gluonhq.connect.converter.InputConverter}. 38 | * 39 | * @param the type of the object to read 40 | */ 41 | public interface ObjectDataReader { 42 | 43 | /** 44 | * Provide an instance of a GluonObservableObject. This method is called by {@link DataProvider#retrieveObject(ObjectDataReader)} 45 | * to get a GluonObservableObject that will contain the actual object when the retrieve operation has completed 46 | * successfully. Most implementations will just return an instance of GluonObservableObject itself. Note that it is 47 | * perfectly valid to return existing instances of GluonObservableObject. 48 | * 49 | * @return an instance of a GluonObservableObject 50 | */ 51 | GluonObservableObject newGluonObservableObject(); 52 | 53 | /** 54 | * Reads the object and returns it. The actual source of the read and the method that converts the read data into 55 | * an object instance is completely left to the implementation. This method is called by 56 | * {@link DataProvider#retrieveObject(ObjectDataReader)} to initiate the actual read process. The returned object 57 | * will be set on the GluonObservableObject that is returned in the {@link #newGluonObservableObject()} method. 58 | * 59 | * @return the read object 60 | * @throws IOException when an exception occurred during the read process 61 | */ 62 | T readObject() throws IOException; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/ObjectDataRemover.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableObject; 30 | 31 | import java.io.IOException; 32 | import java.util.Optional; 33 | 34 | /** 35 | * An ObjectDataRemover is an entity that has the ability to remove an object. The actual source and method that are 36 | * used for removing the object is completely up to the implementation. The most common scenario is that the remover 37 | * uses an {@link com.gluonhq.connect.source.OutputDataSource} that is able to remove the object that the source 38 | * points to. 39 | * 40 | * @param the type of the object to remove 41 | */ 42 | public interface ObjectDataRemover { 43 | 44 | /** 45 | * Removes the object and optionally returns an object. The actual method that removes the object is completely 46 | * left to the implementation. This method is called by {@link DataProvider#removeObject(GluonObservableObject, ObjectDataRemover)} 47 | * to initiate the actual removal process. If this method returns a non-empty Optional, the object that is contained 48 | * in the Optional will be set on the provided observable object. Otherwise, the value of the 49 | * observable object will be set to null. When the remove operation completed 50 | * successfully, the state of the provided observable will be set to 51 | * {@link com.gluonhq.connect.ConnectState#REMOVED}. 52 | * 53 | * @param observable the observable object that needs to be removed 54 | * @return an optional containing an object that will ultimately be set on the provided GluonObservableObject 55 | * @throws IOException when an exception occurred during the removal process 56 | */ 57 | Optional removeObject(GluonObservableObject observable) throws IOException; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/ObjectDataWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableObject; 30 | 31 | import java.io.IOException; 32 | import java.util.Optional; 33 | 34 | /** 35 | * An ObjectDataWriter is an entity that has the ability to write an object. The actual source and method that are used 36 | * for writing the object is completely up to the implementation. The most common scenario is that the writer converts 37 | * the object into serialized form by using an {@link com.gluonhq.connect.converter.OutputConverter} which than is 38 | * passed into an {@link com.gluonhq.connect.source.OutputDataSource} that is able to write the serialized data a 39 | * certain source. 40 | * 41 | * @param the type of the object to write 42 | */ 43 | public interface ObjectDataWriter { 44 | 45 | /** 46 | * Provide an instance of a GluonObservableObject. This method is called by {@link DataProvider#storeObject(Object, ObjectDataWriter)} 47 | * to get a GluonObservableObject that will contain the actual object when the store operation has completed 48 | * successfully. Most implementations will just return an instance of GluonObservableObject itself. Note that it is 49 | * perfectly valid to return existing instances of GluonObservableObject. 50 | * 51 | * @return an instance of a GluonObservableObject 52 | */ 53 | GluonObservableObject newGluonObservableObject(); 54 | 55 | /** 56 | * Writes the object and optionally returns one. The actual method that converts the object into serialized data and 57 | * the source where this data is written to is completely left to the implementation. This method is called by 58 | * {@link DataProvider#storeObject(Object, ObjectDataWriter)} to initiate the actual write process. The returned 59 | * object will be set on the final GluonObservableObject that is provided by this writer's 60 | * {@link #newGluonObservableObject()} method. The returned object can be the same as the provided object or it 61 | * can be a completely new object. An empty Optional can be returned as well, which is the same as returning the 62 | * provided object. 63 | * 64 | * @param object the object to write 65 | * @return the object that will ultimately be set on the GluonObservableObject 66 | * @throws IOException when an exception occurred during the write process 67 | */ 68 | Optional writeObject(T object) throws IOException; 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/OutputStreamObjectDataWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableObject; 30 | import com.gluonhq.connect.converter.OutputStreamOutputConverter; 31 | import com.gluonhq.connect.source.OutputDataSource; 32 | 33 | import java.io.IOException; 34 | import java.util.Optional; 35 | 36 | /** 37 | * A helper class that represents an {@link ObjectDataWriter} that writes an object by converting it with a specific 38 | * {@link com.gluonhq.connect.converter.OutputStreamOutputConverter} and writing it to a specific 39 | * {@link OutputDataSource}. 40 | * 41 | * @param the type of the object to write 42 | */ 43 | public class OutputStreamObjectDataWriter implements ObjectDataWriter { 44 | 45 | private final OutputDataSource dataSource; 46 | private final OutputStreamOutputConverter converter; 47 | 48 | /** 49 | * Construct an instance that will use the specified data source to write the object to that is converted with the 50 | * specified converter. The OutputStream of the OutputDataSource will be set on the Converter before calling its 51 | * {@link OutputStreamOutputConverter#write(Object) write} method. 52 | * 53 | * @param dataSource the data source where the converted object will be written to 54 | * @param converter the converter that is used for converting the object to be written 55 | */ 56 | public OutputStreamObjectDataWriter(OutputDataSource dataSource, OutputStreamOutputConverter converter) { 57 | this.dataSource = dataSource; 58 | this.converter = converter; 59 | } 60 | 61 | @Override 62 | public GluonObservableObject newGluonObservableObject() { 63 | return new GluonObservableObject<>(); 64 | } 65 | 66 | /** 67 | * Writes the object to the specified data source and returns an Optional that contains the exact same object 68 | * instance that was passed in. This implementation uses the specified converter to convert the provided 69 | * object. The OutputStream of the specified data source will be set on the converter, before calling 70 | * the {@link OutputStreamOutputConverter#write(Object) write} method on the converter. 71 | * 72 | * @param object the object to write 73 | * @return the object that will ultimately be set on the GluonObservableObject 74 | * @throws IOException when an exception occurred during the write process 75 | */ 76 | @Override 77 | public Optional writeObject(T object) throws IOException { 78 | converter.setOutputStream(dataSource.getOutputStream()); 79 | converter.write(object); 80 | return Optional.of(object); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/RestListDataReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableList; 30 | import com.gluonhq.connect.converter.InputStreamIterableInputConverter; 31 | import com.gluonhq.connect.converter.JsonIterableInputConverter; 32 | import com.gluonhq.connect.source.RestDataSource; 33 | 34 | import java.io.IOException; 35 | import java.io.InputStream; 36 | import java.util.Iterator; 37 | 38 | public class RestListDataReader extends BaseRestProvider implements ListDataReader { 39 | 40 | private final Class targetClass; 41 | private final InputStreamIterableInputConverter inputConverter; 42 | 43 | public RestListDataReader(RestDataSource dataSource, Class targetClass) { 44 | super(dataSource); 45 | 46 | this.targetClass = targetClass; 47 | this.inputConverter = null; 48 | } 49 | 50 | public RestListDataReader(RestDataSource dataSource, InputStreamIterableInputConverter inputConverter) { 51 | super(dataSource); 52 | 53 | this.targetClass = null; 54 | this.inputConverter = inputConverter; 55 | } 56 | 57 | @Override 58 | public GluonObservableList newGluonObservableList() { 59 | return new GluonObservableList<>(); 60 | } 61 | 62 | @Override 63 | public Iterator iterator() throws IOException { 64 | InputStream inputStream = dataSource.getInputStream(); 65 | InputStreamIterableInputConverter converter = inputConverter; 66 | if (converter == null) { 67 | String contentType = getContentType(); 68 | if (contentType != null) { 69 | if (contentType.startsWith(CONTENT_TYPE_APPLICATION_JSON)) { 70 | converter = new JsonIterableInputConverter<>(targetClass); 71 | } else { 72 | throw new IllegalStateException("Could not determine IterableInputConverter based on Content-Type: " + contentType); 73 | } 74 | } else { 75 | converter = new JsonIterableInputConverter<>(targetClass); 76 | } 77 | } 78 | 79 | converter.setInputStream(inputStream); 80 | return converter.iterator(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/RestObjectDataReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableObject; 30 | import com.gluonhq.connect.converter.InputStreamInputConverter; 31 | import com.gluonhq.connect.converter.JsonInputConverter; 32 | import com.gluonhq.connect.converter.StringInputConverter; 33 | import com.gluonhq.connect.converter.VoidInputConverter; 34 | import com.gluonhq.connect.source.RestDataSource; 35 | 36 | import java.io.IOException; 37 | import java.io.InputStream; 38 | 39 | public class RestObjectDataReader extends BaseRestProvider implements ObjectDataReader { 40 | 41 | protected final Class targetClass; 42 | private final InputStreamInputConverter inputConverter; 43 | 44 | public RestObjectDataReader(RestDataSource dataSource, Class targetClass) { 45 | super(dataSource); 46 | 47 | this.targetClass = targetClass; 48 | this.inputConverter = null; 49 | } 50 | 51 | public RestObjectDataReader(RestDataSource dataSource, InputStreamInputConverter inputConverter) { 52 | super(dataSource); 53 | 54 | this.targetClass = null; 55 | this.inputConverter = inputConverter; 56 | } 57 | 58 | @Override 59 | public GluonObservableObject newGluonObservableObject() { 60 | return new GluonObservableObject<>(); 61 | } 62 | 63 | @Override 64 | public T readObject() throws IOException { 65 | InputStream inputStream = dataSource.getInputStream(); 66 | InputStreamInputConverter converter = inputConverter; 67 | if (converter == null) { 68 | if (targetClass != null && String.class.isAssignableFrom(targetClass)) { 69 | converter = new StringInputConverter(); 70 | } else if (targetClass != null && Void.class.isAssignableFrom(targetClass)) { 71 | converter = new VoidInputConverter(); 72 | } else { 73 | int responseCode = getRestDataSource().getResponseCode(); 74 | if (responseCode == 204) { 75 | converter = new VoidInputConverter(); 76 | } else { 77 | String contentType = getContentType(); 78 | if (contentType != null) { 79 | if (contentType.startsWith(CONTENT_TYPE_APPLICATION_JSON)) { 80 | converter = new JsonInputConverter<>(targetClass); 81 | } else if (contentType.startsWith(CONTENT_TYPE_TEXT_PLAIN)) { 82 | converter = new StringInputConverter(); 83 | } else { 84 | throw new IllegalStateException("Could not determine InputConverter based on Content-Type: " + contentType); 85 | } 86 | } else { 87 | converter = new JsonInputConverter<>(targetClass); 88 | } 89 | } 90 | } 91 | } 92 | 93 | converter.setInputStream(inputStream); 94 | return (T) converter.read(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/RestObjectDataWriterAndRemover.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.GluonObservableObject; 30 | import com.gluonhq.connect.converter.InputStreamInputConverter; 31 | import com.gluonhq.connect.converter.JsonOutputConverter; 32 | import com.gluonhq.connect.converter.OutputStreamOutputConverter; 33 | import com.gluonhq.connect.converter.StringOutputConverter; 34 | import com.gluonhq.connect.converter.VoidOutputConverter; 35 | import com.gluonhq.connect.source.RestDataSource; 36 | 37 | import java.io.IOException; 38 | import java.util.Optional; 39 | 40 | public class RestObjectDataWriterAndRemover extends RestObjectDataReader implements ObjectDataWriter, ObjectDataRemover { 41 | 42 | private final OutputStreamOutputConverter outputConverter; 43 | 44 | public RestObjectDataWriterAndRemover(RestDataSource dataSource, Class targetClass) { 45 | super(dataSource, targetClass); 46 | 47 | this.outputConverter = null; 48 | } 49 | 50 | public RestObjectDataWriterAndRemover(RestDataSource dataSource, OutputStreamOutputConverter outputConverter, 51 | InputStreamInputConverter inputConverter) { 52 | super(dataSource, inputConverter); 53 | 54 | this.outputConverter = outputConverter; 55 | } 56 | 57 | @Override 58 | public Optional writeObject(T object) throws IOException { 59 | getOutputConverter().write(object); 60 | 61 | return Optional.ofNullable(readObject()); 62 | } 63 | 64 | @Override 65 | public Optional removeObject(GluonObservableObject observable) throws IOException { 66 | getOutputConverter().write(observable.get()); 67 | 68 | return Optional.ofNullable(readObject()); 69 | } 70 | 71 | private OutputStreamOutputConverter getOutputConverter() throws IOException { 72 | OutputStreamOutputConverter converter = outputConverter; 73 | 74 | if (converter == null) { 75 | if (dataSource.getContentType() != null) { 76 | if (dataSource.getContentType().startsWith(CONTENT_TYPE_APPLICATION_JSON)) { 77 | converter = new JsonOutputConverter<>(targetClass); 78 | } else { 79 | throw new IllegalStateException("Could not determine OutputConverter based on Content-Type: " + dataSource.getContentType()); 80 | } 81 | } else if (targetClass != null && String.class.isAssignableFrom(targetClass)) { 82 | converter = new StringOutputConverter(); 83 | } else if (targetClass != null && Void.class.isAssignableFrom(targetClass)) { 84 | converter = new VoidOutputConverter(); 85 | } else { 86 | converter = new JsonOutputConverter<>(targetClass); 87 | } 88 | } 89 | 90 | converter.setOutputStream(dataSource.getOutputStream()); 91 | return converter; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/provider/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /** 28 | * The com.gluonhq.connect.provider package contains classes that provide convenience methods to map data 29 | * sources with a data format to give access to instances of {@link com.gluonhq.connect.GluonObservable}. 30 | */ 31 | package com.gluonhq.connect.provider; -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/source/BasicInputDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.source; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | 32 | /** 33 | * An implementation of {@link InputDataSource} that takes any generic {@link java.io.InputStream InputStream} as its 34 | * source. 35 | */ 36 | public class BasicInputDataSource implements InputDataSource { 37 | 38 | private InputStream inputStream; 39 | 40 | /** 41 | * Construct a BasicInputDataSource that uses the given inputStream as its source. 42 | * 43 | * @param inputStream the input stream to use as the source for this input data source 44 | */ 45 | public BasicInputDataSource(InputStream inputStream) { 46 | this.inputStream = inputStream; 47 | } 48 | 49 | @Override 50 | public InputStream getInputStream() throws IOException { 51 | return inputStream; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/source/BasicOutputDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.source; 28 | 29 | import java.io.OutputStream; 30 | 31 | /** 32 | * An implementation of {@link OutputDataSource} that takes any generic{@link java.io.OutputStream OutputStream} as its 33 | * source. 34 | */ 35 | public class BasicOutputDataSource implements OutputDataSource { 36 | 37 | private OutputStream outputStream; 38 | 39 | /** 40 | * Construct a BasicOutputDataSource that uses the given outputStream as its source. 41 | * 42 | * @param outputStream the output stream to use as the source for this output data source 43 | */ 44 | public BasicOutputDataSource(OutputStream outputStream) { 45 | this.outputStream = outputStream; 46 | } 47 | 48 | @Override 49 | public OutputStream getOutputStream() { 50 | return outputStream; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/source/FileDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.source; 28 | 29 | import com.gluonhq.connect.provider.FileClient; 30 | 31 | import java.io.File; 32 | import java.io.FileInputStream; 33 | import java.io.FileOutputStream; 34 | import java.io.IOException; 35 | import java.io.InputStream; 36 | import java.io.OutputStream; 37 | 38 | /** 39 | * An implementation of {@link IODataSource} that can read from and write to a file. 40 | * 41 | *

Attention: it is advised not to use this class directly, but rather construct it by creating a 42 | * {@link FileClient} and build the FileDataSource with the {@link FileClient#createFileDataSource()} method. 43 | */ 44 | public class FileDataSource implements IODataSource { 45 | 46 | private final File file; 47 | 48 | /** 49 | * Create a new FileDataSource instance. The provided file will be used for reading 50 | * from and/or storing data into. 51 | * 52 | * @param file the file to use for reading the data from from or writing the data to 53 | */ 54 | public FileDataSource(File file) { 55 | this.file = file; 56 | } 57 | 58 | /** 59 | * Returns the file that this data source is mapped to. 60 | * 61 | * @return the file that this data source will use for reading and writing data 62 | */ 63 | public File getFile() { 64 | return file; 65 | } 66 | 67 | /** 68 | * Returns an InputStream that is able to read data from the file that was passed in when 69 | * constructing the FileDataSource. 70 | * 71 | * @return an InputStream that is able to read from the file 72 | * @throws IOException when the InputStream on the file could not be created 73 | */ 74 | @Override 75 | public InputStream getInputStream() throws IOException { 76 | return new FileInputStream(file); 77 | } 78 | 79 | /** 80 | * Returns an OutputStream that is able to write data to the file that was passed in when 81 | * constructing the FileDataSource. 82 | * 83 | * @return an OutputStream that is able to write to the file 84 | * @throws IOException when the OutputStream on the file could not be created 85 | */ 86 | @Override 87 | public OutputStream getOutputStream() throws IOException { 88 | return new FileOutputStream(file); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/source/IODataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.source; 28 | 29 | /** 30 | * The IODataSource is a convenience interface that extends from both {@link InputDataSource} and 31 | * {@link OutputDataSource} interfaces. This interface can be used where a data source is required 32 | * that can provide an InputStream as well as an OutputStream. 33 | */ 34 | public interface IODataSource extends InputDataSource, OutputDataSource { 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/source/InputDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.source; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | 32 | /** 33 | * An InputDataSource is a class that returns an InputStream that acts as an input source to read data from. Some 34 | * possible sources can be: a file, a REST URL, a Gluon CloudLink object, ... 35 | */ 36 | public interface InputDataSource { 37 | 38 | /** 39 | * Returns an InputStream that will be used as the source to read data from. 40 | * 41 | * @return an InputStream that is used as the source to read data from 42 | * @throws IOException when an exception occurred while getting the InputStream 43 | */ 44 | InputStream getInputStream() throws IOException; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/source/OutputDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.source; 28 | 29 | import java.io.IOException; 30 | import java.io.OutputStream; 31 | 32 | /** 33 | * An OutputDataSource is a class that returns an OutputStream that acts as an output source to write data to. Some 34 | * possible sources can be: a file, a REST URL, a Gluon Cloud object, ... 35 | */ 36 | public interface OutputDataSource { 37 | 38 | /** 39 | * Returns the OutputStream that will be used as the source to write data to. 40 | * 41 | * @return an OutputStream that is used as the source to write data to 42 | * @throws IOException when an exception occurred while getting the OutputStream 43 | */ 44 | OutputStream getOutputStream() throws IOException; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/connect/source/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /** 28 | * The com.gluonhq.connect.source package contains classes that describe from what sources data can be 29 | * read from or written to. 30 | */ 31 | package com.gluonhq.connect.source; -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/impl/connect/OAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.impl.connect; 28 | 29 | import com.gluonhq.connect.MultiValuedMap; 30 | 31 | import javax.crypto.Mac; 32 | import javax.crypto.SecretKey; 33 | import javax.crypto.spec.SecretKeySpec; 34 | import java.io.UnsupportedEncodingException; 35 | import java.net.URLEncoder; 36 | import java.security.GeneralSecurityException; 37 | import java.util.Base64; 38 | import java.util.List; 39 | import java.util.Map; 40 | import java.util.TreeSet; 41 | import java.util.UUID; 42 | 43 | public class OAuth { 44 | 45 | public static final String SIGNATURE = "oauth_signature"; 46 | public static final String NONCE = "oauth_nonce"; 47 | public static final String VERSION = "oauth_version"; 48 | public static final String CONSUMER_KEY = "oauth_consumer_key"; 49 | public static final String SIGNATURE_METHOD = "oauth_signature_method"; 50 | public static final String TIMESTAMP = "oauth_timestamp"; 51 | 52 | public static String getHeader(String method, String url, 53 | MultiValuedMap requestParams, 54 | String consumerKey, String consumerSecret) 55 | throws UnsupportedEncodingException, GeneralSecurityException { 56 | TreeSet params = new TreeSet(); 57 | for (Map.Entry> entry : requestParams.entrySet()) { 58 | String key = entry.getKey(); 59 | for (String val : entry.getValue()) { 60 | params.add(percentEncode(key) + "=" + percentEncode(val)); 61 | 62 | } 63 | } 64 | String nonce = getNonce(); 65 | params.add(percentEncode(NONCE) + "=" + percentEncode(nonce)); 66 | String version = "1.0"; 67 | params.add(percentEncode(VERSION) + "=" + percentEncode(version)); 68 | String timeStamp = Long.toString(System.currentTimeMillis() / 1000); 69 | params.add(percentEncode(TIMESTAMP) + "=" + percentEncode(timeStamp)); 70 | String signatureMethod = "HMAC-SHA1"; 71 | params.add(percentEncode(SIGNATURE_METHOD) + "=" + percentEncode(signatureMethod)); 72 | params.add(percentEncode(CONSUMER_KEY) + "=" + percentEncode(consumerKey)); 73 | int idx = 0; 74 | int psize = params.size(); 75 | StringBuilder sb = new StringBuilder(); 76 | for (String part : params) { 77 | sb.append(part); 78 | if (++idx < psize) { 79 | sb.append("&"); 80 | } 81 | } 82 | String baseString = method + "&" + percentEncode(url) + "&" + percentEncode(sb.toString()); 83 | String signKey = percentEncode(consumerSecret) + "&"; 84 | String signature = computeSignature(baseString, signKey); 85 | StringBuilder sh = new StringBuilder("OAuth "); 86 | sh.append(percentEncode(SIGNATURE)).append("=\"").append(percentEncode(signature)).append("\""); 87 | sh.append(", "); 88 | sh.append(percentEncode(NONCE)).append("=\"").append(percentEncode(nonce)).append("\""); 89 | sh.append(", "); 90 | sh.append(percentEncode(VERSION)).append("=\"").append(percentEncode(version)).append("\""); 91 | sh.append(", "); 92 | sh.append(percentEncode(CONSUMER_KEY)).append("=\"").append(percentEncode(consumerKey)).append("\""); 93 | sh.append(", "); 94 | sh.append(percentEncode(SIGNATURE_METHOD)).append("=\"").append(percentEncode(signatureMethod)).append("\""); 95 | sh.append(", "); 96 | sh.append(percentEncode(TIMESTAMP)).append("=\"").append(percentEncode(timeStamp)).append("\""); 97 | return sh.toString(); 98 | } 99 | 100 | private static String getNonce() { 101 | return UUID.randomUUID().toString(); 102 | } 103 | 104 | private static String percentEncode(String s) { 105 | if (s == null) { 106 | return ""; 107 | } 108 | try { 109 | return URLEncoder.encode(s, "UTF-8") 110 | .replace("+", "%20").replace("*", "%2A") 111 | .replace("~", "%7E"); 112 | } catch (UnsupportedEncodingException wow) { 113 | throw new RuntimeException(wow.getMessage(), wow); 114 | } 115 | } 116 | 117 | private static String computeSignature(String baseString, String secret) throws GeneralSecurityException, UnsupportedEncodingException { 118 | byte[] sb = secret.getBytes("UTF-8"); 119 | SecretKey secretKey = new SecretKeySpec(sb, "HmacSHA1"); 120 | Mac mac = Mac.getInstance("HmacSHA1"); 121 | mac.init(secretKey); 122 | byte[] text = baseString.getBytes("UTF-8"); 123 | byte[] digest = mac.doFinal(text); 124 | return Base64.getEncoder().encodeToString(digest); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/impl/connect/converter/ClassInspector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.impl.connect.converter; 28 | 29 | import javax.xml.bind.annotation.XmlElement; 30 | import javax.xml.bind.annotation.XmlTransient; 31 | import java.lang.reflect.Method; 32 | import java.lang.reflect.Modifier; 33 | import java.util.Arrays; 34 | import java.util.HashMap; 35 | import java.util.Locale; 36 | import java.util.Map; 37 | 38 | public class ClassInspector { 39 | 40 | private static final Map, ClassInspector> inspectors = new HashMap<>(); 41 | 42 | private final Map, Map> inspectedGetters = new HashMap<>(); 43 | private final Map, Map> inspectedSetters = new HashMap<>(); 44 | 45 | private final Class targetClass; 46 | 47 | public synchronized static ClassInspector resolve(Class targetClass) { 48 | if (inspectors.containsKey(targetClass)) { 49 | return (ClassInspector) inspectors.get(targetClass); 50 | } 51 | 52 | ClassInspector inspector = new ClassInspector<>(targetClass); 53 | inspectors.put(targetClass, inspector); 54 | return inspector; 55 | } 56 | 57 | private ClassInspector(Class targetClass) { 58 | this.targetClass = targetClass; 59 | 60 | resolveProperties(); 61 | } 62 | 63 | public Map getGetters() { 64 | return inspectedGetters.get(targetClass); 65 | } 66 | 67 | public Map getSetters() { 68 | return inspectedSetters.get(targetClass); 69 | } 70 | 71 | private void resolveProperties() { 72 | if (inspectedSetters.containsKey(targetClass)) { 73 | return; 74 | } 75 | Map gettersMappedByPropertyName = new HashMap<>(); 76 | Map settersMappedByPropertyName = new HashMap<>(); 77 | inspectedGetters.put(targetClass, gettersMappedByPropertyName); 78 | inspectedSetters.put(targetClass, settersMappedByPropertyName); 79 | 80 | Method[] methods = targetClass.getMethods(); 81 | 82 | // sort methods array by method name, so getter methods are processed before setter methods 83 | Arrays.sort(methods, (m1, m2) -> m1.getName().compareTo(m2.getName())); 84 | 85 | Map getters = new HashMap<>(); 86 | for (Method method : methods) { 87 | String methodName = method.getName(); 88 | 89 | // check if the method is a getter: 90 | // - is public 91 | // - has no arguments 92 | // - is not annotated with XmlTransient 93 | // - starts with get and returns a non-void or starts with is and returns a boolean 94 | if (Modifier.isPublic(method.getModifiers()) && 95 | method.getParameterTypes().length == 0 && 96 | !method.isAnnotationPresent(XmlTransient.class) && 97 | ((methodName.matches("^get[A-Z].*") && !method.getReturnType().equals(void.class)) || 98 | (methodName.matches("^is[A-Z].*") && method.getReturnType().equals(boolean.class)))) { 99 | String bareMethodName = methodName.startsWith("get") ? methodName.substring(3) : methodName.substring(2); 100 | getters.put(bareMethodName, method); 101 | } 102 | 103 | // check if the method is a setter: 104 | // - is public 105 | // - has exactly one argument 106 | // - is not annotated with XmlTransient 107 | // - starts with set and returns void 108 | // - has a matching getter method 109 | if (Modifier.isPublic(method.getModifiers()) && 110 | method.getParameterTypes().length == 1 && 111 | method.getReturnType().equals(void.class) && 112 | !method.isAnnotationPresent(XmlTransient.class) && 113 | methodName.matches("^set[A-Z].*")) { 114 | String bareMethodName = methodName.substring(3); 115 | Method getter = getters.get(bareMethodName); 116 | if (getter != null) { 117 | String finalName = bareMethodName.substring(0, 1).toLowerCase(Locale.ROOT); 118 | if (bareMethodName.length() > 1) { 119 | finalName += bareMethodName.substring(1); 120 | } 121 | 122 | if (getter.isAnnotationPresent(XmlElement.class) || method.isAnnotationPresent(XmlElement.class)) { 123 | XmlElement xmlElement = getter.isAnnotationPresent(XmlElement.class) ? getter.getAnnotation(XmlElement.class) : method.getAnnotation(XmlElement.class); 124 | String annotatedName = xmlElement.name(); 125 | if (annotatedName != null && !annotatedName.isEmpty()) { 126 | finalName = annotatedName; 127 | } 128 | } 129 | 130 | gettersMappedByPropertyName.put(finalName, getter); 131 | settersMappedByPropertyName.put(finalName, method); 132 | } 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/impl/connect/converter/JsonUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.impl.connect.converter; 28 | 29 | import javax.json.Json; 30 | import javax.json.JsonReader; 31 | import javax.json.JsonReaderFactory; 32 | import java.io.BufferedReader; 33 | import java.io.IOException; 34 | import java.io.InputStream; 35 | import java.io.InputStreamReader; 36 | import java.io.Reader; 37 | import java.io.StringReader; 38 | import java.util.logging.Level; 39 | import java.util.logging.Logger; 40 | 41 | /** 42 | * A utility class that provides useful methods when working with JSON data. 43 | */ 44 | public class JsonUtil { 45 | 46 | private static final Logger LOG = Logger.getLogger(JsonUtil.class.getName()); 47 | 48 | private static final JsonReaderFactory readerFactory = Json.createReaderFactory(null); 49 | 50 | /** 51 | * Create a JsonReader from the specified InputStream. When the logging level for this class is set 52 | * to {@link Level#FINE}, the JSON content of the InputStream will be written to a String and logged. Otherwise, 53 | * it will just create a JsonReader from a basic InputStreamReader. 54 | * @param input the InputStream to read the JSON data from 55 | * @return a JsonReader to read the data from the InputStream 56 | */ 57 | public static JsonReader createJsonReader(InputStream input) { 58 | Reader sourceReader; 59 | if (LOG.isLoggable(Level.FINE)) { 60 | String string; 61 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"))) { 62 | StringBuilder stringBuilder = new StringBuilder(); 63 | String line; 64 | while ((line = reader.readLine()) != null) { 65 | stringBuilder.append(line); 66 | } 67 | string = stringBuilder.toString(); 68 | sourceReader = new StringReader(string); 69 | 70 | LOG.fine("Read JSON data: " + string); 71 | } catch (IOException ex) { 72 | LOG.log(Level.SEVERE, "Something went wrong while reading plain text from inputstream.", ex); 73 | return null; 74 | } 75 | } else { 76 | sourceReader = new InputStreamReader(input); 77 | } 78 | 79 | return readerFactory.createReader(sourceReader); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/impl/connect/event/ConnectEventDispatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.impl.connect.event; 28 | 29 | import javafx.event.Event; 30 | import javafx.event.EventDispatchChain; 31 | import javafx.event.EventDispatcher; 32 | import javafx.event.EventHandler; 33 | import javafx.event.EventType; 34 | 35 | import java.util.HashMap; 36 | import java.util.Map; 37 | 38 | /** 39 | * An {@code EventDispatcher} which handles {@link com.gluonhq.connect.ConnectStateEvent}'s 40 | * registration and when used in an event dispatch chain it forwards the received 41 | * events to the appropriate registered handlers. 42 | */ 43 | public class ConnectEventDispatcher implements EventDispatcher { 44 | 45 | private final Map, ConnectEventHandler> eventHandlerMap; 46 | private final Object eventSource; 47 | 48 | public ConnectEventDispatcher(Object eventSource) { 49 | this.eventSource = eventSource; 50 | eventHandlerMap = new HashMap<>(); 51 | } 52 | 53 | @Override 54 | public Event dispatchEvent(Event event, EventDispatchChain tail) { 55 | event = dispatchCapturingEvent((T) event); 56 | if (event.isConsumed()) { 57 | return null; 58 | } 59 | event = tail.dispatchEvent(event); 60 | if (event != null) { 61 | event = dispatchBubblingEvent((T) event); 62 | if (event.isConsumed()) { 63 | return null; 64 | } 65 | } 66 | return event; 67 | } 68 | 69 | /** 70 | * Sets the specified singleton handler. There can only be one such handler 71 | * specified at a time. 72 | * 73 | * @param eventType the event type to associate with the given eventHandler 74 | * @param eventHandler the handler to register, or null to unregister 75 | * @throws NullPointerException if the event type is null 76 | */ 77 | public final void setEventHandler(final EventType eventType, final EventHandler eventHandler) { 78 | validateEventType(eventType); 79 | 80 | ConnectEventHandler dialogEventHandler = eventHandlerMap.get(eventType); 81 | 82 | if (dialogEventHandler == null) { 83 | if (eventHandler == null) { 84 | return; 85 | } 86 | dialogEventHandler = new ConnectEventHandler<>(); 87 | eventHandlerMap.put(eventType, dialogEventHandler); 88 | } 89 | 90 | dialogEventHandler.setEventHandler(eventHandler); 91 | } 92 | 93 | public final Event dispatchCapturingEvent(T event) { 94 | EventType eventType = (EventType) event.getEventType(); 95 | do { 96 | event = dispatchCapturingEvent(eventType, event); 97 | eventType = (EventType) eventType.getSuperType(); 98 | } while (eventType != null); 99 | 100 | return event; 101 | } 102 | 103 | public final Event dispatchBubblingEvent(T event) { 104 | EventType eventType = (EventType) event.getEventType(); 105 | do { 106 | event = dispatchBubblingEvent(eventType, event); 107 | eventType = (EventType) eventType.getSuperType(); 108 | } while (eventType != null); 109 | 110 | return event; 111 | } 112 | 113 | private T dispatchCapturingEvent(final EventType handlerType, T event) { 114 | final ConnectEventHandler compositeEventHandler = eventHandlerMap.get(handlerType); 115 | 116 | if (compositeEventHandler != null) { 117 | event = fixEventSource(event, eventSource); 118 | compositeEventHandler.dispatchCapturingEvent(event); 119 | } 120 | return event; 121 | } 122 | 123 | private T dispatchBubblingEvent(final EventType handlerType, T event) { 124 | final ConnectEventHandler compositeEventHandler = eventHandlerMap.get(handlerType); 125 | 126 | if (compositeEventHandler != null) { 127 | event = fixEventSource(event, eventSource); 128 | compositeEventHandler.dispatchBubblingEvent(event); 129 | } 130 | 131 | return event; 132 | } 133 | 134 | private T fixEventSource(final T event, final Object eventSource) { 135 | return (event.getSource() != eventSource) ? (T) event.copyFor(eventSource, event.getTarget()) : event; 136 | } 137 | 138 | private static void validateEventType(final EventType eventType) { 139 | if (eventType == null) { 140 | throw new NullPointerException("Event type must not be null"); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/gluonhq/impl/connect/event/ConnectEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.impl.connect.event; 28 | 29 | import javafx.event.Event; 30 | import javafx.event.EventHandler; 31 | 32 | public final class ConnectEventHandler { 33 | 34 | private EventProcessorRecord firstRecord; 35 | private EventProcessorRecord lastRecord; 36 | 37 | private EventHandler eventHandler; 38 | 39 | public void setEventHandler(final EventHandler eventHandler) { 40 | this.eventHandler = eventHandler; 41 | } 42 | 43 | public EventHandler getEventHandler() { 44 | return eventHandler; 45 | } 46 | 47 | public void dispatchBubblingEvent(final Event event) { 48 | final T specificEvent = (T) event; 49 | 50 | EventProcessorRecord record = firstRecord; 51 | while (record != null) { 52 | if (record.isDisconnected()) { 53 | remove(record); 54 | } else { 55 | record.handleBubblingEvent(specificEvent); 56 | } 57 | record = record.nextRecord; 58 | } 59 | 60 | if (eventHandler != null) { 61 | eventHandler.handle(specificEvent); 62 | } 63 | } 64 | 65 | public void dispatchCapturingEvent(final Event event) { 66 | final T specificEvent = (T) event; 67 | 68 | EventProcessorRecord record = firstRecord; 69 | while (record != null) { 70 | if (record.isDisconnected()) { 71 | remove(record); 72 | } else { 73 | record.handleCapturingEvent(specificEvent); 74 | } 75 | record = record.nextRecord; 76 | } 77 | } 78 | 79 | private void remove(final EventProcessorRecord record) { 80 | final EventProcessorRecord prevRecord = record.prevRecord; 81 | final EventProcessorRecord nextRecord = record.nextRecord; 82 | 83 | if (prevRecord != null) { 84 | prevRecord.nextRecord = nextRecord; 85 | } else { 86 | firstRecord = nextRecord; 87 | } 88 | 89 | if (nextRecord != null) { 90 | nextRecord.prevRecord = prevRecord; 91 | } else { 92 | lastRecord = prevRecord; 93 | } 94 | } 95 | 96 | private static abstract class EventProcessorRecord { 97 | private EventProcessorRecord nextRecord; 98 | private EventProcessorRecord prevRecord; 99 | 100 | public abstract boolean stores(EventHandler eventProcessor, 101 | boolean isFilter); 102 | 103 | public abstract void handleBubblingEvent(T event); 104 | 105 | public abstract void handleCapturingEvent(T event); 106 | 107 | public abstract boolean isDisconnected(); 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, 2020 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /** 29 | * Defines APIs to simplify data-binding between JavaFX controls and any data-source. 30 | */ 31 | module com.gluonhq.connect { 32 | requires java.json; 33 | requires java.logging; 34 | requires java.xml.bind; 35 | 36 | requires javafx.graphics; 37 | 38 | exports com.gluonhq.connect; 39 | exports com.gluonhq.connect.converter; 40 | exports com.gluonhq.connect.provider; 41 | exports com.gluonhq.connect.source; 42 | } -------------------------------------------------------------------------------- /src/test/java/com/gluonhq/connect/HttpServerManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect; 28 | 29 | import io.vertx.core.Handler; 30 | import io.vertx.core.Vertx; 31 | import io.vertx.core.http.HttpServer; 32 | import io.vertx.core.http.HttpServerRequest; 33 | 34 | import java.util.ArrayList; 35 | import java.util.HashMap; 36 | import java.util.List; 37 | import java.util.Map; 38 | import java.util.concurrent.CountDownLatch; 39 | import java.util.concurrent.TimeUnit; 40 | import java.util.concurrent.TimeoutException; 41 | 42 | public class HttpServerManager implements AutoCloseable { 43 | 44 | private HttpServer httpServer; 45 | private List requests = new ArrayList<>(); 46 | 47 | public void startHttpServer(Handler requestHandler) throws InterruptedException, TimeoutException { 48 | CountDownLatch latch = new CountDownLatch(1); 49 | httpServer = Vertx.vertx().createHttpServer(); 50 | httpServer.requestHandler(new RequestHandlerWrapper(requestHandler)); 51 | httpServer.listen(45000, asyncResult -> { 52 | if (asyncResult.failed()) { 53 | asyncResult.cause().printStackTrace(); 54 | } 55 | latch.countDown(); 56 | }); 57 | 58 | if (!latch.await(10, TimeUnit.SECONDS)) { 59 | throw new TimeoutException("HttpServer could not be started in time."); 60 | } 61 | } 62 | 63 | @Override 64 | public void close() { 65 | if (httpServer != null) { 66 | httpServer.close(); 67 | } 68 | } 69 | 70 | public void verify(HttpRequest request, long times) { 71 | long count = requests.stream().filter(request::matches).count(); 72 | if (times != count) { 73 | throw new AssertionError("Request must be called exactly " + times + " times, but was called " + count + " times instead."); 74 | } 75 | } 76 | 77 | private class RequestHandlerWrapper implements Handler { 78 | 79 | private Handler handler; 80 | 81 | RequestHandlerWrapper(Handler handler) { 82 | this.handler = handler; 83 | } 84 | 85 | @Override 86 | public void handle(HttpServerRequest request) { 87 | requests.add(request); 88 | handler.handle(request); 89 | } 90 | } 91 | 92 | public static class HttpRequest { 93 | 94 | private String method; 95 | private Map headers = new HashMap<>(); 96 | 97 | public HttpRequest withMethod(String method) { 98 | this.method = method; 99 | return this; 100 | } 101 | 102 | public HttpRequest withHeader(String header, String value) { 103 | this.headers.put(header, value); 104 | return this; 105 | } 106 | 107 | boolean matches(HttpServerRequest request) { 108 | return (this.method == null || this.method.equals(request.rawMethod())) && 109 | headers.entrySet().stream().allMatch(e -> request.getHeader(e.getKey()).equals(e.getValue())); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/test/java/com/gluonhq/connect/converter/JsonConverterMathBigTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import org.testng.annotations.Test; 30 | 31 | import javax.json.Json; 32 | import javax.json.JsonObject; 33 | import java.math.BigDecimal; 34 | import java.math.BigInteger; 35 | 36 | import static org.testng.Assert.assertEquals; 37 | import static org.testng.Assert.assertTrue; 38 | 39 | public class JsonConverterMathBigTest { 40 | 41 | @Test 42 | public void readBigDecimalField() { 43 | JsonObject jsonObject = Json.createObjectBuilder().add("bigDecimal", new BigDecimal(-24.21021)).build(); 44 | 45 | JsonConverter jsonConverter = new JsonConverter<>(ClassWithBigDecimalField.class); 46 | ClassWithBigDecimalField object = jsonConverter.readFromJson(jsonObject); 47 | assertEquals(object.getBigDecimal(), new BigDecimal(-24.21021)); 48 | } 49 | 50 | @Test 51 | public void writeBigDecimalField() { 52 | ClassWithBigDecimalField object = new ClassWithBigDecimalField(); 53 | object.setBigDecimal(new BigDecimal(547893.3137490854)); 54 | 55 | JsonConverter jsonConverter = new JsonConverter<>(ClassWithBigDecimalField.class); 56 | JsonObject jsonObject = jsonConverter.writeToJson(object); 57 | assertTrue(jsonObject.containsKey("bigDecimal")); 58 | assertEquals(jsonObject.getJsonNumber("bigDecimal").bigDecimalValue(), new BigDecimal(547893.3137490854)); 59 | } 60 | 61 | @Test 62 | public void readBigIntegerField() { 63 | JsonObject jsonObject = Json.createObjectBuilder().add("bigInteger", new BigInteger("84132514497684153649768137548986169814")).build(); 64 | 65 | JsonConverter jsonConverter = new JsonConverter<>(ClassWithBigIntegerField.class); 66 | ClassWithBigIntegerField object = jsonConverter.readFromJson(jsonObject); 67 | assertEquals(object.getBigInteger(), new BigInteger("84132514497684153649768137548986169814")); 68 | } 69 | 70 | @Test 71 | public void writeBigIntegerField() { 72 | ClassWithBigIntegerField object = new ClassWithBigIntegerField(); 73 | object.setBigInteger(new BigInteger("57486575406257840165894267426524656554057289574")); 74 | 75 | JsonConverter jsonConverter = new JsonConverter<>(ClassWithBigIntegerField.class); 76 | JsonObject jsonObject = jsonConverter.writeToJson(object); 77 | assertTrue(jsonObject.containsKey("bigInteger")); 78 | assertEquals(jsonObject.getJsonNumber("bigInteger").bigIntegerValue(), new BigInteger("57486575406257840165894267426524656554057289574")); 79 | } 80 | 81 | public static final class ClassWithBigDecimalField { 82 | 83 | private BigDecimal bigDecimal; 84 | 85 | public BigDecimal getBigDecimal() { 86 | return bigDecimal; 87 | } 88 | 89 | public void setBigDecimal(BigDecimal bigDecimal) { 90 | this.bigDecimal = bigDecimal; 91 | } 92 | } 93 | 94 | public static final class ClassWithBigIntegerField { 95 | 96 | private BigInteger bigInteger; 97 | 98 | public BigInteger getBigInteger() { 99 | return bigInteger; 100 | } 101 | 102 | public void setBigInteger(BigInteger bigInteger) { 103 | this.bigInteger = bigInteger; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/test/java/com/gluonhq/connect/converter/StringInputConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.converter; 28 | 29 | import org.testng.annotations.Test; 30 | 31 | import java.io.ByteArrayInputStream; 32 | import java.nio.charset.StandardCharsets; 33 | 34 | import static org.testng.Assert.assertEquals; 35 | 36 | public class StringInputConverterTest { 37 | 38 | @Test 39 | public void readFromString() { 40 | String string = "ABCD 0123"; 41 | 42 | StringInputConverter converter = new StringInputConverter(); 43 | 44 | converter.setInputStream(new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8))); 45 | 46 | String readString = converter.read(); 47 | assertEquals(readString, string); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/gluonhq/connect/provider/RestClientContentTypeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.provider; 28 | 29 | import com.gluonhq.connect.HttpServerManager; 30 | import com.gluonhq.connect.converter.StringInputConverter; 31 | import com.gluonhq.connect.converter.StringOutputConverter; 32 | import com.gluonhq.connect.source.RestDataSource; 33 | import org.testng.annotations.Test; 34 | 35 | import java.io.IOException; 36 | import java.util.concurrent.TimeoutException; 37 | 38 | import static org.testng.Assert.assertEquals; 39 | 40 | public class RestClientContentTypeTest { 41 | 42 | @Test 43 | public void testCustomContentTypeWithPost() throws InterruptedException, IOException, TimeoutException { 44 | try (HttpServerManager httpServerManager = new HttpServerManager()){ 45 | httpServerManager.startHttpServer(request -> { 46 | if (request.path().equals("/jsonBody")) { 47 | request.response().setStatusCode(200).end("OK"); 48 | } 49 | }); 50 | 51 | RestDataSource restDataSource = RestClient.create() 52 | .method("POST") 53 | .host("http://localhost:45000") 54 | .path("jsonBody") 55 | .contentType("application/json") 56 | .createRestDataSource(); 57 | 58 | StringOutputConverter outputConverter = new StringOutputConverter(); 59 | outputConverter.setOutputStream(restDataSource.getOutputStream()); 60 | outputConverter.write("{\"body\":\"json\"}"); 61 | 62 | StringInputConverter inputConverter = new StringInputConverter(); 63 | inputConverter.setInputStream(restDataSource.getInputStream()); 64 | String readString = inputConverter.read(); 65 | assertEquals(readString, "OK"); 66 | 67 | httpServerManager.verify(new HttpServerManager.HttpRequest() 68 | .withMethod("POST") 69 | .withHeader("content-type", "application/json"), 1); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/gluonhq/connect/source/RestDataSourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018 Gluon 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Gluon, any associated website, nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL GLUON BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package com.gluonhq.connect.source; 28 | 29 | import com.gluonhq.connect.HttpServerManager; 30 | import com.gluonhq.connect.converter.StringInputConverter; 31 | import com.gluonhq.connect.provider.RestClient; 32 | import org.testng.annotations.Test; 33 | 34 | import java.io.IOException; 35 | import java.util.concurrent.TimeoutException; 36 | 37 | import static org.testng.Assert.assertEquals; 38 | 39 | public class RestDataSourceTest { 40 | 41 | @Test 42 | public void testEmptyResponse() throws IOException, InterruptedException, TimeoutException { 43 | try (HttpServerManager httpServerManager = new HttpServerManager()) { 44 | httpServerManager.startHttpServer(request -> { 45 | request.response() 46 | .setStatusCode(200) 47 | .end(""); 48 | }); 49 | 50 | RestDataSource restDataSource = RestClient.create() 51 | .host("http://localhost:45000") 52 | .path("empty") 53 | .createRestDataSource(); 54 | 55 | StringInputConverter converter = new StringInputConverter(); 56 | converter.setInputStream(restDataSource.getInputStream()); 57 | String readString = converter.read(); 58 | 59 | assertEquals(readString, ""); 60 | } 61 | } 62 | } 63 | --------------------------------------------------------------------------------