diff --git a/.idea/modules/binary-plugin-assignment-done.main.iml b/.idea/modules/binary-plugin-assignment-done.main.iml
new file mode 100644
index 0000000..4a4ce55
--- /dev/null
+++ b/.idea/modules/binary-plugin-assignment-done.main.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/binary-plugin-example.main.iml b/.idea/modules/binary-plugin-example.main.iml
new file mode 100644
index 0000000..4a4ce55
--- /dev/null
+++ b/.idea/modules/binary-plugin-example.main.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/README.md b/binary-plugin/README.md
index d99b7bb..e54567b 100644
--- a/binary-plugin/README.md
+++ b/binary-plugin/README.md
@@ -4,7 +4,9 @@ This directory contains assignments and examples with the focus on standalone Gr
| Module | Description | Lectures |
| ------------- |:-------------:|-------------:|
-| **[binary-plugin-example](binary-plugin-example)** | Example showing necessary components of binary plugin, utilities that `gradle-java-plugin` plugin offers to ease up binary plugin compilation and packaging. Publishing of plugin with `maven-publish` plugin to local, private/remote Maven repository or [Gradle Plugin Portal](https://plugins.gradle.org/) is also covered. | [Binary Plugin](https://www.udemy.com/course/gradle-development/learn/lecture/28264772#overview)
[Private Maven Publish](https://www.udemy.com/course/gradle-development/learn/lecture/29429886)|
+| **[binary-plugin-example](binary-plugin-example)** | Example showing necessary components of binary plugin, utilities that `gradle-java-plugin` plugin offers to ease up binary plugin compilation and packaging. Publishing of plugin with `maven-publish` plugin to local, private/remote Maven repository or [Gradle Plugin Portal](https://plugins.gradle.org/) is also covered. | [Binary Plugin](https://www.udemy.com/course/gradle-development/learn/lecture/28264772#overview)
[Private Maven Publish](https://www.udemy.com/course/gradle-development/learn/lecture/29429886)|
+| **[binary-plugin-assignment-done](binary-plugin-assignment-done)** | Solved assignment for the binary plugin lecture. It shows how can script plugin from the previous lectures for sorting files be overwritten into binary plugin.| [Binary Plugin Assignment](https://www.udemy.com/course/gradle-development/learn/practice/1361294) |
+| **[binary-plugin-assignment-test-project](binary-plugin-assignment-test-project)** | Simple project that demonstrates application of the binary plugin created in binary-plugin-assignment-done. | [Binary Plugin Assignment](https://www.udemy.com/course/gradle-development/learn/practice/1361294) |
# Resources
diff --git a/binary-plugin/binary-plugin-assignment-done/.gitignore b/binary-plugin/binary-plugin-assignment-done/.gitignore
new file mode 100644
index 0000000..2677823
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.gitignore
@@ -0,0 +1,152 @@
+
+# Created by https://www.toptal.com/developers/gitignore/api/java,gradle,intellij
+# Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle,intellij
+
+### Intellij ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+# https://plugins.jetbrains.com/plugin/7973-sonarlint
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator-enh.xml
+.idea/**/markdown-navigator/
+
+# Cache file creation bug
+# See https://youtrack.jetbrains.com/issue/JBR-2257
+.idea/$CACHE_FILE$
+
+# CodeStream plugin
+# https://plugins.jetbrains.com/plugin/12206-codestream
+.idea/codestream.xml
+
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+### Gradle ###
+.gradle
+build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# Cache of project
+.gradletasknamecache
+
+# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
+# gradle/wrapper/gradle-wrapper.properties
+
+### Gradle Patch ###
+**/build/
+
+# End of https://www.toptal.com/developers/gitignore/api/java,gradle,intellij
diff --git a/binary-plugin/binary-plugin-assignment-done/.idea/.gitignore b/binary-plugin/binary-plugin-assignment-done/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/binary-plugin/binary-plugin-assignment-done/.idea/checkstyle-idea.xml b/binary-plugin/binary-plugin-assignment-done/.idea/checkstyle-idea.xml
new file mode 100644
index 0000000..3460331
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.idea/checkstyle-idea.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/.idea/compiler.xml b/binary-plugin/binary-plugin-assignment-done/.idea/compiler.xml
new file mode 100644
index 0000000..b73660a
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/.idea/jarRepositories.xml b/binary-plugin/binary-plugin-assignment-done/.idea/jarRepositories.xml
new file mode 100644
index 0000000..fdc392f
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/.idea/misc.xml b/binary-plugin/binary-plugin-assignment-done/.idea/misc.xml
new file mode 100644
index 0000000..565e017
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/.idea/modules/binary-plugin-example.iml b/binary-plugin/binary-plugin-assignment-done/.idea/modules/binary-plugin-example.iml
new file mode 100644
index 0000000..63c7f19
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.idea/modules/binary-plugin-example.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/.idea/modules/binary-plugin-example.main.iml b/binary-plugin/binary-plugin-assignment-done/.idea/modules/binary-plugin-example.main.iml
new file mode 100644
index 0000000..4a4ce55
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.idea/modules/binary-plugin-example.main.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/.idea/vcs.xml b/binary-plugin/binary-plugin-assignment-done/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/README.md b/binary-plugin/binary-plugin-assignment-done/README.md
new file mode 100644
index 0000000..ac5d1d0
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/README.md
@@ -0,0 +1,35 @@
+# Binary Plugin Assignment Done
+
+## Implementation
+
+This project shows you one possible solution for the Binary Plugin Assignment:
+- [Binary Plugin Assignment - Gradle Plugin Development](https://www.udemy.com/course/gradle-development/learn/practice/1361294)
+
+Solution for the assignment is taking over the functionality from Precompiled Plugin Assignment.
+Code is written in Java language.
+Plugin logic is broken down in two tasks:
+- [SortFilesTask](src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/SortFilesTask.java) and
+- [DeleteTask](src/main/java/com/rivancic/gradle/plugin/files/tasks/delete/DeleteTask.java)
+
+While sorting algorithm is extracted further into [FileDirectoryMapper](src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryMapper.java) implementation classes.
+
+In [build.gradle](build.gradle) plugin ID: `com.rivancic.files-plugin` is defined withing the `gradlePlugin{}` block with the help of `java-gradle-plugin`.
+implementationClass property points to `com.rivancic.gradle.plugin.files.FilesPlugin`.
+
+## Testing
+
+For testing the solution you can publish plugin with the `maven-publish` plugin to local Maven repository and then apply
+it in the testing project as:
+```
+plugins {
+ id "com.rivancic.files-plugin" version "0.1.0"
+}
+```
+
+I have created testing project just for this purpose in [binary-plugin-assignment-test-project](../binary-plugin-assignment-test-project)
+
+## Resources
+
+[Gradle Plugin Development Plugin (Gradle Userguide)](https://docs.gradle.org/current/userguide/java_gradle_plugin.html)
+
+[Developing Custom Gradle Plugins (Gradle Userguide)](https://docs.gradle.org/current/userguide/custom_plugins.html)
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/build.gradle b/binary-plugin/binary-plugin-assignment-done/build.gradle
new file mode 100644
index 0000000..a78c763
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/build.gradle
@@ -0,0 +1,48 @@
+/**
+ * java-gradle-plugin - Core Gradle Plugin, Java Gradle Plugin.
+ * It simplifies compilation and publishing of Gradle binary plugins.
+ *
+ * maven-publish - Core Gradle Plugin, Java Gradle PluginMaven Publish
+ * plugin will make it possible to publish artifacts to Maven repositories.
+ */
+plugins {
+ id "java-gradle-plugin"
+ id "maven-publish"
+}
+
+
+
+/**
+ * An extension for java-gradle-plugin in which we define all the plugins that this project will create.
+ * Each plugin should have name, id and an implementationClass defined.
+ * During the jar task it will be verified that plugin descriptor is correct. implementationClass has to be an existing
+ * class implementing Plugin interface.
+ */
+gradlePlugin {
+ plugins {
+ create("filesPlugin") {
+ id = "com.rivancic.files-plugin"
+ implementationClass = "com.rivancic.gradle.plugin.files.FilesPlugin"
+ }
+ }
+}
+
+/**
+ * In publishing block we can define specific package repositories where the artifacts will be published.
+ * As in our case we have Maven Archiva running locally we specify local URL,
+ * name of the repository so that we can find publishing task easily and credentials as Archiva requires
+ * them by default.
+ */
+publishing {
+ repositories {
+ maven {
+ url = "http://localhost:8080/repository/internal"
+ name = "mavenArchivaPrivate"
+ allowInsecureProtocol = true
+ credentials {
+ username = "$privateArchivaUser"
+ password = "$privateArchivaPassword"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/gradle.properties b/binary-plugin/binary-plugin-assignment-done/gradle.properties
new file mode 100644
index 0000000..735af3c
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/gradle.properties
@@ -0,0 +1,5 @@
+group 'com.rivancic'
+version '0.1.0'
+
+tasks.files.folder=files
+tasks.files.sortType=alphabet
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/gradle/wrapper/gradle-wrapper.jar b/binary-plugin/binary-plugin-assignment-done/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/binary-plugin/binary-plugin-assignment-done/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/binary-plugin/binary-plugin-assignment-done/gradle/wrapper/gradle-wrapper.properties b/binary-plugin/binary-plugin-assignment-done/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..b1159fc
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/binary-plugin/binary-plugin-assignment-done/gradlew b/binary-plugin/binary-plugin-assignment-done/gradlew
new file mode 100755
index 0000000..4f906e0
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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"`
+
+# 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" "-Xms64m"'
+
+# 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
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+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" -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\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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=`expr $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
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+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"
+
+exec "$JAVACMD" "$@"
diff --git a/binary-plugin/binary-plugin-assignment-done/gradlew.bat b/binary-plugin/binary-plugin-assignment-done/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@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 Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@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" "-Xms64m"
+
+@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 execute
+
+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 execute
+
+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
+
+: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 %*
+
+: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/binary-plugin/binary-plugin-assignment-done/settings.gradle b/binary-plugin/binary-plugin-assignment-done/settings.gradle
new file mode 100644
index 0000000..5380c98
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/settings.gradle
@@ -0,0 +1,29 @@
+/**
+ * By default only Gradle Plugin Portal is defined as a repository that provides Gradle plugins that can be applied
+ * within
plugins{}
block.
+ *
+ * If you want to specify any additional repository you have to define them in pluginManagement block within
+ * setting.gradle file. Remember pluginManagement has to be the first statement inside settings.gradle file.
+ *
+ * In definition below 3 repositories will be taken ito account when Gradle will search for defined plugin by its ID and version:
+ * - Gradle Plugin Portal,
+ * - Maven Local repository will be taken into account when Gradle
+ * - Custom defined Maven repository where Archiva server is providing the plugins.
+ */
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenLocal()
+ maven {
+ url = "http://localhost:8080/repository/internal"
+ name = "mavenArchivaPrivate"
+ allowInsecureProtocol = true
+ credentials {
+ username = "$privateArchivaUser"
+ password = "$privateArchivaPassword"
+ }
+ }
+ }
+}
+rootProject.name = 'binary-plugin-assignment-done'
+
diff --git a/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/FilesPlugin.java b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/FilesPlugin.java
new file mode 100644
index 0000000..4576909
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/FilesPlugin.java
@@ -0,0 +1,40 @@
+package com.rivancic.gradle.plugin.files;
+
+import com.rivancic.gradle.plugin.files.tasks.clean.CleanTask;
+import com.rivancic.gradle.plugin.files.tasks.sort.SortFilesTask;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+
+/**
+ * Implementation of Plugin Gradle API interface. In the {@link Plugin#apply(Object)} method we configure base plugin logic.
+ *
+ * In our case we first log lines so that we know plugin is being applied in the first place.
+ *
+ * Then we just register new tasks so that they are configured once they need to be invoked.
+ *
+ * We have to check first before adding {@link CleanTask} task as it might already be added to the project if you would apply "java" plugin to the main project.
+ *
+ * As the last part we register {@link SortFilesTask} task. Task for sorting files also depends on clean task so we always get expected result.
+ */
+public class FilesPlugin implements Plugin {
+
+ private static final String CLEAN_TASK_NAME = "clean";
+ private static final String SORT_FILES_TASK_NAME = "sortFiles";
+
+ @Override
+ public void apply(Project project) {
+
+ project.getLogger().info("=============================================================================================");
+ project.getLogger().info(" Binary Files Plugin ");
+ project.getLogger().info("=============================================================================================");
+
+ // Check if clean task is already registered. Then don't add it. As it can conflict with java clean task if java plugin is applied to the same project.
+ if (project.getTasks().findByName(CLEAN_TASK_NAME) == null) {
+ project.getTasks().register(CLEAN_TASK_NAME, CleanTask.class);
+ }
+
+ project.getTasks()
+ .register(SORT_FILES_TASK_NAME, SortFilesTask.class)
+ .configure(action -> action.dependsOn(project.getTasks().getByName(CLEAN_TASK_NAME)));
+ }
+}
diff --git a/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/clean/CleanTask.java b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/clean/CleanTask.java
new file mode 100644
index 0000000..5e9c277
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/clean/CleanTask.java
@@ -0,0 +1,15 @@
+package com.rivancic.gradle.plugin.files.tasks.clean;
+
+import org.gradle.api.tasks.Delete;
+
+public class CleanTask extends Delete {
+
+ public static final String FILES_GROUP_NAME = "files";
+ public static final String CLEAN_TASK_DESCRIPTION = "Clean build directory";
+
+ public CleanTask() {
+ setGroup(FILES_GROUP_NAME);
+ setDescription(CLEAN_TASK_DESCRIPTION);
+ delete(getProject().getLayout().getBuildDirectory());
+ }
+}
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/SortFilesTask.java b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/SortFilesTask.java
new file mode 100644
index 0000000..48c43dc
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/SortFilesTask.java
@@ -0,0 +1,66 @@
+package com.rivancic.gradle.plugin.files.tasks.sort;
+
+import com.rivancic.gradle.plugin.files.tasks.sort.mapper.FileDirectoryMapper;
+import com.rivancic.gradle.plugin.files.tasks.sort.mapper.FileDirectoryMapperFactory;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+
+/**
+ * Task is grouped into "files" group.
+ *
+ * Root folder containing files that have to be sorted is parametrized through Gradle properties with the key [tasks.files.folder].
+ * Property has to be accessed through the project.ext map as direct reference doesn't work if property key is named with the dot notation.
+ *
+ * This method sorts files from specific directory and copies them to build/files directory.
+ * Files are being sorted based on their extension, creation date or initial character. Default sorting type is by creation date.
+ * One can explicitly define sorting type with setting following property key [tasks.files.sortType] to value:
+ *
+ *
date
+ *
extension
+ *
alphabeth
+ *
+ *
+ * Files are being resolved with the Project#file() method, as this way we get correct path to the relative path.
+ * Only none hidden files are taken into consideration.
+ *
+ * Based on sorting type new subdirectory is created in build target and file is copied to matching subdirectory.
+ * Name of the subdirectory is defined with FileDirectoryMapper.
+ */
+public class SortFilesTask extends DefaultTask {
+
+ public SortFilesTask() {
+ setGroup("files");
+ setDescription("Sorts files in given directory into build/files subdirectories based on the sorting type [date, extension, alphabet]");
+ }
+
+ // action that will be executed
+ @TaskAction
+ public void apply() {
+
+ getProject().getLogger().quiet("==== Sorting Files ====");
+
+ FileDirectoryMapper fileMapper = FileDirectoryMapperFactory.getFileDirectoryMapper(getProject());
+
+ Arrays.stream(getProject().file(getProject().getExtensions().getExtraProperties().get("tasks.files.folder"))
+ .listFiles())
+ .filter(file -> file.isFile() && !file.isHidden())
+ .forEach(file -> {
+ getProject().getLogger().quiet("Filename: " + file.getName());
+ try {
+ String directory = fileMapper.getDirectory(file);
+ getProject().mkdir(getProject().getLayout().getBuildDirectory().dir("files/" + directory + "/"));
+ Files.copy(file.toPath(), getProject().getLayout().getBuildDirectory().dir("files/" + directory + "/" + file.getName()).get().getAsFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException e) {
+ getProject().getLogger().warn("Couldn't sort " + file.getName() + " file properly.");
+ }
+ });
+
+ getProject().getLogger().quiet("");
+ getProject().getLogger().quiet("=======================");
+ }
+}
diff --git a/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryAlphabetMapper.java b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryAlphabetMapper.java
new file mode 100644
index 0000000..73f0c3e
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryAlphabetMapper.java
@@ -0,0 +1,14 @@
+package com.rivancic.gradle.plugin.files.tasks.sort.mapper;
+
+import java.io.File;
+
+/**
+ * Maps file initial to alphabetical ordered directory
+ */
+public class FileDirectoryAlphabetMapper implements FileDirectoryMapper {
+
+ @Override
+ public String getDirectory(File file) {
+ return file.getName().substring(0,1);
+ }
+}
diff --git a/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryDateMapper.java b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryDateMapper.java
new file mode 100644
index 0000000..fe181b7
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryDateMapper.java
@@ -0,0 +1,22 @@
+package com.rivancic.gradle.plugin.files.tasks.sort.mapper;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.attribute.FileTime;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Maps file creation date to directory name.
+ */
+public class FileDirectoryDateMapper implements FileDirectoryMapper {
+ @Override
+ public String getDirectory(File file) throws IOException {
+ FileTime creationTime = (FileTime) Files.getAttribute(Paths.get(file.getPath()), "creationTime");
+ DateTimeFormatter fileCreationDateFormat = DateTimeFormatter.ofPattern("MM-YYYY");
+ return fileCreationDateFormat.format(Instant.ofEpochMilli(creationTime.toMillis()).atZone(ZoneOffset.UTC).toLocalDate());
+ }
+}
diff --git a/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryExtensionMapper.java b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryExtensionMapper.java
new file mode 100644
index 0000000..2166405
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryExtensionMapper.java
@@ -0,0 +1,26 @@
+package com.rivancic.gradle.plugin.files.tasks.sort.mapper;
+
+import java.io.File;
+
+/**
+ * Maps file extension to directory name.
+ */
+public class FileDirectoryExtensionMapper implements FileDirectoryMapper {
+
+ @Override
+ public String getDirectory(File file) {
+ return getExtensionOf(file.getName());
+ }
+
+ /**
+ * Get file extension from its file name.
+ *
+ * If filename is image.jpg then the method will return "jpg".
+ *
+ * @param filename from which extension will be extracted
+ * @return extension of the file
+ */
+ static String getExtensionOf(String filename) {
+ return filename.substring(filename.lastIndexOf(".") + 1);
+ }
+}
diff --git a/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryMapper.java b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryMapper.java
new file mode 100644
index 0000000..7b70960
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryMapper.java
@@ -0,0 +1,11 @@
+package com.rivancic.gradle.plugin.files.tasks.sort.mapper;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Implements mapping a file to specific directory name. The logic is based on the sorting algorithm.
+ */
+public interface FileDirectoryMapper {
+ String getDirectory(File file) throws IOException;
+}
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryMapperFactory.java b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryMapperFactory.java
new file mode 100644
index 0000000..d7c98f5
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-done/src/main/java/com/rivancic/gradle/plugin/files/tasks/sort/mapper/FileDirectoryMapperFactory.java
@@ -0,0 +1,32 @@
+package com.rivancic.gradle.plugin.files.tasks.sort.mapper;
+
+import org.gradle.api.InvalidUserDataException;
+import org.gradle.api.Project;
+
+public class FileDirectoryMapperFactory {
+
+ /**
+ * Fetches sorting type from [tasks.files.sortType] properties. If property is not present then files will be sorted by the date.
+ *
+ * @param project holding properties.
+ * @return FileDirectoryMapper that actually defines sorting algorithm
+ */
+ public static FileDirectoryMapper getFileDirectoryMapper(Project project) {
+ String sortType;
+ if (project.hasProperty("tasks.files.sortType")) {
+ sortType = project.getExtensions().getExtraProperties().get("tasks.files.sortType").toString();
+ if (sortType.equals("extension")) {
+ return new FileDirectoryExtensionMapper();
+ } else if (sortType.equals("date")) {
+ return new FileDirectoryDateMapper();
+ } else if (sortType.equals("alphabet")) {
+ return new FileDirectoryAlphabetMapper();
+ } else {
+ throw new InvalidUserDataException("Invalid property tasks.files.sortType value provided [" + sortType + "]. Valid values are ['extension','date']");
+ }
+ } else {
+ project.getLogger().quiet("Property [tasks.files.sortType] isn't set, default sorting will be done by creation date");
+ return new FileDirectoryDateMapper();
+ }
+ }
+}
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/.gitignore b/binary-plugin/binary-plugin-assignment-test-project/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/checkstyle-idea.xml b/binary-plugin/binary-plugin-assignment-test-project/.idea/checkstyle-idea.xml
new file mode 100644
index 0000000..3460331
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/checkstyle-idea.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/compiler.xml b/binary-plugin/binary-plugin-assignment-test-project/.idea/compiler.xml
new file mode 100644
index 0000000..b73660a
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/gradle.xml b/binary-plugin/binary-plugin-assignment-test-project/.idea/gradle.xml
new file mode 100644
index 0000000..611e7c8
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/gradle.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/jarRepositories.xml b/binary-plugin/binary-plugin-assignment-test-project/.idea/jarRepositories.xml
new file mode 100644
index 0000000..fdc392f
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/misc.xml b/binary-plugin/binary-plugin-assignment-test-project/.idea/misc.xml
new file mode 100644
index 0000000..565e017
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/modules/binary-plugin-example.iml b/binary-plugin/binary-plugin-assignment-test-project/.idea/modules/binary-plugin-example.iml
new file mode 100644
index 0000000..63c7f19
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/modules/binary-plugin-example.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/modules/binary-plugin-example.main.iml b/binary-plugin/binary-plugin-assignment-test-project/.idea/modules/binary-plugin-example.main.iml
new file mode 100644
index 0000000..4a4ce55
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/modules/binary-plugin-example.main.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/sonarlint/issuestore/index.pb b/binary-plugin/binary-plugin-assignment-test-project/.idea/sonarlint/issuestore/index.pb
new file mode 100644
index 0000000..bce0e0f
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/sonarlint/issuestore/index.pb
@@ -0,0 +1,7 @@
+
+X
+(gradle/wrapper/gradle-wrapper.properties,f/b/fbe448ebfc3eb2d4e308f6b8b043666f5b57235e
+s
+Csrc/main/java/com/rivancic/gradle/plugin/example/ExamplePlugin.java,4/e/4e30a613c47feee219a73e77cf4c10b886b406df
+<
+build.gradle,f/0/f07866736216be0ee2aba49e392191aeae700a35
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/uiDesigner.xml b/binary-plugin/binary-plugin-assignment-test-project/.idea/uiDesigner.xml
new file mode 100644
index 0000000..e96534f
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/.idea/vcs.xml b/binary-plugin/binary-plugin-assignment-test-project/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/README.md b/binary-plugin/binary-plugin-assignment-test-project/README.md
new file mode 100644
index 0000000..5f66586
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/README.md
@@ -0,0 +1,15 @@
+# Binary Plugin Test Project
+
+This is a helper project to test [Binary Plugin Assignment](../binary-plugin-assignment-done).
+
+Binary plugin is applied to the project in [build.gradle](build.gradle) file
+
+```groovy
+plugins {
+ id "com.rivancic.files-plugin" version "${filesPluginVersion}"
+}
+```
+
+`filesPluginVersion` is secified in [gradle.properties](gradle.properties) file.
+
+Files form `files` directory are sorted into [build/files](build/files) directory.
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/build.gradle b/binary-plugin/binary-plugin-assignment-test-project/build.gradle
new file mode 100644
index 0000000..b131e86
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/build.gradle
@@ -0,0 +1,6 @@
+plugins {
+ id "com.rivancic.files-plugin" version "${filesPluginVersion}"
+}
+
+group 'com.rivancic'
+version '0.1.0'
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/files/business.jpg b/binary-plugin/binary-plugin-assignment-test-project/files/business.jpg
new file mode 100644
index 0000000..f917733
Binary files /dev/null and b/binary-plugin/binary-plugin-assignment-test-project/files/business.jpg differ
diff --git a/binary-plugin/binary-plugin-assignment-test-project/files/scanner.wav b/binary-plugin/binary-plugin-assignment-test-project/files/scanner.wav
new file mode 100644
index 0000000..f6faf81
Binary files /dev/null and b/binary-plugin/binary-plugin-assignment-test-project/files/scanner.wav differ
diff --git a/binary-plugin/binary-plugin-assignment-test-project/files/stock.jpg b/binary-plugin/binary-plugin-assignment-test-project/files/stock.jpg
new file mode 100644
index 0000000..dee521a
Binary files /dev/null and b/binary-plugin/binary-plugin-assignment-test-project/files/stock.jpg differ
diff --git a/binary-plugin/binary-plugin-assignment-test-project/gradle.properties b/binary-plugin/binary-plugin-assignment-test-project/gradle.properties
new file mode 100644
index 0000000..476d3ba
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/gradle.properties
@@ -0,0 +1,4 @@
+filesPluginVersion=0.1.0
+
+tasks.files.folder=files
+tasks.files.sortType=alphabet
\ No newline at end of file
diff --git a/binary-plugin/binary-plugin-assignment-test-project/gradle/wrapper/gradle-wrapper.jar b/binary-plugin/binary-plugin-assignment-test-project/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/binary-plugin/binary-plugin-assignment-test-project/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/binary-plugin/binary-plugin-assignment-test-project/gradle/wrapper/gradle-wrapper.properties b/binary-plugin/binary-plugin-assignment-test-project/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..b1159fc
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/binary-plugin/binary-plugin-assignment-test-project/gradlew b/binary-plugin/binary-plugin-assignment-test-project/gradlew
new file mode 100755
index 0000000..4f906e0
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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"`
+
+# 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" "-Xms64m"'
+
+# 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
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+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" -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\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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=`expr $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
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+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"
+
+exec "$JAVACMD" "$@"
diff --git a/binary-plugin/binary-plugin-assignment-test-project/gradlew.bat b/binary-plugin/binary-plugin-assignment-test-project/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@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 Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@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" "-Xms64m"
+
+@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 execute
+
+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 execute
+
+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
+
+: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 %*
+
+: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/binary-plugin/binary-plugin-assignment-test-project/settings.gradle b/binary-plugin/binary-plugin-assignment-test-project/settings.gradle
new file mode 100644
index 0000000..907188e
--- /dev/null
+++ b/binary-plugin/binary-plugin-assignment-test-project/settings.gradle
@@ -0,0 +1,29 @@
+/**
+ * By default only Gradle Plugin Portal is defined as a repository that provides Gradle plugins that can be applied
+ * within
plugins{}
block.
+ *
+ * If you want to specify any additional repository you have to define them in pluginManagement block within
+ * setting.gradle file. Remember pluginManagement has to be the first statement inside settings.gradle file.
+ *
+ * In definition below 3 repositories will be taken ito account when Gradle will search for defined plugin by its ID and version:
+ * - Gradle Plugin Portal,
+ * - Maven Local repository will be taken into account when Gradle
+ * - Custom defined Maven repository where Archiva server is providing the plugins.
+ */
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenLocal()
+ maven {
+ url = "http://localhost:8080/repository/internal"
+ name = "mavenArchivaPrivate"
+ allowInsecureProtocol = true
+ credentials {
+ username = "$privateArchivaUser"
+ password = "$privateArchivaPassword"
+ }
+ }
+ }
+}
+rootProject.name = 'binary-plugin-assignment-test-project'
+
diff --git a/binary-plugin/binary-plugin-example/.gitignore b/binary-plugin/binary-plugin-example/.gitignore
new file mode 100644
index 0000000..2677823
--- /dev/null
+++ b/binary-plugin/binary-plugin-example/.gitignore
@@ -0,0 +1,152 @@
+
+# Created by https://www.toptal.com/developers/gitignore/api/java,gradle,intellij
+# Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle,intellij
+
+### Intellij ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+# https://plugins.jetbrains.com/plugin/7973-sonarlint
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator-enh.xml
+.idea/**/markdown-navigator/
+
+# Cache file creation bug
+# See https://youtrack.jetbrains.com/issue/JBR-2257
+.idea/$CACHE_FILE$
+
+# CodeStream plugin
+# https://plugins.jetbrains.com/plugin/12206-codestream
+.idea/codestream.xml
+
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+### Gradle ###
+.gradle
+build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# Cache of project
+.gradletasknamecache
+
+# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
+# gradle/wrapper/gradle-wrapper.properties
+
+### Gradle Patch ###
+**/build/
+
+# End of https://www.toptal.com/developers/gitignore/api/java,gradle,intellij
diff --git a/binary-plugin/binary-plugin-example/gradle/wrapper/gradle-wrapper.properties b/binary-plugin/binary-plugin-example/gradle/wrapper/gradle-wrapper.properties
index 669386b..b1159fc 100644
--- a/binary-plugin/binary-plugin-example/gradle/wrapper/gradle-wrapper.properties
+++ b/binary-plugin/binary-plugin-example/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/task/file-tasks-assignment/README.md b/task/file-tasks-assignment/README.md
index 9c2ed90..c4d53db 100644
--- a/task/file-tasks-assignment/README.md
+++ b/task/file-tasks-assignment/README.md
@@ -91,7 +91,7 @@ source code of Gradle API and debug build.grade script.
**Managing Files**
-- Method [Project#file()](https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:file(java.lang.Object)) gets you relative path to the file from project location !!! TODO link to project section !!!
+- Method [Project#file()](https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:file(java.lang.Object)) gets you relative path to the file from project location.
- Method [Project#mkdir()](https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:mkdir(java.lang.Object)) can create new directory [Gradle Creating directories](https://docs.gradle.org/current/userguide/working_with_files.html#sec:creating_directories_example)
- [java.nio.Files.copy()](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/nio/file/Files.html#copy(java.nio.file.Path,java.nio.file.Path,java.nio.file.CopyOption...)) can copy file from source to target directory
- You can use all other helper classes from Java [java.io](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/io/package-summary.html) and [java.nio.file](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/nio/file/package-summary.html) packages to manage files and folders.