commit aeee81544c6d2881ccf02458fcef1f6ba1c9c169 Author: Erik C. Thauvin Date: Mon Jan 18 13:22:10 2016 -0800 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d7290a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +**/.idea/dictionaries +**/.idea/gradle.xml +**/.idea/libraries +**/.idea/tasks.xml +**/.idea/workspace.xml +*.iws +.DS_Store +.classpath +.gradle +.nb-gradle +.project +.settings +/bin +/build +/deploy +/dist +/gen +/local.properties +/out +/proguard-project.txt +/project.properties +/test-output +Thumbs.db +ehthumbs.db \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..a872926 --- /dev/null +++ b/build.gradle @@ -0,0 +1,98 @@ +apply plugin: 'java' +apply plugin: 'idea' +apply plugin: 'maven' + +defaultTasks 'deploy' + +version = '1.0' + +def deployDir = 'deploy' +def isRelease = 'release' in gradle.startParameter.taskNames +def mavenGroupId = 'net.thauvin.erik' +//def buildProps = 'buildnumber.properties' +//def buildProp = 'build' + +[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + compile 'org.apache.velocity:velocity:1.7' + testCompile 'org.testng:testng:+' +} + +test { + useTestNG() +} + +compileJava { + /* + doFirst { + if (isRelease) + { + ant.propertyfile(file: buildProps) { + entry(key: buildProp, + type: 'int', + default: '-1', + operation: '+') + } + } + } + */ +} + + +jar { + /* + doFirst { + def props = new Properties() + file(buildProps).withInputStream { stream -> props.load(stream) } + project.version = version + '.' + props.get(buildProp) + } + */ + archiveName = archiveName.toLowerCase() +} + +clean { + delete deployDir +} + +task copyToDeploy(type: Copy) { + from(configurations.runtime) { + exclude 'servlet-api-*.jar' + exclude 'jsp-api-*.jar' + } + from jar + into deployDir +} + +task deploy(dependsOn: ['build', 'copyToDeploy']) { + description = "Copies all needed files to the ${deployDir} directory." + group = "Publishing" + outputs.dir deployDir + inputs.files copyToDeploy + mustRunAfter clean +} + +uploadArchives { + repositories { + mavenDeployer { + repository(url: mavenLocal().url) + pom.artifactId = rootProject.name.toLowerCase() + pom.groupId = mavenGroupId + } + } +} + +task wrapper(type: Wrapper) { + gradleVersion = gradle.gradleVersion +} + +task release(dependsOn: ['deploy', 'wrapper', 'uploadArchives']) { + group = "Publishing" + description = "Releases new version." + isRelease = true +} \ No newline at end of file diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..d7290a0 --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,24 @@ +**/.idea/dictionaries +**/.idea/gradle.xml +**/.idea/libraries +**/.idea/tasks.xml +**/.idea/workspace.xml +*.iws +.DS_Store +.classpath +.gradle +.nb-gradle +.project +.settings +/bin +/build +/deploy +/dist +/gen +/local.properties +/out +/proguard-project.txt +/project.properties +/test-output +Thumbs.db +ehthumbs.db \ No newline at end of file diff --git a/example/build.gradle b/example/build.gradle new file mode 100644 index 0000000..97d7c03 --- /dev/null +++ b/example/build.gradle @@ -0,0 +1,94 @@ +plugins { + id "com.ewerk.gradle.plugins.annotation-processor" version "1.0.2" +} +apply plugin: 'java' +apply plugin: 'idea' +apply plugin: 'application' + +defaultTasks 'run' + +def isRelease = 'release' in gradle.startParameter.taskNames +def deployDir = 'deploy' + +def getVersion(isIncrement = false) +{ + def propsFile = 'version.properties' + def majorProp = 'version.major' + def minorProp = 'version.minor' + def patchProp = 'version.patch' + def metaProp = 'version.buildmeta' + def preProp = 'version.prerelease' + if (isIncrement) + { + ant.propertyfile(file: propsFile) { + entry(key: patchProp, + type: 'int', + default: '-1', + operation: '+') + } + } + def p = new Properties() + file(propsFile).withInputStream { stream -> p.load(stream) } + def metadata = p.getProperty(metaProp, '') + def prerelease = p.getProperty(preProp, '') + return (p.getProperty(majorProp, '1') + '.' + p.getProperty(minorProp, '0') + '.' + p.getProperty(patchProp, '0') + + (prerelease.length() > 0 ? '-' + prerelease : '') + (metadata.length() > 0 ? '+' + metadata : '')) +} + +version = getVersion() + +mainClassName = 'net.thauvin.erik.semver.example.Example' +[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + compile "net.thauvin.erik:semver:+" +} + +annotationProcessor { + project.version = getVersion(isRelease) + library "net.thauvin.erik:semver:+" + processor "net.thauvin.erik.semver.VersionProcessor" +} + +compileJava { + options.compilerArgs << "-proc:none" +} + +jar { + manifest.attributes('Main-Class': mainClassName) +} + +clean { + delete deployDir +} + + +task copyToDeploy(type: Copy) { + from jar + into deployDir +} + +task deploy(dependsOn: ['build', 'copyToDeploy']) { + description = "Copies all needed files to the ${deployDir} directory." + group = "Publishing" + outputs.dir deployDir + inputs.files copyToDeploy + mustRunAfter clean +} + + +task release(dependsOn: ['deploy', 'wrapper']) { + group = "Publishing" + description = "Releases new version." + isRelease = true +} + +task wrapper(type: Wrapper) { + gradleVersion = gradle.gradleVersion +} + diff --git a/example/example.iml b/example/example.iml new file mode 100644 index 0000000..6f7fa8e --- /dev/null +++ b/example/example.iml @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/gradle/wrapper/gradle-wrapper.jar b/example/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..13372ae Binary files /dev/null and b/example/gradle/wrapper/gradle-wrapper.jar differ diff --git a/example/gradle/wrapper/gradle-wrapper.properties b/example/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..0fb6b87 --- /dev/null +++ b/example/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Jan 17 00:40:16 PST 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip diff --git a/example/gradlew b/example/gradlew new file mode 100644 index 0000000..9d82f78 --- /dev/null +++ b/example/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 "$@" diff --git a/example/gradlew.bat b/example/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/example/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 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 diff --git a/example/settings.gradle b/example/settings.gradle new file mode 100644 index 0000000..9c6dad5 --- /dev/null +++ b/example/settings.gradle @@ -0,0 +1,19 @@ +/* + * This settings file was auto generated by the Gradle buildInit task + * by 'erik' at '1/14/16 4:59 PM' with Gradle 2.10 + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at https://docs.gradle.org/2.10/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'example' diff --git a/example/src/generated/java/net/thauvin/erik/semver/example/GeneratedVersion.java b/example/src/generated/java/net/thauvin/erik/semver/example/GeneratedVersion.java new file mode 100644 index 0000000..7397269 --- /dev/null +++ b/example/src/generated/java/net/thauvin/erik/semver/example/GeneratedVersion.java @@ -0,0 +1,92 @@ +/* + * This file is automatically generated by the Semantic Version Annotation Processor. + * Do not modify this file -- YOUR CHANGES WILL BE ERASED! + */ +package net.thauvin.erik.semver.example; + +import java.util.Date; + +/** + * This class provides semantic version information. + * + * @author Semantic Version Annotation Processor + */ +public final class GeneratedVersion { + private final static String buildmeta = ""; + private final static Date date = new Date(1453146881481L); + private final static int major = 3; + private final static int minor = 1; + private final static int patch = 35; + private final static String prerelease = "beta"; + + /** + * Returns the build date. + * + * @return The build date. + */ + public static Date getBuildDate() { + return date; + } + + /** + * Returns the full version. + * + * @return The full version string. + */ + public static String getVersion() { + return "" + getMajor() + '.' + getMinor() + '.' + getPatch() + getPreRelease() + getBuildMetadata(); + } + + /** + * Returns the major version. + * + * @return The major version. + */ + public static int getMajor() { + return major; + } + + /** + * Returns the minor version. + * + * @return The minor version. + */ + public static int getMinor() { + return minor; + } + + /** + * Returns the patch version. + * + * @return The patch version. + */ + public static int getPatch() { + return patch; + } + + /** + * Returns the pre-release version. + * + * @return The pre-release version, if any. + */ + public static String getPreRelease() { + if (prerelease.length() > 0) { + return '-' + prerelease; + } + + return ""; + } + + /** + * Returns the build metadata. + * + * @return The build metadata, if any. + */ + public static String getBuildMetadata() { + if (buildmeta.length() > 0) { + return '+' + buildmeta; + } + + return ""; + } +} \ No newline at end of file diff --git a/example/src/main/java/net/thauvin/erik/semver/example/Example.java b/example/src/main/java/net/thauvin/erik/semver/example/Example.java new file mode 100644 index 0000000..560b962 --- /dev/null +++ b/example/src/main/java/net/thauvin/erik/semver/example/Example.java @@ -0,0 +1,57 @@ +/* + * Example.java + * + * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.semver.example; + +import net.thauvin.erik.semver.Version; + +import java.text.SimpleDateFormat; + +/** + * The Example class. + * + * @author Erik C. Thauvin + * @created 2016-01-13 + * @since 1.0 + */ +@Version(properties = "version.properties") +public class Example +{ + public static void main(final String... args) + { + final SimpleDateFormat sdf = new SimpleDateFormat("'Built on' EEE, d MMM yyyy 'at' HH:mm:ss z"); + + System.out.println(Example.class.getSimpleName() + ' ' + GeneratedVersion.getVersion()); + System.out.println(sdf.format(GeneratedVersion.getBuildDate())); + } +} \ No newline at end of file diff --git a/example/version.properties b/example/version.properties new file mode 100644 index 0000000..a59576e --- /dev/null +++ b/example/version.properties @@ -0,0 +1,6 @@ +#Mon, 18 Jan 2016 00:09:19 -0800 +version.major=3 +version.minor=1 +version.patch=35 +version.buildmeta= +version.prerelease=beta \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..13372ae Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..5b19cb3 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Jan 16 15:10:14 PST 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 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 "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /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 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 diff --git a/semver.iml b/semver.iml new file mode 100644 index 0000000..9708fb2 --- /dev/null +++ b/semver.iml @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/semver.ipr b/semver.ipr new file mode 100644 index 0000000..2420a7d --- /dev/null +++ b/semver.ipr @@ -0,0 +1,608 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..135beeb --- /dev/null +++ b/settings.gradle @@ -0,0 +1,19 @@ +/* + * This settings file was auto generated by the Gradle buildInit task + * by 'erik' at '1/13/16 1:03 PM' with Gradle 2.10 + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at https://docs.gradle.org/2.10/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'semver' diff --git a/src/main/java/net/thauvin/erik/semver/Constants.java b/src/main/java/net/thauvin/erik/semver/Constants.java new file mode 100644 index 0000000..31e8496 --- /dev/null +++ b/src/main/java/net/thauvin/erik/semver/Constants.java @@ -0,0 +1,79 @@ +/* + * Constants.java + * + * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.semver; + +/** + * The Constants class. + * + * @author Erik C. Thauvin + * @created 2016-01-13 + * @since 1.0 + */ +public final class Constants +{ + public static final String DEFAULT_CLASS_NAME = "GeneratedVersion"; + + public static final int DEFAULT_MAJOR = 1; + + public static final int DEFAULT_MINOR = 0; + + public static final int DEFAULT_PATCH = 0; + + public static final String DEFAULT_TEMPLATE = "version.vm"; + + public static final String EMPTY = ""; + + public static final String KEY_VERSION_BUILDMETA = "version.buildmeta"; + + public static final String KEY_VERSION_MAJOR = "version.major"; + + public static final String KEY_VERSION_MINOR = "version.minor"; + + public static final String KEY_VERSION_PATCH = "version.patch"; + + public static final String KEY_VERSION_PRERELEASE = "version.prerelease"; + + public static final String VELOCITY_PROPERTIES = "velocity.properties"; + + /** + * Disables the default constructor. + * + * @throws UnsupportedOperationException if an error occurred. if the constructor is called. + */ + private Constants() + throws UnsupportedOperationException + { + throw new UnsupportedOperationException("Illegal constructor call."); + } +} \ No newline at end of file diff --git a/src/main/java/net/thauvin/erik/semver/Version.java b/src/main/java/net/thauvin/erik/semver/Version.java new file mode 100644 index 0000000..84d7bb3 --- /dev/null +++ b/src/main/java/net/thauvin/erik/semver/Version.java @@ -0,0 +1,77 @@ +/* + * Version.java + * + * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.semver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The Version class. + * + * @author Erik C. Thauvin + * @created 2016-01-13 + * @since 1.0 + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface Version +{ + String buildmeta() default Constants.EMPTY; + + String buildmetaKey() default Constants.KEY_VERSION_BUILDMETA; + + String className() default Constants.DEFAULT_CLASS_NAME; + + int major() default Constants.DEFAULT_MAJOR; + + String majorKey() default Constants.KEY_VERSION_MAJOR; + + int minor() default Constants.DEFAULT_MINOR; + + String minorKey() default Constants.KEY_VERSION_MINOR; + + int patch() default Constants.DEFAULT_PATCH; + + String patchKey() default Constants.KEY_VERSION_PATCH; + + String prerelease() default Constants.EMPTY; + + String prereleaseKey() default Constants.KEY_VERSION_PRERELEASE; + + String properties() default Constants.EMPTY; + + String template() default Constants.DEFAULT_TEMPLATE; +} \ No newline at end of file diff --git a/src/main/java/net/thauvin/erik/semver/VersionInfo.java b/src/main/java/net/thauvin/erik/semver/VersionInfo.java new file mode 100644 index 0000000..d53e998 --- /dev/null +++ b/src/main/java/net/thauvin/erik/semver/VersionInfo.java @@ -0,0 +1,135 @@ +/* + * VersionInfo.java + * + * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.semver; + +/** + * The VersionInfo class. + * + * @author Erik C. Thauvin + * @created 2016-01-16 + * @since 1.0 + */ +public class VersionInfo +{ + private final long epoch = System.currentTimeMillis(); + + private String buildmeta; + + private int major; + + private int minor; + + private int patch; + + private String prerelease; + + public VersionInfo() + { + major = Constants.DEFAULT_MAJOR; + minor = Constants.DEFAULT_MINOR; + patch = Constants.DEFAULT_PATCH; + buildmeta = Constants.EMPTY; + prerelease = Constants.EMPTY; + } + + public VersionInfo(final Version version) + { + major = version.major(); + minor = version.minor(); + patch = version.patch(); + buildmeta = version.buildmeta(); + prerelease = version.prerelease(); + } + + public String getBuildMetadata() + { + return buildmeta; + } + + public void setBuildMetadata(final String buildmeta) + { + this.buildmeta = buildmeta; + } + + public long getEpoch() + { + return epoch; + } + + public int getMajor() + { + return major; + } + + public void setMajor(final int major) + { + this.major = major; + } + + public int getMinor() + { + return minor; + } + + public void setMinor(final int minor) + { + this.minor = minor; + } + + public int getPatch() + { + return patch; + } + + public void setPatch(final int patch) + { + this.patch = patch; + } + + public String getPreRelease() + { + return prerelease; + } + + public void setPreRelease(final String prerelease) + { + this.prerelease = prerelease; + } + + public String getVersion() + { + return "" + major + '.' + minor + '.' + patch + (prerelease.length() > 0 ? '-' + prerelease : "") + ( + buildmeta.length() > 0 ? '+' + buildmeta : ""); + } +} \ No newline at end of file diff --git a/src/main/java/net/thauvin/erik/semver/VersionProcessor.java b/src/main/java/net/thauvin/erik/semver/VersionProcessor.java new file mode 100644 index 0000000..1869cb6 --- /dev/null +++ b/src/main/java/net/thauvin/erik/semver/VersionProcessor.java @@ -0,0 +1,252 @@ +/* + * VersionProcessor.java + * + * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.semver; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import java.io.*; +import java.net.URL; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +/** + * The VersionProcessor class. + * + * @author Erik C. Thauvin + * @created 2016-01-13 + * @since 1.0 + */ +public class VersionProcessor extends AbstractProcessor +{ + private Filer filer; + + private Messager messager; + + private void error(final String s) + { + log(Diagnostic.Kind.ERROR, s); + } + + private void error(final String s, final Throwable t) + { + messager.printMessage(Diagnostic.Kind.ERROR, (t != null ? t.toString() : s)); + } + + private VersionInfo findValues(final Version version) + throws IOException + { + final VersionInfo versionInfo; + + if (version.properties().length() > 0) + { + versionInfo = new VersionInfo(); + + final File propsFile = new File(version.properties()); + if (propsFile.exists()) + { + note("Found properties: " + propsFile); + final Properties p = new Properties(); + + try (FileReader reader = new FileReader(propsFile)) + { + p.load(reader); + + versionInfo.setMajor(parseIntProperty(p, version.majorKey(), Constants.DEFAULT_MAJOR)); + versionInfo.setMinor(parseIntProperty(p, version.minorKey(), Constants.DEFAULT_MINOR)); + versionInfo.setPatch(parseIntProperty(p, version.patchKey(), Constants.DEFAULT_PATCH)); + versionInfo.setBuildMetadata(p.getProperty(version.buildmetaKey(), Constants.EMPTY)); + versionInfo.setPreRelease(p.getProperty(version.prereleaseKey(), Constants.EMPTY)); + } + } + else + { + error("Could not find: " + propsFile); + throw new FileNotFoundException(propsFile + " (The system cannot find the file specified)"); + } + } + else + { + versionInfo = new VersionInfo(version); + } + + return versionInfo; + } + + /** + * {@inheritDoc} + */ + @Override + public Set getSupportedAnnotationTypes() + { + final Set result = new HashSet<>(); + result.add(Version.class.getCanonicalName()); + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public SourceVersion getSupportedSourceVersion() + { + return SourceVersion.RELEASE_8; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized void init(final ProcessingEnvironment processingEnv) + { + super.init(processingEnv); + filer = processingEnv.getFiler(); + messager = processingEnv.getMessager(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean process(final Set annotations, final RoundEnvironment roundEnv) + { + for (final Element annotatedElement : roundEnv.getElementsAnnotatedWith(Version.class)) + { + final Version version = annotatedElement.getAnnotation(Version.class); + if (annotatedElement.getKind() == ElementKind.CLASS) + { + final Element enclosing = annotatedElement.getEnclosingElement(); + if (enclosing.getKind() == ElementKind.PACKAGE) + { + final PackageElement packageElement = (PackageElement) enclosing; + try + { + final VersionInfo versionInfo = findValues(version); + note("Found version: " + versionInfo.getVersion()); + writeTemplate(packageElement.getQualifiedName().toString(), + version.className(), + versionInfo, + version.template()); + } + catch (IOException e) + { + error("IOException occurred while running annotation processor", e); + } + } + } + } + return true; + } + + private void log(final Diagnostic.Kind kind, final String s) + { + messager.printMessage(kind, '[' + VersionProcessor.class.getSimpleName() + "] " + s); + } + + private void note(final String s) + { + log(Diagnostic.Kind.NOTE, s); + } + + private int parseIntProperty(final Properties p, final String property, final int defaultValue) + { + try + { + return Integer.parseInt(p.getProperty(property, "" + defaultValue)); + } + catch (NumberFormatException ignore) + { + warn("Invalid property value: " + property); + return defaultValue; + } + } + + private void warn(final String s) + { + log(Diagnostic.Kind.WARNING, s); + } + + private void writeTemplate(final String packageName, final String className, final VersionInfo versionInfo, + final String template) + throws IOException + { + final Properties p = new Properties(); + final URL url = this.getClass().getClassLoader().getResource(Constants.VELOCITY_PROPERTIES); + + if (url != null) + { + p.load(url.openStream()); + + final VelocityEngine ve = new VelocityEngine(p); + ve.init(); + + final VelocityContext vc = new VelocityContext(); + vc.put("packageName", packageName); + vc.put("className", className); + vc.put("buildmeta", versionInfo.getBuildMetadata()); + vc.put("epoch", versionInfo.getEpoch()); + vc.put("patch", versionInfo.getPatch()); + vc.put("major", versionInfo.getMajor()); + vc.put("minor", versionInfo.getMinor()); + vc.put("prerelease", versionInfo.getPreRelease()); + + final Template vt = ve.getTemplate(template); + + note("Loaded template: " + vt.getName()); + + final JavaFileObject jfo = filer.createSourceFile(packageName + '.' + className); + try (final Writer writer = jfo.openWriter()) + { + vt.merge(vc, writer); + } + + note("Generated source: " + jfo.getName()); + } + else + { + error("Could not load '" + Constants.VELOCITY_PROPERTIES + "' from jar."); + } + + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 0000000..44488e0 --- /dev/null +++ b/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +net.thauvin.erik.semver.VersionProcessor diff --git a/src/main/resources/velocity.properties b/src/main/resources/velocity.properties new file mode 100644 index 0000000..ba28119 --- /dev/null +++ b/src/main/resources/velocity.properties @@ -0,0 +1,4 @@ +runtime.log.logsystem.class = org.apache.velocity.runtime.log.SystemLogChute +resource.loader = file, class +file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader +class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader \ No newline at end of file diff --git a/src/main/resources/version.vm b/src/main/resources/version.vm new file mode 100644 index 0000000..6157a52 --- /dev/null +++ b/src/main/resources/version.vm @@ -0,0 +1,92 @@ +/* + * This file is automatically generated by the Semantic Version Annotation Processor. + * Do not modify this file -- YOUR CHANGES WILL BE ERASED! + */ +package ${packageName}; + +import java.util.Date; + +/** + * This class provides semantic version information. + * + * @author Semantic Version Annotation Processor + */ +public final class ${className} { + private final static String buildmeta = "${buildmeta}"; + private final static Date date = new Date(${epoch}L); + private final static int major = ${major}; + private final static int minor = ${minor}; + private final static int patch = ${patch}; + private final static String prerelease = "${prerelease}"; + + /** + * Returns the build date. + * + * @return The build date. + */ + public static Date getBuildDate() { + return date; + } + + /** + * Returns the full version. + * + * @return The full version string. + */ + public static String getVersion() { + return "" + getMajor() + '.' + getMinor() + '.' + getPatch() + getPreRelease() + getBuildMetadata(); + } + + /** + * Returns the major version. + * + * @return The major version. + */ + public static int getMajor() { + return major; + } + + /** + * Returns the minor version. + * + * @return The minor version. + */ + public static int getMinor() { + return minor; + } + + /** + * Returns the patch version. + * + * @return The patch version. + */ + public static int getPatch() { + return patch; + } + + /** + * Returns the pre-release version. + * + * @return The pre-release version, if any. + */ + public static String getPreRelease() { + if (prerelease.length() > 0) { + return '-' + prerelease; + } + + return ""; + } + + /** + * Returns the build metadata. + * + * @return The build metadata, if any. + */ + public static String getBuildMetadata() { + if (buildmeta.length() > 0) { + return '+' + buildmeta; + } + + return ""; + } +} \ No newline at end of file