Repository: geode-examples Updated Branches: refs/heads/master 6d6326968 -> 7aacbd04a
GEODE-2260 Add content from develop branch of Geode repo. Project: http://git-wip-us.apache.org/repos/asf/geode-examples/repo Commit: http://git-wip-us.apache.org/repos/asf/geode-examples/commit/7aacbd04 Tree: http://git-wip-us.apache.org/repos/asf/geode-examples/tree/7aacbd04 Diff: http://git-wip-us.apache.org/repos/asf/geode-examples/diff/7aacbd04 Branch: refs/heads/master Commit: 7aacbd04a3856b36d173dd1b427d1836454dff69 Parents: 6d63269 Author: Karen Miller <[email protected]> Authored: Fri Dec 30 13:36:11 2016 -0800 Committer: Karen Miller <[email protected]> Committed: Fri Dec 30 13:36:11 2016 -0800 ---------------------------------------------------------------------- README.md | 74 ++++++++- build.gradle | 59 +++++++ gradle.properties | 21 +++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53639 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 160 ++++++++++++++++++ gradlew.bat | 90 ++++++++++ replicated/.gitignore | 2 + replicated/README.md | 45 +++++ replicated/build.gradle | 20 +++ replicated/scripts/.gitignore | 2 + replicated/scripts/pidkiller.sh | 35 ++++ replicated/scripts/setEnv.sh | 33 ++++ replicated/scripts/startAll.sh | 45 +++++ replicated/scripts/stopAll.sh | 28 ++++ .../geode/examples/replicated/BaseClient.java | 63 +++++++ .../geode/examples/replicated/Consumer.java | 40 +++++ .../geode/examples/replicated/Producer.java | 40 +++++ replicated/src/main/main2.iml | 6 + .../geode/examples/replicated/ConsumerTest.java | 71 ++++++++ .../geode/examples/replicated/ProducerTest.java | 70 ++++++++ .../examples/replicated/ReplicatedTest.java | 164 +++++++++++++++++++ replicated/src/test/test5.iml | 6 + settings.gradle | 21 +++ .../apache/geode/example/utils/ShellUtil.java | 106 ++++++++++++ utils/src/main/main5.iml | 6 + 26 files changed, 1210 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/README.md ---------------------------------------------------------------------- diff --git a/README.md b/README.md index 29b8fd4..6266603 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,72 @@ -Initial README.md file for the geode-examples repository. +# Apache Geode examples -To be replaced right away by existing README.md file from the -Apache Geode repository. +This is the home of Apache Geode examples that are bundled with the project. Contributions<sup>[2]</sup> and corrections are welcome. Please talk to us about your suggestions at [[email protected]](mailto:[email protected]) or submit a [pull request](https://github.com/apache/geode/pull/new/develop). + +## Example requirements + +All examples: + +* Need to be testable. Use unit tests, integration tests or whatever is applicable. Tests will run through the project's CI. +* Should be `Gradle` projects or part of existing ones. There may be exceptions here, but the community should have a consensus to accept. +* Have to follow code format & style from Apache Geode <sup>[1]</sup> guidelines. +* Should contain a `README.md` file with step-by-step instruction on how to set up and run the example. *Diagrams give you extra credit.* +* Donations need to be licensed through ASL 2.0 and contributors need to file an ICLA<sup>[3]</sup>. + +## Structure + +### Installation and a Tutorial for Beginners + +* [How to Install](http://geode.apache.org/docs/guide/getting_started/installation/install_standalone.html) +* Set a `GEODE_HOME` environment variable to point to the root directory of the installation; this directory contains `bin/`. For those that have built from source, it will be the `geode-assembly/build/install/apache-geode` directory. +* If desired run the tutorial: [Apache Geode in 15 minutes or Less](http://geode.apache.org/docs/guide/getting_started/15_minute_quickstart_gfsh.html) + +### Basics + +* [Replicated Region](replicated) +* Partitioned Region +* Persistence +* OQL (Querying) + +### Intermediate + +* PDX & Serialization +* Lucene Indexing +* OQL Indexing +* Functions +* CacheLoader & CacheWriter +* Listeners +* Async Event Queues +* Continuous Querying +* Transactions +* Eviction +* Expiration +* Overflow +* Security +* Off-heap + +### Advanced + +* WAN Gateway +* Durable subscriptions +* Delta propagation +* Network partition detection +* D-lock +* Compression +* Resource manager +* PDX Advanced + +### Use cases, integrations and external examples + +This section has self-contained little projects that illustrate a use case or an integration with other projects. + +* SpringBoot Application +* HTTP Session replication +* Redis +* Memcached +* Spark Connector + +## References + +- [1] [https://cwiki.apache.org/confluence/display/GEODE/Criteria+for+Code+Submissions](https://cwiki.apache.org/confluence/display/GEODE/Criteria+for+Code+Submissions) +- [2] [https://cwiki.apache.org/confluence/display/GEODE/How+to+Contribute](https://cwiki.apache.org/confluence/display/GEODE/How+to+Contribute) +- [3] [http://www.apache.org/licenses/#clas](http://www.apache.org/licenses/#clas) http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..1e638bc --- /dev/null +++ b/build.gradle @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +subprojects { + + apply plugin:'java' + + repositories { + mavenLocal() + maven { + url "https://repository.apache.org/content/repositories/snapshots/" + } + mavenCentral() + } + + dependencies { + testCompile project(":utils") + compile "org.apache.geode:geode-core:$geodeVersion" + testCompile "junit:junit:$junitVersion" + testCompile "org.mockito:mockito-core:$mockitocoreVersion" + compile "org.apache.commons:commons-exec:$commonsExecVersion" + compile "com.jayway.awaitility:awaitility:$awaitilityVersion" + } + + task run(type: JavaExec) { + description = 'Run example' + def mainClass = rootProject.hasProperty('main') ? "${rootProject.getProperty('main')}" : 'Main' + main = "org.apache.geode.examples.${project.name}.$mainClass" + classpath = sourceSets.main.runtimeClasspath + standardInput = System.in + systemProperties = System.getProperties() + if (rootProject.hasProperty('args')) { + args = ["${rootProject.getProperty('args')}"] + } + } + + test { + def geodeHome = System.getenv('GEODE_HOME'); + geodeHome = geodeHome != null ? geodeHome : file('../../geode-assembly/build/install/apache-geode/').absolutePath + environment 'GEODE_HOME': geodeHome + } + + +} + http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/gradle.properties ---------------------------------------------------------------------- diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..c1739af --- /dev/null +++ b/gradle.properties @@ -0,0 +1,21 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +geodeVersion = 1.0.0-incubating +junitVersion = 4.12 +mockitocoreVersion = 1.10.19 +commonsExecVersion = 1.3 +awaitilityVersion = 1.7.0 http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/gradle/wrapper/gradle-wrapper.jar ---------------------------------------------------------------------- diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..2c6137b Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/gradle/wrapper/gradle-wrapper.properties ---------------------------------------------------------------------- diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..6132c99 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Jun 20 23:30:08 PDT 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/gradlew ---------------------------------------------------------------------- diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..9d82f78 --- /dev/null +++ b/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/gradlew.bat ---------------------------------------------------------------------- diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..5f19212 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/.gitignore ---------------------------------------------------------------------- diff --git a/replicated/.gitignore b/replicated/.gitignore new file mode 100644 index 0000000..b858ea8 --- /dev/null +++ b/replicated/.gitignore @@ -0,0 +1,2 @@ +server*/* +locator*/* http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/README.md ---------------------------------------------------------------------- diff --git a/replicated/README.md b/replicated/README.md new file mode 100644 index 0000000..ea923dd --- /dev/null +++ b/replicated/README.md @@ -0,0 +1,45 @@ +# Geode replicated region example + +This is one of the most basic examples. +Two servers host a replicated region. +The producer puts 50 entries into the replicated region. The consumer prints the number of entries in the region. + +## Steps +1. From the ```geode-examples/replicated``` directory, start the locator and two servers: + + $ scripts/startAll.sh + +2. Run the producer: + + $ gradle run -Pmain=Producer + ... + ... + INFO: Done. Inserted 50 entries. + +3. Run the consumer: + + $ gradle run -Pmain=Consumer + ... + ... + INFO: Done. 50 entries available on the server(s). + +4. Kill one of the servers: + + $ gfsh + ... + gfsh>connect + gfsh>stop server --name=server1 + gfsh>quit + +5. Run the consumer a second time, and notice that all the entries are still available due to replication: + + $ gradle run -Pmain=Consumer + ... + ... + INFO: Done. 50 entries available on the server(s). + +6. Shutdown the system: + + $ scripts/stopAll.sh + +This example is a simple demonstration on basic APIs of Geode, as well how to write tests using mocks for Geode applications. http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/build.gradle ---------------------------------------------------------------------- diff --git a/replicated/build.gradle b/replicated/build.gradle new file mode 100644 index 0000000..52283ec --- /dev/null +++ b/replicated/build.gradle @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +sourceSets.test { + resources.srcDirs = ["${projectDir}/scripts"] +} http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/scripts/.gitignore ---------------------------------------------------------------------- diff --git a/replicated/scripts/.gitignore b/replicated/scripts/.gitignore new file mode 100644 index 0000000..32f8870 --- /dev/null +++ b/replicated/scripts/.gitignore @@ -0,0 +1,2 @@ +locator1/ +server*/ http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/scripts/pidkiller.sh ---------------------------------------------------------------------- diff --git a/replicated/scripts/pidkiller.sh b/replicated/scripts/pidkiller.sh new file mode 100755 index 0000000..ecf8f2d --- /dev/null +++ b/replicated/scripts/pidkiller.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @brief Script that look for .pid files on a directory and kill those processes. +# + +export DIR=$1 + +if [ $# -eq 0 ] + then + echo "No arguments supplied. Script needs directory to look for pid files." + exit 1 +fi + +for pid in `find $DIR -name "*.pid"` +do + echo "Found: $pid" + kill -9 `cat $pid` + echo "Killed." +done + http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/scripts/setEnv.sh ---------------------------------------------------------------------- diff --git a/replicated/scripts/setEnv.sh b/replicated/scripts/setEnv.sh new file mode 100755 index 0000000..e9e860e --- /dev/null +++ b/replicated/scripts/setEnv.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +## check if locator port has been set otherwise set to default +export GEODE_LOCATOR_PORT="${GEODE_LOCATOR_PORT:-10334}" + +## check if GEODE_HOME has been set +: ${GEODE_HOME?"GEODE_HOME enviroment variable needs to be set"} + +## check if gfsh script is accessible and print version +: ${GEODE_HOME/bin/gfsh?"gfsh doesn't seem to be available. Please check $GEODE_HOME"} +echo "Geode version: `$GEODE_HOME/bin/gfsh version`" + +## prefer GEODE_HOME for finding gfsh +export PATH=$GEODE_HOME/bin:$PATH + + +: ${GEODE_LOCATOR_PORT?} http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/scripts/startAll.sh ---------------------------------------------------------------------- diff --git a/replicated/scripts/startAll.sh b/replicated/scripts/startAll.sh new file mode 100755 index 0000000..2b08f19 --- /dev/null +++ b/replicated/scripts/startAll.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set -e + +current=`pwd` + +cd `dirname $0` + +. ./setEnv.sh + +cd $current + +#export GEODE_LOCATOR_PORT="${GEODE_LOCATOR_PORT:-10334}" +# start a locator +gfsh start locator --name=locator1 --mcast-port=0 --port=${GEODE_LOCATOR_PORT} + +# start 2 servers on a random available port +for N in {1..2} +do + gfsh start server --locators=localhost[${GEODE_LOCATOR_PORT}] --name=server$N --server-port=0 --mcast-port=0 +done + +# create a region using GFSH +gfsh -e "connect --locator=localhost[${GEODE_LOCATOR_PORT}]" -e "create region --name=myRegion --type=REPLICATE" + +gfsh -e "connect --locator=localhost[${GEODE_LOCATOR_PORT}]" -e "list members" + +exit 0 + http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/scripts/stopAll.sh ---------------------------------------------------------------------- diff --git a/replicated/scripts/stopAll.sh b/replicated/scripts/stopAll.sh new file mode 100755 index 0000000..a6364a8 --- /dev/null +++ b/replicated/scripts/stopAll.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +set -e + +current=`pwd` + +cd `dirname $0` + +. ./setEnv.sh + +cd $current + +gfsh -e "connect --locator=localhost[${GEODE_LOCATOR_PORT}]" -e "shutdown --include-locators=true" http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/src/main/java/org/apache/geode/examples/replicated/BaseClient.java ---------------------------------------------------------------------- diff --git a/replicated/src/main/java/org/apache/geode/examples/replicated/BaseClient.java b/replicated/src/main/java/org/apache/geode/examples/replicated/BaseClient.java new file mode 100644 index 0000000..3e656f6 --- /dev/null +++ b/replicated/src/main/java/org/apache/geode/examples/replicated/BaseClient.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.examples.replicated; + +import java.util.logging.Logger; + +import org.apache.geode.cache.Region; +import org.apache.geode.cache.client.ClientCache; +import org.apache.geode.cache.client.ClientCacheFactory; +import org.apache.geode.cache.client.ClientRegionShortcut; + + +public abstract class BaseClient { + + static final Logger logger = Logger.getAnonymousLogger(); + protected ClientCache clientCache; + + protected void setRegion(Region region) { + this.region = region; + } + + private Region region; + private final String locatorHost = System.getProperty("GEODE_LOCATOR_HOST", "localhost"); + private final int locatorPort = Integer.getInteger("GEODE_LOCATOR_PORT", 10334); + protected static final String REGION_NAME = "myRegion"; + static final int NUM_ENTRIES = 50; + + public BaseClient() { + this.clientCache = getClientCache(); + } + + protected Region getRegion() { + if (region == null) { + region = getClientCache() + .<String, String>createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY) + .create(REGION_NAME); + } + return region; + } + + protected ClientCache getClientCache() { + if (clientCache == null) { + clientCache = new ClientCacheFactory().addPoolLocator(locatorHost, locatorPort) + .set("log-level", "WARN") + .create(); + } + return clientCache; + } +} http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/src/main/java/org/apache/geode/examples/replicated/Consumer.java ---------------------------------------------------------------------- diff --git a/replicated/src/main/java/org/apache/geode/examples/replicated/Consumer.java b/replicated/src/main/java/org/apache/geode/examples/replicated/Consumer.java new file mode 100644 index 0000000..7954bb5 --- /dev/null +++ b/replicated/src/main/java/org/apache/geode/examples/replicated/Consumer.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.examples.replicated; + +import org.apache.geode.cache.client.ClientCache; + +public class Consumer extends BaseClient { + + public static void main(String[] args) { + new Consumer().countEntriesOnServer(); + } + + public Consumer() { + } + + public Consumer(ClientCache clientCache) { + this.clientCache = clientCache; + } + + public int countEntriesOnServer() { + int size = getRegion().keySetOnServer().size(); + logger.info(String.format("Done. %d entries available on the server(s).", size)); + return size; + } + +} http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/src/main/java/org/apache/geode/examples/replicated/Producer.java ---------------------------------------------------------------------- diff --git a/replicated/src/main/java/org/apache/geode/examples/replicated/Producer.java b/replicated/src/main/java/org/apache/geode/examples/replicated/Producer.java new file mode 100644 index 0000000..79d5dfe --- /dev/null +++ b/replicated/src/main/java/org/apache/geode/examples/replicated/Producer.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.examples.replicated; + +import org.apache.geode.cache.client.ClientCache; + +public class Producer extends BaseClient { + + public static void main(String[] args) { + new Producer().populateRegion(); + } + + public Producer() { + } + + public Producer(ClientCache clientCache) { + this.clientCache = clientCache; + } + + public void populateRegion() { + for (int i=0; i < NUM_ENTRIES; i++) { + getRegion().put(i, "value" + i); + } + logger.info("Done. Inserted " + NUM_ENTRIES + " entries."); + } +} http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/src/main/main2.iml ---------------------------------------------------------------------- diff --git a/replicated/src/main/main2.iml b/replicated/src/main/main2.iml new file mode 100644 index 0000000..19dbd15 --- /dev/null +++ b/replicated/src/main/main2.iml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="false"> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/src/test/java/org/apache/geode/examples/replicated/ConsumerTest.java ---------------------------------------------------------------------- diff --git a/replicated/src/test/java/org/apache/geode/examples/replicated/ConsumerTest.java b/replicated/src/test/java/org/apache/geode/examples/replicated/ConsumerTest.java new file mode 100644 index 0000000..2fab508 --- /dev/null +++ b/replicated/src/test/java/org/apache/geode/examples/replicated/ConsumerTest.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.geode.examples.replicated; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.Set; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.apache.geode.cache.Region; +import org.apache.geode.cache.client.ClientCache; +import org.apache.geode.cache.client.NoAvailableLocatorsException; + +public class ConsumerTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private Consumer consumer; + private ClientCache clientCache = mock(ClientCache.class); + private Region region = mock(Region.class); + private Set keys = mock(Set.class); + + @Before + public void setup() { + when(region.getName()).thenReturn(Consumer.REGION_NAME); + when(keys.size()).thenReturn(Consumer.NUM_ENTRIES); + when(region.keySetOnServer()).thenReturn(keys); + when(clientCache.getRegion(any())).thenReturn(region); + consumer = new Consumer(clientCache); + consumer.setRegion(region); + } + + @Test + public void numberOfEntriesOnServerShouldMatchConsumerEntries() throws Exception { + assertEquals(consumer.NUM_ENTRIES, consumer.countEntriesOnServer()); + } + + @Test + public void numberOfEntriesShouldBeGreaterThanZero() throws Exception { + assertTrue(consumer.NUM_ENTRIES > 0); + } + + @Test + public void countingEntriesWithoutConnectionShouldThrowNoAvailableLocatorsException() throws Exception { + consumer = new Consumer(); + expectedException.expect(NoAvailableLocatorsException.class); + assertEquals(consumer.NUM_ENTRIES, consumer.countEntriesOnServer()); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/src/test/java/org/apache/geode/examples/replicated/ProducerTest.java ---------------------------------------------------------------------- diff --git a/replicated/src/test/java/org/apache/geode/examples/replicated/ProducerTest.java b/replicated/src/test/java/org/apache/geode/examples/replicated/ProducerTest.java new file mode 100644 index 0000000..9b4a251 --- /dev/null +++ b/replicated/src/test/java/org/apache/geode/examples/replicated/ProducerTest.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.examples.replicated; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; + +import java.util.Set; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.apache.geode.cache.Region; +import org.apache.geode.cache.client.ClientCache; + +public class ProducerTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private Producer producer; + private ClientCache clientCache = mock(ClientCache.class); + private Region region = mock(Region.class); + private Set keys = mock(Set.class); + + @Before + public void setup() throws Exception { + when(region.getName()).thenReturn(Producer.REGION_NAME); + when(region.keySetOnServer()).thenReturn(keys); + when(clientCache.getRegion(any())).thenReturn(region); + } + + @Test + public void populateRegionShouldReturnCorrectNumberOfEntries() throws Exception { + producer = new Producer(clientCache); + producer.setRegion(region); + + producer.populateRegion(); + verify(region, times(producer.NUM_ENTRIES)).put(any(), any()); + } + + @Test + public void populateWhenRegionDoesNotExistShouldThrowNullPointer() throws Exception { + producer = new Producer(clientCache); + expectedException.expect(NullPointerException.class); + producer.populateRegion(); + } + + @After + public void tearDown() { + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/src/test/java/org/apache/geode/examples/replicated/ReplicatedTest.java ---------------------------------------------------------------------- diff --git a/replicated/src/test/java/org/apache/geode/examples/replicated/ReplicatedTest.java b/replicated/src/test/java/org/apache/geode/examples/replicated/ReplicatedTest.java new file mode 100644 index 0000000..ab84485 --- /dev/null +++ b/replicated/src/test/java/org/apache/geode/examples/replicated/ReplicatedTest.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.examples.replicated; + +import static org.hamcrest.core.Is.*; +import static org.junit.Assert.*; +import static org.junit.Assume.*; + +import java.io.IOException; +import java.net.ServerSocket; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecuteResultHandler; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.environment.EnvironmentUtils; +import org.apache.geode.example.utils.ShellUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Tests for the shell scripts of the replicated example + */ +public class ReplicatedTest { + + //TODO: parameterize + public static final String GEODE_LOCATOR_PORT = "GEODE_LOCATOR_PORT="; + private static final String startScriptFileName = "startAll.sh"; + private static final String stopScriptFileName = "stopAll.sh"; + private static final String pidkillerScriptFileName = "pidkiller.sh"; + private boolean processRunning = false; + private ShellUtil shell = new ShellUtil(); + private final long scriptTimeout = TimeUnit.SECONDS.toMillis(120); + private static final Logger logger = Logger.getAnonymousLogger(); + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + private int locatorPort; + private Map environment; + + @Before + public void setup() throws IOException { + // ignores test if running on windows + assumeThat(System.getProperty("os.name").startsWith("Windows"), is(false)); + + locatorPort = getAvailablePort(); + environment = EnvironmentUtils.getProcEnvironment(); + EnvironmentUtils.addVariableToEnvironment(environment, GEODE_LOCATOR_PORT + locatorPort); + logger.fine("Locator port: " + locatorPort); + } + + @Test + public void checkIfScriptsExistsAndAreExecutable() throws IOException { + assertTrue(shell.getFileFromClassLoader(startScriptFileName).map(x -> x.isFile()).orElse(false)); + assertTrue(shell.getFileFromClassLoader(stopScriptFileName).map(x -> x.isFile()).orElse(false)); + } + + @Test + public void executeStartThenStopScript() throws InterruptedException, IOException { + final int exitCodeStart = executeScript(startScriptFileName); + assertEquals(0, exitCodeStart); + + final int exitCodeStop = executeScript(stopScriptFileName); + assertEquals(0, exitCodeStop); + } + + @Test + public void failToStopWhenNoServersAreRunning() throws InterruptedException, IOException { + final int exitCode; + + exitCode = executeScript(stopScriptFileName); + assertEquals(1, exitCode); + } + + /** + * Execute the kill script that looks for pid files + * @throws IOException + * @throws InterruptedException + */ + private void runKillScript() throws IOException, InterruptedException { + CommandLine cmdLine = CommandLine.parse(shell.getFileFromClassLoader(pidkillerScriptFileName) + .map(x -> x.getAbsolutePath()) + .orElseThrow(IllegalArgumentException::new)); + cmdLine.addArgument(testFolder.getRoot().getAbsolutePath()); + + DefaultExecuteResultHandler resultHandler = shell.execute(cmdLine, scriptTimeout, environment, testFolder + .getRoot()); + resultHandler.waitFor(scriptTimeout); + } + + /** + * Given a script file name, runs the script and return the exit code. + * If exitCode != 0 extract and prints exception. + * @param scriptName + * @return <code>int</code> with exitCode + * @throws IOException + * @throws InterruptedException + */ + private int executeScript(String scriptName) throws IOException, InterruptedException { + final int exitCode; + DefaultExecuteResultHandler resultHandler = shell.execute(scriptName, scriptTimeout, environment, testFolder + .getRoot()); + processRunning = true; + resultHandler.waitFor(); + + logger.finest(String.format("Executing %s...", scriptName)); + exitCode = resultHandler.getExitValue(); + + // extract and log exception if any happened + if (exitCode != 0) { + ExecuteException executeException = resultHandler.getException(); + logger.log(Level.SEVERE, executeException.getMessage(), executeException); + } + return exitCode; + } + + @After + public void tearDown() { + if (processRunning) { + try { + runKillScript(); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } + } + + /** + * Get a random available port + * @return <code>int</code> port number + */ + private static int getAvailablePort() { + try (ServerSocket socket = new ServerSocket(0)) { + int port = socket.getLocalPort(); + socket.close(); + return port; + } catch (IOException ioex) { + logger.log(Level.SEVERE, ioex.getMessage(), ioex); + } + throw new IllegalStateException("No TCP/IP ports available."); + } + +} http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/replicated/src/test/test5.iml ---------------------------------------------------------------------- diff --git a/replicated/src/test/test5.iml b/replicated/src/test/test5.iml new file mode 100644 index 0000000..19dbd15 --- /dev/null +++ b/replicated/src/test/test5.iml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="false"> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/settings.gradle ---------------------------------------------------------------------- diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..432a8eb --- /dev/null +++ b/settings.gradle @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +rootProject.name = 'geode-examples' + +include 'replicated' +include 'utils' + http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/utils/src/main/java/org/apache/geode/example/utils/ShellUtil.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/org/apache/geode/example/utils/ShellUtil.java b/utils/src/main/java/org/apache/geode/example/utils/ShellUtil.java new file mode 100644 index 0000000..c5290b8 --- /dev/null +++ b/utils/src/main/java/org/apache/geode/example/utils/ShellUtil.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.geode.example.utils; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecuteResultHandler; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.exec.ShutdownHookProcessDestroyer; + +/** + * Utility class for executing shell commands using Apache commons-exec + */ +public class ShellUtil { + + private final ClassLoader classLoader = getClass().getClassLoader(); + + public Optional<File> getFileFromClassLoader(String fileName) { + URL resourceURL = classLoader.getResource(fileName); + return (resourceURL == null) ? Optional.empty() : Optional.of(new File(resourceURL.getFile())); + } + + public CommandLine parseCommandLine(String fileName) { + return getFileFromClassLoader(fileName).map(file -> CommandLine.parse(file.getAbsolutePath())) + .orElseThrow(IllegalArgumentException::new); + } + + public DefaultExecuteResultHandler execute(CommandLine cmdLine, long timeout, Map environment, File dir) throws IOException { + ExecutorTemplate exampleTestExecutor = new ExecutorTemplate(timeout, dir).invoke(); + DefaultExecutor executor = exampleTestExecutor.getExecutor(); + DefaultExecuteResultHandler resultHandler = exampleTestExecutor.getResultHandler(); + executor.execute(cmdLine, environment, resultHandler); + + return resultHandler; + + } + + public DefaultExecuteResultHandler execute(String fileName, long timeout, Map environment, File dir) throws IOException { + ExecutorTemplate exampleTestExecutor = new ExecutorTemplate(timeout, dir).invoke(); + DefaultExecutor executor = exampleTestExecutor.getExecutor(); + DefaultExecuteResultHandler resultHandler = exampleTestExecutor.getResultHandler(); + executor.execute(parseCommandLine(fileName), environment, resultHandler); + + return resultHandler; + } + + /** + * Executor template for common scenarios + */ + private static class ExecutorTemplate { + + private final long timeout; + private final File dir; + private DefaultExecutor executor; + private DefaultExecuteResultHandler resultHandler; + + public ExecutorTemplate(final long timeout, final File dir) { + this.timeout = timeout; + this.dir = dir; + } + + public DefaultExecutor getExecutor() { + return executor; + } + + public DefaultExecuteResultHandler getResultHandler() { + return resultHandler; + } + + public ExecutorTemplate invoke() { + executor = new DefaultExecutor(); + ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout); + executor.setWatchdog(watchdog); + + PumpStreamHandler psh = new PumpStreamHandler(System.out, System.err); + executor.setProcessDestroyer(new ShutdownHookProcessDestroyer()); + executor.setStreamHandler(psh); + executor.setWorkingDirectory(dir); + + resultHandler = new DefaultExecuteResultHandler(); + return this; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/geode-examples/blob/7aacbd04/utils/src/main/main5.iml ---------------------------------------------------------------------- diff --git a/utils/src/main/main5.iml b/utils/src/main/main5.iml new file mode 100644 index 0000000..19dbd15 --- /dev/null +++ b/utils/src/main/main5.iml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="false"> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file
