diff --git a/.gitignore b/.gitignore index f65bab3..d5fba1a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.iws .gradle build/ +out/ # Log files *.log diff --git a/build.gradle b/build.gradle index 8df5500..f137a4e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,42 +1,25 @@ buildscript { - ext { - grailsVersion = project.grailsVersion - } repositories { - mavenLocal() maven { url "https://repo.grails.org/grails/core" } } dependencies { classpath "org.grails:grails-gradle-plugin:$grailsVersion" + classpath "gradle.plugin.com.github.erdi.webdriver-binaries:webdriver-binaries-gradle-plugin:2.0" } } -plugins { - id "io.spring.dependency-management" version "0.5.4.RELEASE" - id "com.jfrog.bintray" version "1.2" -} - version "1.0.1" group "org.grails.plugins" apply plugin: 'maven-publish' -apply plugin: 'eclipse' -apply plugin: 'idea' -apply plugin: "spring-boot" +apply plugin: "eclipse" +apply plugin: "idea" +apply plugin: "io.spring.dependency-management" apply plugin: "org.grails.grails-plugin" -apply plugin: "org.grails.grails-gsp" -// Used for publishing to central repository, remove if not needed -apply from: 'https://raw.githubusercontent.com/grails/grails-profile-repository/master/profiles/plugin/templates/grailsCentralPublishing.gradle' -apply from: 'https://raw.githubusercontent.com/grails/grails-profile-repository/master/profiles/plugin/templates/bintrayPublishing.gradle' - -ext { - grailsVersion = project.grailsVersion - gradleWrapperVersion = project.gradleWrapperVersion -} - -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +apply plugin: "com.github.erdi.webdriver-binaries" +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenLocal() @@ -44,42 +27,71 @@ repositories { maven { url "https://repo.grails.org/grails/core" } } -dependencyManagement { - imports { - mavenBom "org.grails:grails-bom:$grailsVersion" +configurations { + developmentOnly + runtimeClasspath { + extendsFrom developmentOnly } - applyMavenExclusions false } dependencies { - provided 'org.springframework.boot:spring-boot-starter-logging' - provided "org.springframework.boot:spring-boot-starter-actuator" - provided "org.springframework.boot:spring-boot-autoconfigure" - provided "org.springframework.boot:spring-boot-starter-tomcat" + developmentOnly("org.springframework.boot:spring-boot-devtools") + compile "org.springframework.boot:spring-boot-starter-logging" + compile "org.springframework.boot:spring-boot-autoconfigure" + compile "org.grails:grails-core" + compile "org.springframework.boot:spring-boot-starter-actuator" + compile "org.springframework.boot:spring-boot-starter-tomcat" + compile "org.grails:grails-web-boot" + compile "org.grails:grails-logging" + compile "org.grails:grails-plugin-databinding" + compile "org.grails:grails-plugin-url-mappings" + console "org.grails:grails-console" + profile "org.grails.profiles:web-plugin" + runtime "com.bertramlabs.plugins:asset-pipeline-grails:3.0.10" + testCompile "org.grails:grails-gorm-testing-support" + testCompile "org.mockito:mockito-core" + testCompile "org.grails:grails-web-testing-support" + testCompile "org.grails.plugins:geb" + testCompile "org.seleniumhq.selenium:selenium-remote-driver:3.14.0" + testCompile "org.seleniumhq.selenium:selenium-api:3.14.0" + testCompile "org.seleniumhq.selenium:selenium-support:3.14.0" + testRuntime "org.seleniumhq.selenium:selenium-chrome-driver:3.14.0" + testRuntime "org.seleniumhq.selenium:selenium-firefox-driver:3.14.0" - provided "org.grails:grails-web-boot" - provided "org.grails:grails-dependencies" provided 'javax.servlet:javax.servlet-api:3.1.0' compile 'net.sf.opencsv:opencsv:2.3' - testCompile "org.grails:grails-plugin-testing" +} - testCompile "org.grails.plugins:geb:1.0.0.BUILD-SNAPSHOT" - // Note: It is recommended to update to a more robust driver (Chrome, Firefox etc.) - testRuntime 'org.seleniumhq.selenium:selenium-htmlunit-driver:2.44.0' +bootRun { + ignoreExitValue true + jvmArgs( + '-Dspring.output.ansi.enabled=always', + '-noverify', + '-XX:TieredStopAtLevel=1', + '-Xmx1024m') + sourceResources sourceSets.main + String springProfilesActive = 'spring.profiles.active' + systemProperty springProfilesActive, System.getProperty(springProfilesActive) +} +tasks.withType(GroovyCompile) { + configure(groovyOptions) { + forkOptions.jvmArgs = ['-Xmx1024m'] + } } -task wrapper(type: Wrapper) { - gradleVersion = gradleWrapperVersion +webdriverBinaries { + chromedriver '2.45.0' + geckodriver '0.24.0' } -bintray { - user = '' - key = '' - pkg { - repo = 'plugins' - userOrg = 'sachinverma' - licenses = ['Apache-2.0'] - } +tasks.withType(Test) { + systemProperty "geb.env", System.getProperty('geb.env') + systemProperty "geb.build.reportsDir", reporting.file("geb/integrationTest") + systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver') + systemProperty "webdriver.gecko.driver", System.getProperty('webdriver.gecko.driver') } + +// enable if you wish to package this plugin as a standalone application +bootJar.enabled = false \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 50e0c18..d3cfbcd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,6 @@ -grailsVersion=3.0.17 -gradleWrapperVersion=2.3 +grailsVersion=4.0.11 +gorm.version=7.0.8.RELEASE +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx1024M +gradleWrapperVersion=5.6.4 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 085a1cd..87b738c 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2bdcf31..5028f28 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Feb 04 17:05:29 CST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip diff --git a/gradlew b/gradlew index 91a7e26..d2715bc 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,159 +6,167 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# 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 APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=$(basename "$0") + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { - echo "$*" +warn() { + echo "$*" } -die ( ) { - echo - echo "$*" - echo - exit 1 +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 - ;; +nonstop=false +case "$(uname)" in +CYGWIN*) + cygwin=true + ;; +Darwin*) + darwin=true + ;; +MINGW*) + msys=true + ;; +NONSTOP*) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# 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\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - 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 +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 + 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. + 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" +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "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\"" + 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"` - - # 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)" +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 - # 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 + 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=("$@") +# Escape application args +save() { + for i; do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat old mode 100644 new mode 100755 index aec9973..6d57edc --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,84 @@ -@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 Windowz 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 +@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 + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@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="-Xmx64m" + +@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 + +: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=%* + +: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 diff --git a/grails-app/conf/application.yml b/grails-app/conf/application.yml index 0e091fa..19d1c3b 100644 --- a/grails-app/conf/application.yml +++ b/grails-app/conf/application.yml @@ -1,13 +1,92 @@ +--- grails: profile: web-plugin codegen: - defaultPackage: 'grails.plugins.csv' + defaultPackage: grails.plugins.csv + gorm: + reactor: + # Whether to translate GORM events into Reactor events + # Disabled by default for performance reasons + events: false info: app: name: '@info.app.name@' version: '@info.app.version@' grailsVersion: '@info.app.grailsVersion@' spring: + jmx: + unique-names: true + main: + banner-mode: "off" groovy: template: - check-template-location: false \ No newline at end of file + check-template-location: false + devtools: + restart: + additional-exclude: + - '*.gsp' + - '**/*.gsp' + - '*.gson' + - '**/*.gson' + - 'logback.groovy' + - '*.properties' +management: + endpoints: + enabled-by-default: false + +--- +grails: + mime: + disable: + accept: + header: + userAgents: + - Gecko + - WebKit + - Presto + - Trident + types: + all: '*/*' + atom: application/atom+xml + css: text/css + csv: text/csv + form: application/x-www-form-urlencoded + html: + - text/html + - application/xhtml+xml + js: text/javascript + json: + - application/json + - text/json + multipartForm: multipart/form-data + pdf: application/pdf + rss: application/rss+xml + text: text/plain + hal: + - application/hal+json + - application/hal+xml + xml: + - text/xml + - application/xml + urlmapping: + cache: + maxsize: 1000 + controllers: + defaultScope: singleton + converters: + encoding: UTF-8 + views: + default: + codec: html + gsp: + encoding: UTF-8 + htmlcodec: xml + codecs: + expression: html + scriptlet: html + taglib: none + staticparts: none +management: + endpoints: + jmx: + unique-names: true diff --git a/grails-app/conf/logback.groovy b/grails-app/conf/logback.groovy index 5b2d1e3..b835215 100644 --- a/grails-app/conf/logback.groovy +++ b/grails-app/conf/logback.groovy @@ -1,28 +1,37 @@ import grails.util.BuildSettings import grails.util.Environment +import org.springframework.boot.logging.logback.ColorConverter +import org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter +import java.nio.charset.StandardCharsets + +conversionRule 'clr', ColorConverter +conversionRule 'wex', WhitespaceThrowableProxyConverter // See http://logback.qos.ch/manual/groovy.html for details on configuration appender('STDOUT', ConsoleAppender) { encoder(PatternLayoutEncoder) { - pattern = "%level %logger - %msg%n" + charset = StandardCharsets.UTF_8 + + pattern = + '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} ' + // Date + '%clr(%5p) ' + // Log level + '%clr(---){faint} %clr([%15.15t]){faint} ' + // Thread + '%clr(%-40.40logger{39}){cyan} %clr(:){faint} ' + // Logger + '%m%n%wex' // Message } } -root(ERROR, ['STDOUT']) - -if(Environment.current == Environment.DEVELOPMENT) { - def targetDir = BuildSettings.TARGET_DIR - if(targetDir) { - - appender("FULL_STACKTRACE", FileAppender) { - - file = "${targetDir}/stacktrace.log" - append = true - encoder(PatternLayoutEncoder) { - pattern = "%level %logger - %msg%n" - } +def targetDir = BuildSettings.TARGET_DIR +if (Environment.isDevelopmentMode() && targetDir != null) { + appender("FULL_STACKTRACE", FileAppender) { + file = "${targetDir}/stacktrace.log" + append = true + encoder(PatternLayoutEncoder) { + charset = StandardCharsets.UTF_8 + pattern = "%level %logger - %msg%n" } - logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false ) } + logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false) } +root(ERROR, ['STDOUT']) diff --git a/grails-app/controllers/grails/plugins/csv/CsvTestController.groovy b/grails-app/controllers/grails/plugins/csv/CsvTestController.groovy index 82d998a..9ef7022 100644 --- a/grails-app/controllers/grails/plugins/csv/CsvTestController.groovy +++ b/grails-app/controllers/grails/plugins/csv/CsvTestController.groovy @@ -3,12 +3,10 @@ package grails.plugins.csv class CsvTestController { def writeCsv = { - def rows = [] - rows << [1,2] - rows << [3,4] - rows << [5,6] - - renderCsv(rows: rows, filename: params.filename, attachment: params.attachment) { + List> rows = [[1, 2], + [3, 4], + [5, 6]] + renderCsv(rows: rows, filename: params.filename, attachment: params.boolean('attachment')) { x { it[0] } y { it[1] } } diff --git a/grails-app/controllers/grails/plugins/csv/UrlMappings.groovy b/grails-app/controllers/grails/plugins/csv/UrlMappings.groovy new file mode 100644 index 0000000..9e933ca --- /dev/null +++ b/grails-app/controllers/grails/plugins/csv/UrlMappings.groovy @@ -0,0 +1,16 @@ +package grails.plugins.csv + +class UrlMappings { + + static mappings = { + "/$controller/$action?/$id?(.$format)?" { + constraints { + // apply constraints here + } + } + + "/"(view: "/index") + "500"(view: '/error') + "404"(view: '/notFound') + } +} diff --git a/grails-app/init/grails/plugins/csv/Application.groovy b/grails-app/init/grails/plugins/csv/Application.groovy index ae8ff2f..a765e7c 100644 --- a/grails-app/init/grails/plugins/csv/Application.groovy +++ b/grails-app/init/grails/plugins/csv/Application.groovy @@ -2,7 +2,9 @@ package grails.plugins.csv import grails.boot.GrailsApp import grails.boot.config.GrailsAutoConfiguration +import grails.plugins.metadata.PluginSource +@PluginSource class Application extends GrailsAutoConfiguration { static void main(String[] args) { GrailsApp.run(Application, args) diff --git a/grails-app/init/grails/plugins/csv/BootStrap.groovy b/grails-app/init/grails/plugins/csv/BootStrap.groovy new file mode 100644 index 0000000..fe5d55f --- /dev/null +++ b/grails-app/init/grails/plugins/csv/BootStrap.groovy @@ -0,0 +1,9 @@ +package grails.plugins.csv + +class BootStrap { + + def init = { servletContext -> + } + def destroy = { + } +} diff --git a/grails-wrapper.jar b/grails-wrapper.jar new file mode 100644 index 0000000..6b6da64 Binary files /dev/null and b/grails-wrapper.jar differ diff --git a/grailsw b/grailsw new file mode 100755 index 0000000..b6cf797 --- /dev/null +++ b/grailsw @@ -0,0 +1,151 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Grails start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRAILS_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-XX:+TieredCompilation" "-XX:TieredStopAtLevel=1" "-XX:CICompilerCount=3"' + +# 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 + +JAR_PATH=$APP_HOME/grails-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 Cygwin, switch paths to Windows format before running java +if $cygwin; then + APP_HOME=$(cygpath --path --mixed "$APP_HOME") + JAVACMD=$(cygpath --unix "$JAVACMD") + JAR_PATH=$(cygpath --path --mixed "$JAR_PATH") + + # 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 [ "$GRAILS_CYGPATTERN" != "" ]; then + OURCYGPATTERN="$OURCYGPATTERN|($GRAILS_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 GRAILS_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRAILS_OPTS + +exec "$JAVACMD" -jar "${JVM_OPTS[@]}" "$JAR_PATH" "$@" diff --git a/grailsw.bat b/grailsw.bat new file mode 100755 index 0000000..14734e4 --- /dev/null +++ b/grailsw.bat @@ -0,0 +1,89 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Grails 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 GRAILS_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-XX:+TieredCompilation" "-XX:TieredStopAtLevel=1" "-XX:CICompilerCount=3" + +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 Windowz 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 JAR_PATH=%APP_HOME%/grails-wrapper.jar + +@rem Execute Grails +"%JAVA_EXE%" -jar %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRAILS_OPTS% %JAR_PATH% %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRAILS_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRAILS_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/integration-test/groovy/grails/plugins/csv/CSVMapReaderIntTest.groovy b/src/integration-test/groovy/grails/plugins/csv/CSVMapReaderIntTest.groovy index 6e707a1..0441d3e 100644 --- a/src/integration-test/groovy/grails/plugins/csv/CSVMapReaderIntTest.groovy +++ b/src/integration-test/groovy/grails/plugins/csv/CSVMapReaderIntTest.groovy @@ -1,6 +1,6 @@ package grails.plugins.csv -import grails.test.mixin.integration.Integration +import grails.testing.mixin.integration.Integration import org.junit.Test @Integration diff --git a/src/integration-test/groovy/grails/plugins/csv/CSVReaderUtilsIntegrationTest.groovy b/src/integration-test/groovy/grails/plugins/csv/CSVReaderUtilsIntegrationTest.groovy index 47c858f..f2afdb9 100644 --- a/src/integration-test/groovy/grails/plugins/csv/CSVReaderUtilsIntegrationTest.groovy +++ b/src/integration-test/groovy/grails/plugins/csv/CSVReaderUtilsIntegrationTest.groovy @@ -16,17 +16,13 @@ */ package grails.plugins.csv -import grails.test.mixin.TestFor -import grails.test.mixin.integration.Integration +import grails.testing.mixin.integration.Integration import org.junit.Test -import org.springframework.core.io.ClassPathResource -import org.springframework.core.io.Resource /** * Tests to verify dynamically added methods to Java/Groovy classes (String, InputStream, etc) work as expected * - * @since 0.1 - * @author Les Hazlewood + * @since 0.1* @author Les Hazlewood */ @Integration class CSVReaderUtilsIntegrationTest extends GroovyTestCase { diff --git a/src/integration-test/groovy/grails/plugins/csv/CsvTestControllerGebSpec.groovy b/src/integration-test/groovy/grails/plugins/csv/CsvTestControllerGebSpec.groovy index f56f714..ba37346 100644 --- a/src/integration-test/groovy/grails/plugins/csv/CsvTestControllerGebSpec.groovy +++ b/src/integration-test/groovy/grails/plugins/csv/CsvTestControllerGebSpec.groovy @@ -1,30 +1,27 @@ package grails.plugins.csv -import grails.test.mixin.integration.Integration -import grails.transaction.* - -import spock.lang.* -import geb.spock.* +import geb.spock.GebSpec +import grails.testing.mixin.integration.Integration @Integration class CsvTestControllerGebSpec extends GebSpec { - def setup() { - } + def setup() { + } - def cleanup() { - } + def cleanup() { + } - void "test writeCsv"(){ - when: "writeCsv action is visited" - go '/csvTest/writeCsv' + void "test writeCsv"() { + when: "writeCsv action is visited" + go '/csvTest/writeCsv' - then: - driver.pageSource.contains("\"x\",\"y\"") - driver.pageSource.contains("\"1\",\"2\"") - driver.pageSource.contains("\"3\",\"4\"") - driver.pageSource.contains("\"5\",\"6\"") + then: + driver.pageSource.contains("\"x\",\"y\"") + driver.pageSource.contains("\"1\",\"2\"") + driver.pageSource.contains("\"3\",\"4\"") + driver.pageSource.contains("\"5\",\"6\"") - } + } } diff --git a/src/integration-test/groovy/grails/plugins/csv/CsvTestControllerSpec.groovy b/src/integration-test/groovy/grails/plugins/csv/CsvTestControllerSpec.groovy index 51092ac..60c28ab 100644 --- a/src/integration-test/groovy/grails/plugins/csv/CsvTestControllerSpec.groovy +++ b/src/integration-test/groovy/grails/plugins/csv/CsvTestControllerSpec.groovy @@ -1,10 +1,9 @@ package grails.plugins.csv -import grails.test.mixin.TestFor +import grails.testing.mixin.integration.Integration import spock.lang.Specification - -@TestFor(CsvTestController) +@Integration class CsvTestControllerSpec extends Specification { def populateValidParams(params) { diff --git a/src/main/groovy/grails/plugins/csv/CSVMapReader.groovy b/src/main/groovy/grails/plugins/csv/CSVMapReader.groovy index db429af..b3b82be 100644 --- a/src/main/groovy/grails/plugins/csv/CSVMapReader.groovy +++ b/src/main/groovy/grails/plugins/csv/CSVMapReader.groovy @@ -23,25 +23,24 @@ import au.com.bytecode.opencsv.CSVReader * Also removes blank lines as for whatever reason the CSVReader does not * Uses an underlying OpenCSV's CSVReader. * - * @since 0.2 - * @author Joshua Burnett + * @since 0.2* @author Joshua Burnett */ -public class CSVMapReader implements Closeable, Iterable { +class CSVMapReader implements Closeable, Iterable { CSVReader csvReader - //the column names from the first header line in the file - def fieldKeys = [] - - /** - * If this is >0 then on each iteration, instead of a map, will return a list of maps of this batchSize - * and returnAll or toList will return a list of lists(batches) of maps based on the batchSize - * For example: this is usefull if you have a million rows in the CSV and want each iteration to return a list(batch) of 50 rows(maps) at a time - * so you can process inserts into the db in batches of 50. - */ - Integer batchSize = 0 - - public CSVMapReader() { + //the column names from the first header line in the file + def fieldKeys = [] + + /** + * If this is >0 then on each iteration, instead of a map, will return a list of maps of this batchSize + * and returnAll or toList will return a list of lists(batches) of maps based on the batchSize + * For example: this is usefull if you have a million rows in the CSV and want each iteration to return a list(batch) of 50 rows(maps) at a time + * so you can process inserts into the db in batches of 50. + */ + Integer batchSize = 0 + + CSVMapReader() { } /** @@ -49,118 +48,118 @@ public class CSVMapReader implements Closeable, Iterable { * * @param reader the reader to an underlying CSV source. */ - public CSVMapReader(Reader reader) { - this(reader, null) + CSVMapReader(Reader reader) { + this(reader, null) } /** * Constructs CSVMapReader from the reader * - * @param reader the reader to an underlying CSV source. + * @param reader the reader to an underlying CSV source. * @param settingsMap map of settings for the underlying CSVReader. */ - public CSVMapReader(Reader reader, Map settingsMap) { - csvReader = CSVReaderUtils.toCsvReader(reader,settingsMap) - if(settingsMap?.batchSize) batchSize = settingsMap?.batchSize?.toInteger() + CSVMapReader(Reader reader, Map settingsMap) { + csvReader = CSVReaderUtils.toCsvReader(reader, settingsMap) + if (settingsMap?.batchSize) batchSize = settingsMap?.batchSize?.toInteger() } - /** + /** * Constructs CSVMapReader using a CSVReader * * @param csvReader the constructed CSVReader */ - public CSVMapReader(CSVReader csvr) { - csvReader = csvr + CSVMapReader(CSVReader csvr) { + csvReader = csvr } - //takes the first header line (assumed from firstreadline) from the file and sets the keys - def initFieldKeys(){ - fieldKeys = fieldKeys?:csvReader.readNext() - } + //takes the first header line (assumed from firstreadline) from the file and sets the keys + def initFieldKeys() { + fieldKeys = fieldKeys ?: csvReader.readNext() + } - /** + /** * Reads the next line from the buffer in CSVReader and converts to map. */ Map readNext() throws IOException { Map result - String[] nextLine = csvReader.readNext() - //skip blank lines if there is only 1 token and its blank - while (nextLine && isBlankLine(nextLine)) { - nextLine = csvReader.readNext() - } - return convertArrayToMap(fieldKeys,nextLine) + String[] nextLine = csvReader.readNext() + //skip blank lines if there is only 1 token and its blank + while (nextLine && isBlankLine(nextLine)) { + nextLine = csvReader.readNext() + } + return convertArrayToMap(fieldKeys, nextLine) } - /** + /** * Reads the next batched chunk of lines from the buffer in CSVReader and return a list of maps. */ List readNextBatch() throws IOException { - def reslist = [] - Map map = readNext() - while(map){ - reslist.add map - if(reslist.size() == batchSize) break; - map = readNext() - } - return reslist - } - - //This is here to remain consitent with file's eachLine in case someone uses it. Just calls the each - void eachLine(Closure closure){ - if(batchSize >0 ) throw new UnsupportedOperationException("batchSize is >0 so you are not getting lines but a list of lines(rows/maps). Use each instead"); - each(closure) - } - - //true it only 1 element in array and its blank - boolean isBlankLine(String[] tokenArray){ - return (!tokenArray[0] && tokenArray.size() <=1 ) - } - - /** + def reslist = [] + Map map = readNext() + while (map) { + reslist.add map + if (reslist.size() == batchSize) break + map = readNext() + } + return reslist + } + + //This is here to remain consitent with file's eachLine in case someone uses it. Just calls the each + void eachLine(Closure closure) { + if (batchSize > 0) throw new UnsupportedOperationException("batchSize is >0 so you are not getting lines but a list of lines(rows/maps). Use each instead") + each(closure) + } + + //true it only 1 element in array and its blank + boolean isBlankLine(String[] tokenArray) { + return (!tokenArray[0] && tokenArray.size() <= 1) + } + + /** * Reads the entire file into a List with each element being a map where keys are the from the 1st header line in file * * @return a List of Maps (or list of lists of maps if batchSize>0) with each map representing a line of the */ List readAll() { - this.collect{it} + this.collect { it } } - /** + /** * a more groovy alternate to readAll (opencsv syntax) that returns this as a list of maps */ - List toList(){ - return readAll() - } - - //groovy way to cast, can do something like " def list = new CSVMapReader(file) as List - Object asType(Class type){ - if(type == List) return readAll() - } - - - static Map convertArrayToMap(keys,tokens){ - if(!tokens) return null - def map = [:] - for ( i in 0..tokens.size()-1 ) { - map[keys[i]] = tokens[i] - } - return map - } - - /** + List toList() { + return readAll() + } + + //groovy way to cast, can do something like " def list = new CSVMapReader(file) as List + Object asType(Class type) { + if (type == List) return readAll() + } + + + static Map convertArrayToMap(keys, tokens) { + if (!tokens) return null + def map = [:] + for (i in 0..tokens.size() - 1) { + map[keys[i]] = tokens[i] + } + return map + } + + /** * Calls close on CSVReader and closes the underlying reader. You should do this if you are working with Stream or Files! */ - public void close() throws IOException { - csvReader.close(); + void close() throws IOException { + csvReader.close() } - public Iterator iterator() { + Iterator iterator() { try { - return new CSVMapReaderIterator(this); + return new CSVMapReaderIterator(this) } catch (IOException e) { - throw new RuntimeException(e); - } + throw new RuntimeException(e) + } } } @@ -170,29 +169,29 @@ class CSVMapReaderIterator implements Iterator { def nextEl CSVMapReaderIterator(CSVMapReader reader) throws IOException { - this.mapReader = reader; + this.mapReader = reader mapReader.initFieldKeys() - nextEl = mapReader.batchSize? mapReader.readNextBatch() :mapReader.readNext() + nextEl = mapReader.batchSize ? mapReader.readNextBatch() : mapReader.readNext() } boolean hasNext() { - if(!nextEl) mapReader.close() + if (!nextEl) mapReader.close() return nextEl } def next() { def curEl = nextEl try { - nextEl = mapReader.batchSize? mapReader.readNextBatch() :mapReader.readNext() + nextEl = mapReader.batchSize ? mapReader.readNextBatch() : mapReader.readNext() } catch (IOException e) { - mapReader.close() - throw new RuntimeException(e); + mapReader.close() + throw new RuntimeException(e) } - return curEl; + return curEl } void remove() { - throw new UnsupportedOperationException("This is a read only iterator."); + throw new UnsupportedOperationException("This is a read only iterator.") } } diff --git a/src/main/groovy/grails/plugins/csv/CSVReaderUtils.groovy b/src/main/groovy/grails/plugins/csv/CSVReaderUtils.groovy index 85c6252..50e8b55 100644 --- a/src/main/groovy/grails/plugins/csv/CSVReaderUtils.groovy +++ b/src/main/groovy/grails/plugins/csv/CSVReaderUtils.groovy @@ -22,56 +22,53 @@ import au.com.bytecode.opencsv.CSVReader /** * Utility class for adding CSV parsing capability to core Java/Groovy classes (String, File, InputStream, Reader). * - * @since 0.1 - * @author Les Hazlewood + * @since 0.1* @author Les Hazlewood */ class CSVReaderUtils { - - public static void eachLine(CSVReader csvReader, Closure c) { + static void eachLine(CSVReader csvReader, Closure c) { try { String[] tokens = csvReader.readNext() while (tokens) { - c.doCall(tokens); - tokens = csvReader.readNext(); + c.doCall(tokens) + tokens = csvReader.readNext() } } finally { csvReader.close() } } - public static void eachLine(File file, Closure c) { - eachLine(toCsvReader(file, null), c); + static void eachLine(File file, Closure c) { + eachLine(toCsvReader(file, null), c) } - public static void eachLine(InputStream is, Closure c) { - eachLine(toCsvReader(is, null), c); + static void eachLine(InputStream is, Closure c) { + eachLine(toCsvReader(is, null), c) } - public static void eachLine(Reader r, Closure c) { - eachLine(toCsvReader(r, null), c); + static void eachLine(Reader r, Closure c) { + eachLine(toCsvReader(r, null), c) } - public static void eachLine(String csv, Closure c) { - eachLine(toCsvReader(csv, null), c); + static void eachLine(String csv, Closure c) { + eachLine(toCsvReader(csv, null), c) } - public static CSVReader toCsvReader(File file, def settingsMap) { + static CSVReader toCsvReader(File file, def settingsMap) { return toCsvReader(new FileInputStream(file), settingsMap) } - public static CSVReader toCsvReader(InputStream is, def settingsMap) { + static CSVReader toCsvReader(InputStream is, def settingsMap) { def charset = settingsMap?.get('charset') - InputStreamReader reader; + InputStreamReader reader if (charset) { reader = new InputStreamReader(is, charset) } else { reader = new InputStreamReader(is) } - return toCsvReader(reader, settingsMap); + return toCsvReader(reader, settingsMap) } - public static CSVReader toCsvReader(Reader r, def settingsMap) { - + static CSVReader toCsvReader(Reader r, def settingsMap) { char separatorChar = (settingsMap?.get('separatorChar') ?: CSVParser.DEFAULT_SEPARATOR) as char char quoteChar = (settingsMap?.get('quoteChar') ?: CSVParser.DEFAULT_QUOTE_CHARACTER) as char char escapeChar = (settingsMap?.get('escapeChar') ?: CSVParser.DEFAULT_ESCAPE_CHARACTER) as char @@ -92,9 +89,7 @@ class CSVReaderUtils { return new CSVReader(r, separatorChar, quoteChar, escapeChar, skipLines, strictQuotes, ignoreLeadingWhiteSpace) } - public static CSVReader toCsvReader(String s, def settingsMap) { + static CSVReader toCsvReader(String s, def settingsMap) { return toCsvReader(new StringReader(s), settingsMap) } - - -} +} \ No newline at end of file diff --git a/src/main/groovy/grails/plugins/csv/CSVWriter.groovy b/src/main/groovy/grails/plugins/csv/CSVWriter.groovy index ccf7adc..b642c77 100644 --- a/src/main/groovy/grails/plugins/csv/CSVWriter.groovy +++ b/src/main/groovy/grails/plugins/csv/CSVWriter.groovy @@ -1,4 +1,3 @@ - package grails.plugins.csv /** * Writes CSV content to a given writer, using a definition DSL. @@ -6,11 +5,7 @@ package grails.plugins.csv * Examples: * * def sw = new StringWriter() - * def b = new CSVBuilder(sw) { - * col1 { it.val1 } - * col2 { it.val2 } - * } - * b << [val1: 'a', val2: 'b'] + * def b = new CSVBuilder(sw) {* col1 { it.val1 }* col2 { it.val2 }*}* b << [val1: 'a', val2: 'b'] * b << [val1: 'c', val2: 'd'] * * assert b.writer.toString() == '''"col1","col2" @@ -23,116 +18,116 @@ package grails.plugins.csv */ class CSVWriter { - private columns = [:] - - final writer - - private cachedQuote - private cachedQuoteEscape - private cachedQuoteReplace - private cachedValueSeperator - private cachedRowSeperator - - private producers - private lastProducer - - private headingsWritten = false - - CSVWriter(Writer writer, Closure definition) { - this.writer = writer - - columns = CSVWriterColumnsBuilder.build(definition) - - // do these once incase subclasses are reading from config etc. - cachedQuote = this.quote - cachedQuoteEscape = this.quoteEscape - cachedQuoteReplace = this.quoteEscape + this.quote - cachedValueSeperator = this.valueSeperator - cachedRowSeperator = this.rowSeperator - - producers = columns.values().toList() - lastProducer = producers.last() - } - - def leftShift(row) { - write(row) - this - } - - def write(row) { - if (!headingsWritten) { - writeHeadings() - } - - writer << this.@cachedRowSeperator - for (producer in this.@producers) { - writeValue(producer(row).toString()) - if (!producer.is(this.@lastProducer)) { - writer << this.@cachedValueSeperator - } - } - - writer - } - - def writeAll(Collection rows) { - for (row in rows) { - write(row) - } - writer - } - - protected writeHeadings() { - columns.eachWithIndex { column, i -> - writeValue(column.key) - if (i != (columns.size() - 1)) { - writer << this.@cachedValueSeperator - } - } - headingsWritten = true - } - - protected writeValue(String value) { - writer << this.@cachedQuote - writer << value.replace(this.@cachedQuote, this.@cachedQuoteReplace) - writer << this.@cachedQuote - } - - protected getQuote() { - '"' - } - - protected getQuoteEscape() { - '"' - } - - protected getValueSeperator() { - "," - } - - protected getRowSeperator() { - "\n" - } + private columns = [:] + + final writer + + private cachedQuote + private cachedQuoteEscape + private cachedQuoteReplace + private cachedValueSeperator + private cachedRowSeperator + + private producers + private lastProducer + + private headingsWritten = false + + CSVWriter(Writer writer, Closure definition) { + this.writer = writer + + columns = CSVWriterColumnsBuilder.build(definition) + + // do these once incase subclasses are reading from config etc. + cachedQuote = this.quote + cachedQuoteEscape = this.quoteEscape + cachedQuoteReplace = this.quoteEscape + this.quote + cachedValueSeperator = this.valueSeperator + cachedRowSeperator = this.rowSeperator + + producers = columns.values().toList() + lastProducer = producers.last() + } + + def leftShift(row) { + write(row) + this + } + + def write(row) { + if (!headingsWritten) { + writeHeadings() + } + + writer << this.@cachedRowSeperator + for (producer in this.@producers) { + writeValue(producer(row).toString()) + if (!producer.is(this.@lastProducer)) { + writer << this.@cachedValueSeperator + } + } + + writer + } + + def writeAll(Collection rows) { + for (row in rows) { + write(row) + } + writer + } + + protected writeHeadings() { + columns.eachWithIndex { column, i -> + writeValue(column.key) + if (i != (columns.size() - 1)) { + writer << this.@cachedValueSeperator + } + } + headingsWritten = true + } + + protected writeValue(String value) { + writer << this.@cachedQuote + writer << value.replace(this.@cachedQuote, this.@cachedQuoteReplace) + writer << this.@cachedQuote + } + + protected getQuote() { + '"' + } + + protected getQuoteEscape() { + '"' + } + + protected getValueSeperator() { + "," + } + + protected getRowSeperator() { + "\n" + } } class CSVWriterColumnsBuilder { - final columns = [:] + final columns = [:] - CSVWriterColumnsBuilder(Closure definition) { - definition.delegate = this - definition() - } + CSVWriterColumnsBuilder(Closure definition) { + definition.delegate = this + definition() + } - def methodMissing(String name, args) { - if (args.size() == 1 && args[0] instanceof Closure) { - columns[name] = args[0] - } else { - throw new IllegalArgumentException('Must have 1 closure argument') - } - } + def methodMissing(String name, args) { + if (args.size() == 1 && args[0] instanceof Closure) { + columns[name] = args[0] + } else { + throw new IllegalArgumentException('Must have 1 closure argument') + } + } - static build(Closure definition) { - new CSVWriterColumnsBuilder(definition).columns - } + static build(Closure definition) { + new CSVWriterColumnsBuilder(definition).columns + } } \ No newline at end of file diff --git a/src/main/groovy/grails/plugins/csv/CsvGrailsPlugin.groovy b/src/main/groovy/grails/plugins/csv/CsvGrailsPlugin.groovy index 358ec90..7e1fd7a 100644 --- a/src/main/groovy/grails/plugins/csv/CsvGrailsPlugin.groovy +++ b/src/main/groovy/grails/plugins/csv/CsvGrailsPlugin.groovy @@ -1,27 +1,21 @@ package grails.plugins.csv import au.com.bytecode.opencsv.CSVReader -import grails.core.GrailsApplication -import grails.plugins.* +import grails.plugins.Plugin import grails.plugins.csv.controller.RenderCsvMethod class CsvGrailsPlugin extends Plugin { - // the version or versions of Grails the plugin is designed for - def grailsVersion = "3.0.1 > *" - // resources that are excluded from plugin packaging + def grailsVersion = "4.0.0 > *" def pluginExcludes = [ "grails-app/controllers/**/*" ] - def observe = [ "controllers" ] - def loadAfter = [ "controllers" ] - def author = "Les Hazlewood, Stefan Armbruster" def authorEmail = "les@katasoft.com, stefan@armbruster-it.de" def title = "Grails CSV Plugin" @@ -83,75 +77,55 @@ class CsvGrailsPlugin extends Plugin { *Note that this option is ONLY valid for InputStream instances. It is ignored otherwise. ''' - // URL to the plugin's documentation def documentation = "http://grails.org/plugin/csv" - - // Extra (optional) plugin metadata - - // License: one of 'APACHE', 'GPL2', 'GPL3' def license = "APACHE" - - // Details of company behind the plugin (if there is one) -// def organization = [ name: "My Company", url: "http://www.my-company.com/" ] - - // Any additional developers beyond the author specified above. def developers = [ [name: "Sachin Verma", email: "sachin.verma@tothenew.com"], [name: "Neha Gupta", email: "neha.gupta@tothenew.com"] ] - - // Location of the plugin's issue tracker. - def issueManagement = [ system: "JIRA", url: "https://github.com/pedjak/grails-csv/issues" ] - - // Online location of the plugin's browseable source code. - def scm = [ url: "https://github.com/pedjak/grails-csv/" ] - - Closure doWithSpring() { {-> - // TODO Implement runtime spring config (optional) - } - } + def issueManagement = [system: "JIRA", url: "https://github.com/pedjak/grails-csv/issues"] + def scm = [url: "https://github.com/pedjak/grails-csv/"] void doWithDynamicMethods() { - // TODO Implement registering dynamic methods to classes (optional) CSVReader.metaClass.eachLine = { closure -> CSVReaderUtils.eachLine((CSVReader) delegate, closure) } - File.metaClass.eachCsvLine = {Closure closure -> + File.metaClass.eachCsvLine = { Closure closure -> CSVReaderUtils.eachLine((File) delegate, closure) } - File.metaClass.toCsvReader = {Map settingsMap -> - return CSVReaderUtils.toCsvReader((File)delegate, settingsMap) + File.metaClass.toCsvReader = { Map settingsMap -> + return CSVReaderUtils.toCsvReader((File) delegate, settingsMap) } - File.metaClass.toCsvMapReader = {Map settingsMap -> - return new CSVMapReader(new FileReader(delegate),settingsMap) + File.metaClass.toCsvMapReader = { Map settingsMap -> + return new CSVMapReader(new FileReader(delegate), settingsMap) } - InputStream.metaClass.eachCsvLine = {Closure closure -> + InputStream.metaClass.eachCsvLine = { Closure closure -> CSVReaderUtils.eachLine((InputStream) delegate, closure) } - InputStream.metaClass.toCsvReader = {Map settingsMap -> - return CSVReaderUtils.toCsvReader((InputStream)delegate, settingsMap) + InputStream.metaClass.toCsvReader = { Map settingsMap -> + return CSVReaderUtils.toCsvReader((InputStream) delegate, settingsMap) } - Reader.metaClass.eachCsvLine = {Closure closure -> - CSVReaderUtils.eachLine((Reader)delegate, closure) + Reader.metaClass.eachCsvLine = { Closure closure -> + CSVReaderUtils.eachLine((Reader) delegate, closure) } - Reader.metaClass.toCsvReader = {Map settingsMap -> - return CSVReaderUtils.toCsvReader((Reader)delegate, settingsMap) + Reader.metaClass.toCsvReader = { Map settingsMap -> + return CSVReaderUtils.toCsvReader((Reader) delegate, settingsMap) } - Reader.metaClass.toCsvMapReader = {Map settingsMap -> - return new CSVMapReader(delegate,settingsMap) + Reader.metaClass.toCsvMapReader = { Map settingsMap -> + return new CSVMapReader(delegate, settingsMap) } - String.metaClass.eachCsvLine = {Closure closure -> + String.metaClass.eachCsvLine = { Closure closure -> CSVReaderUtils.eachLine((String) delegate, closure) } - String.metaClass.toCsvReader = {Map settingsMap -> - return CSVReaderUtils.toCsvReader((String)delegate, settingsMap) + String.metaClass.toCsvReader = { Map settingsMap -> + return CSVReaderUtils.toCsvReader((String) delegate, settingsMap) } - String.metaClass.toCsvMapReader = {Map settingsMap -> - return new CSVMapReader(new StringReader(delegate),settingsMap) + String.metaClass.toCsvMapReader = { Map settingsMap -> + return new CSVMapReader(new StringReader(delegate), settingsMap) } grailsApplication.controllerClasses.each { @@ -159,12 +133,7 @@ class CsvGrailsPlugin extends Plugin { } } - void doWithApplicationContext() { - // TODO Implement post initialization spring config (optional) - } - void onChange(Map event) { - // TODO Implement code that is executed when any artefact that this plugin is // watching is modified and reloaded. The event contains: event.source, if (grailsApplication.isControllerClass(event.source)) { event.source.metaClass.renderCsv = renderCsvMethod @@ -172,18 +141,12 @@ class CsvGrailsPlugin extends Plugin { } void onConfigChange(Map event) { - // TODO Implement code that is executed when the project configuration changes. // The event is the same as for 'onChange'. if (grailsApplication.isControllerClass(event.source)) { event.source.metaClass.renderCsv = renderCsvMethod } } - void onShutdown(Map event) { - // TODO Implement code that is executed when the application shuts down (optional) - } - - def renderCsvMethod = { Map args, Closure definition -> new RenderCsvMethod(delegate).call(args, definition) false diff --git a/src/main/groovy/grails/plugins/csv/controller/RenderCsvMethod.groovy b/src/main/groovy/grails/plugins/csv/controller/RenderCsvMethod.groovy index b454eec..6c5f725 100644 --- a/src/main/groovy/grails/plugins/csv/controller/RenderCsvMethod.groovy +++ b/src/main/groovy/grails/plugins/csv/controller/RenderCsvMethod.groovy @@ -3,28 +3,22 @@ package grails.plugins.csv.controller import grails.plugins.csv.CSVWriter class RenderCsvMethod { - - final controller + final controller RenderCsvMethod(controller) { - this.controller = controller - } - - void call(Map args, Closure columns) { - if (args.rows == null) { - throw new IllegalArgumentException("The 'rows' argument must be provided") - } - - def response = controller.response - - if (args.filename) { - def classifier = (args.attachment == false) ? 'inline' : 'attachment' - response.setHeader("Content-Disposition", "$classifier; filename=\"$args.filename\";") - } - - response.setContentType("text/csv") - - new CSVWriter(response.writer, columns).writeAll(args.rows) - } - + this.controller = controller + } + + void call(Map args, Closure columns) { + if (args.rows == null) { + throw new IllegalArgumentException("The 'rows' argument must be provided") + } + def response = controller.response + if (args.filename) { + String classifier = (args.attachment == false) ? 'inline' : 'attachment' + response.setHeader("Content-Disposition", "$classifier; filename=\"$args.filename\";") + } + response.setContentType("text/csv") + new CSVWriter(response.writer, columns).writeAll(args.rows) + } } \ No newline at end of file diff --git a/src/main/resources/META-INF/grails.factories b/src/main/resources/META-INF/grails.factories deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/resources/fileTest.csv b/src/main/resources/fileTest.csv deleted file mode 100644 index f33b752..0000000 --- a/src/main/resources/fileTest.csv +++ /dev/null @@ -1,3 +0,0 @@ -a, "nested, commas", and a line "spanning -a, few, -lines", test \ No newline at end of file diff --git a/src/main/resources/mapTest.csv b/src/main/resources/mapTest.csv deleted file mode 100644 index 7efd364..0000000 --- a/src/main/resources/mapTest.csv +++ /dev/null @@ -1,3 +0,0 @@ -col1,col2,col3 -"val1",val2,"val3" -"10",20,"30,3"