Open Sourcing service-starter.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f9d7cba
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,16 @@
+.gradle
+.idea
+build/
+target/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+*.iml
+
+*.log
+
+*.toDelete
diff --git a/HEADER b/HEADER
new file mode 100644
index 0000000..d47a70e
--- /dev/null
+++ b/HEADER
@@ -0,0 +1,13 @@
+Copyright ${year} ${name}.
+
+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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..37c4378
--- /dev/null
+++ b/README.md
@@ -0,0 +1,27 @@
+# Mifos I/O Service Starter
+
+
+This project makes it possible to start services locally for the purpose of writing integration tests.
+
+## Abstract
+Mifos I/O is an application framework for digital financial services, a system to support nationwide and cross-national financial transactions and help to level and speed the creation of an inclusive, interconnected digital economy for every nation in the world.
+
+## Versioning
+The version numbers follow the [Semantic Versioning](http://semver.org/) scheme.
+
+In addition to MAJOR.MINOR.PATCH the following postfixes are used to indicate the development state.
+
+* BUILD-SNAPSHOT - A release currently in development.
+* M - A _milestone_ release include specific sets of functions and are released as soon as the functionality is complete.
+* RC - A _release candidate_ is a version with potential to be a final product, considered _code complete_.
+* RELEASE - indicates that this release is the best available version and is recommended for all usage.
+
+The versioning layout is {MAJOR}.{MINOR}.{PATCH}-{INDICATOR}[.{PATCH}]. Only milestones and release candidates can have patch versions. Some examples:
+
+1.2.3-BUILD-SNAPSHOT
+1.3.5-M.1
+1.5.7-RC.2
+2.0.0-RELEASE
+
+## License
+See [LICENSE](LICENSE) file.
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..1d72f8d
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,94 @@
+buildscript {
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ classpath ("io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE")
+ }
+}
+
+plugins {
+ id 'com.github.hierynomus.license' version '0.13.1'
+}
+
+group 'io.mifos'
+version '0.1.0-BUILD-SNAPSHOT'
+
+ext.versions = [
+ frameworkapi : '0.1.0-BUILD-SNAPSHOT',
+ frameworktest : '0.1.0-BUILD-SNAPSHOT',
+ frameworkanubis : '0.1.0-BUILD-SNAPSHOT',
+ validator : '5.3.0.Final'
+]
+
+apply plugin: 'java'
+apply plugin: 'idea'
+apply plugin: 'io.spring.dependency-management'
+apply plugin: 'maven-publish'
+
+tasks.withType(JavaCompile) {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+repositories {
+ jcenter()
+ mavenLocal()
+}
+
+dependencyManagement {
+ imports {
+ mavenBom 'io.spring.platform:platform-bom:Athens-RELEASE'
+ mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Camden.SR1'
+ }
+}
+
+dependencies {
+ compile(
+ [group: 'com.google.code.findbugs', name: 'jsr305'],
+ [group: 'io.mifos.core', name: 'api', version: versions.frameworkapi],
+ [group: 'io.mifos.core', name: 'test', version: versions.frameworktest],
+ [group: 'io.mifos.anubis', name: 'test', version: versions.frameworkanubis],
+ [group: 'org.eclipse.aether', name: 'aether-api', version: '1.1.0'],
+ [group: 'org.eclipse.aether', name: 'aether-spi', version: '1.1.0'],
+ [group: 'org.eclipse.aether', name: 'aether-util', version: '1.1.0'],
+ [group: 'org.eclipse.aether', name: 'aether-impl', version: '1.1.0'],
+ [group: 'org.eclipse.aether', name: 'aether-connector-basic', version: '1.1.0'],
+ [group: 'org.eclipse.aether', name: 'aether-transport-file', version: '1.1.0'],
+ [group: 'org.eclipse.aether', name: 'aether-transport-http', version: '1.1.0'],
+ [group: 'org.apache.maven', name: 'maven-aether-provider', version: '3.1.0'],
+ [group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka-server'],
+ )
+}
+
+jar {
+ from sourceSets.main.allSource
+}
+
+license {
+ exclude("**/aether/*.java")
+ exclude("**/aether/*.html")
+ header rootProject.file('HEADER')
+ strictCheck true
+ mapping {
+ java = 'SLASHSTAR_STYLE'
+ xml = 'XML_STYLE'
+ yml = 'SCRIPT_STYLE'
+ yaml = 'SCRIPT_STYLE'
+ }
+ ext.year = Calendar.getInstance().get(Calendar.YEAR)
+ ext.name = 'The Mifos Initiative'
+}
+
+
+publishing {
+ publications {
+ serviceStarterPublication(MavenPublication) {
+ from components.java
+ groupId project.group
+ artifactId project.name
+ version project.version
+ }
+ }
+}
\ 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..c7d59a1
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..f1b1899
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Mar 15 18:38:13 CET 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..4453cce
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## 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=""
+
+# 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, 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
+
+# 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"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..40dc664
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'service-starter'
diff --git a/src/main/java/io/mifos/core/test/servicestarter/ArtifactResolver.java b/src/main/java/io/mifos/core/test/servicestarter/ArtifactResolver.java
new file mode 100644
index 0000000..be0146c
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/ArtifactResolver.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.core.test.servicestarter;
+
+import io.mifos.core.test.servicestarter.aether.Booter;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.ArtifactRequest;
+import org.eclipse.aether.resolution.ArtifactResolutionException;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.util.repository.AuthenticationBuilder;
+
+import java.io.File;
+import java.util.Collections;
+
+/**
+ * @author Myrle Krantz
+ */
+class ArtifactResolver {
+ private final String artifactoryDirectory;
+ private final String username;
+ private final String password;
+
+ private RemoteRepository repositoryForProject(final String project)
+ {
+ return new RemoteRepository.Builder(project, "default", "https://mifosio-radar.bintray.com/io.mifos." + project)
+ .setAuthentication(new AuthenticationBuilder().addUsername(username).addPassword(password).build())
+ .build();
+ }
+
+
+ ArtifactResolver(final String artifactoryDirectory, final String username, final String password)
+ {
+ this.artifactoryDirectory = artifactoryDirectory;
+ this.username = username;
+ this.password = password;
+ }
+
+ File getJarFile(final String project, final String group, final String name, final String version)
+ throws ArtifactResolutionException {
+ final RepositorySystem system = Booter.newRepositorySystem();
+ final RepositorySystemSession session = Booter.newRepositorySystemSession(system, artifactoryDirectory);
+
+
+ final ArtifactRequest artifactRequest = new ArtifactRequest();
+ artifactRequest.setArtifact(new DefaultArtifact(group, name, "jar", version));
+ artifactRequest.setRepositories(Collections.singletonList(repositoryForProject(project)));
+
+ final ArtifactResult artifactResult = system.resolveArtifact(session, artifactRequest);
+
+ return artifactResult.getArtifact().getFile();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/mifos/core/test/servicestarter/EurekaForTest.java b/src/main/java/io/mifos/core/test/servicestarter/EurekaForTest.java
new file mode 100644
index 0000000..8eade00
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/EurekaForTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.core.test.servicestarter;
+
+import org.junit.rules.ExternalResource;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings({"unused", "WeakerAccess"})
+public class EurekaForTest extends ExternalResource {
+ static final int PORT = 8761;
+ static final String DEFAULT_ZONE = "http://localhost:" + PORT + "/eureka/";
+ private ConfigurableApplicationContext eurekaServer;
+
+ @SuppressWarnings("WeakerAccess")
+ @EnableEurekaServer
+ @Configuration
+ @EnableAutoConfiguration(exclude= {HibernateJpaAutoConfiguration.class, DataSourceAutoConfiguration.class})
+ static class EurekaServer {
+ }
+
+ protected void before() throws Throwable {
+
+ // start eureka server for test
+ eurekaServer = SpringApplication.run(EurekaServer.class,
+ "--server.port=" + PORT,
+ "--security.basic.enabled=false",
+ "--error.whitelabel.enabled=false",
+ "--eureka.instance.leaseRenewalIntervalInSeconds=1", //Speed up registration for test purposes.
+ "--eureka.server.responseCacheUpdateIntervalMs=500",
+ "--eureka.instance.hostname=localhost",
+ "--eureka.client.registerWithEureka=false",
+ "--eureka.client.fetchRegistry=false",
+ "--eureka.serviceUrl.defaultZone=" + DEFAULT_ZONE);
+ }
+
+ /**
+ * Override to tear down your specific external resource.
+ */
+ protected void after() {
+ eurekaServer.close();
+ }
+}
diff --git a/src/main/java/io/mifos/core/test/servicestarter/InitializedMicroservice.java b/src/main/java/io/mifos/core/test/servicestarter/InitializedMicroservice.java
new file mode 100644
index 0000000..7e66897
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/InitializedMicroservice.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.core.test.servicestarter;
+
+import io.mifos.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
+import org.eclipse.aether.resolution.ArtifactResolutionException;
+
+import java.io.IOException;
+
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("unused")
+public class InitializedMicroservice<T> extends Microservice<T> {
+ public InitializedMicroservice(
+ final Class<T> clazz,
+ final String artifactName,
+ final String artifactVersion,
+ final IntegrationTestEnvironment integrationTestEnvironment) {
+ super(clazz, artifactName, artifactVersion, integrationTestEnvironment);
+ this.integrationTestEnvironment.addApplication(applicationName);
+ }
+
+ public void start() throws InterruptedException, IOException, ArtifactResolutionException {
+ super.start();
+ final TenantApplicationSecurityEnvironmentTestRule tenantApplicationSecurityEnvironment
+ = new TenantApplicationSecurityEnvironmentTestRule(applicationName, processEnvironment.serverURI(), integrationTestEnvironment.getSystemSecurityEnvironment());
+ tenantApplicationSecurityEnvironment.initializeTenantInApplication();
+ }
+}
diff --git a/src/main/java/io/mifos/core/test/servicestarter/IntegrationTestEnvironment.java b/src/main/java/io/mifos/core/test/servicestarter/IntegrationTestEnvironment.java
new file mode 100644
index 0000000..8c9dbbb
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/IntegrationTestEnvironment.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.core.test.servicestarter;
+
+import io.mifos.anubis.test.v1.SystemSecurityEnvironment;
+import io.mifos.core.api.context.AutoUserContext;
+import io.mifos.core.lang.security.RsaKeyPairFactory;
+import io.mifos.core.test.fixture.DataStoreTenantInitializer;
+import io.mifos.core.test.fixture.TenantDataStoreTestContext;
+import org.junit.rules.ExternalResource;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.Socket;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.*;
+
+import static io.mifos.core.test.env.TestEnvironment.*;
+
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("WeakerAccess")
+public class IntegrationTestEnvironment extends ExternalResource {
+
+
+ static String getJava()
+ {
+ final String javaHome = System.getProperty("java.home");
+ return javaHome + File.separator + "bin" + File.separator + "java";
+ }
+
+ static String getArtifactoryDirectory()
+ {
+ final String homeDirectory = System.getProperty("user.home");
+ return homeDirectory + File.separator + ".m2" + File.separator + "repository";
+ }
+
+ static String getBintrayUser()
+ {
+ return System.getenv().get("BINTRAY_USER");
+ }
+
+ static String getBintrayPassword()
+ {
+ return System.getenv().get("BINTRAY_PASSWORD");
+ }
+
+ private int nextPort;
+ private final Set<Integer> ports;
+ private final RsaKeyPairFactory.KeyPairHolder keyPairHolder;
+ private final SystemSecurityEnvironment systemSecurityEnvironment;
+ private final DataStoreTenantInitializer[] dataStoreTenantInitializers;
+ private final List<String> applicationNames;
+ private TenantDataStoreTestContext tenantDataStoreTestContext;
+
+ public IntegrationTestEnvironment(final DataStoreTenantInitializer... dataStoreTenantInitializers) {
+ final Properties properties = System.getProperties();
+ properties.setProperty(CASSANDRA_CLUSTER_NAME_PROPERTY, CASSANDRA_CLUSTER_NAME_DEFAULT);
+ properties.setProperty(CASSANDRA_CONTACT_POINTS_PROPERTY, CASSANDRA_CONTACT_POINTS_DEFAULT);
+ properties.setProperty(CASSANDRA_META_KEYSPACE_PROPERTY, CASSANDRA_META_KEYSPACE_DEFAULT);
+ properties.setProperty(CASSANDRA_CONSISTENCY_LEVEL_READ_PROPERTY, CASSANDRA_CONSISTENCY_LEVEL_DEFAULT);
+ properties.setProperty(CASSANDRA_CONSISTENCY_LEVEL_WRITE_PROPERTY, CASSANDRA_CONSISTENCY_LEVEL_DEFAULT);
+ properties.setProperty(CASSANDRA_CONSISTENCY_LEVEL_DELETE_PROPERTY, CASSANDRA_CONSISTENCY_LEVEL_DEFAULT);
+ properties.setProperty(MARIADB_DRIVER_CLASS_PROPERTY, MARIADB_DRIVER_CLASS_DEFAULT);
+ properties.setProperty(MARIADB_DATABASE_NAME_PROPERTY, MARIADB_DATABASE_NAME_DEFAULT);
+ properties.setProperty(MARIADB_HOST_PROPERTY, MARIADB_HOST_DEFAULT);
+ properties.setProperty(MARIADB_PORT_PROPERTY, MARIADB_PORT_DEFAULT);
+ properties.setProperty(MARIADB_USER_PROPERTY, MARIADB_USER_DEFAULT);
+ properties.setProperty(MARIADB_PASSWORD_PROPERTY, MARIADB_PASSWORD_DEFAULT);
+ properties.setProperty(HYSTRIX_ENABLED_PROPERTY, HYSTRIX_ENABLED_DEFAULT);
+ properties.setProperty(RIBBON_USES_EUREKA_PROPERTY, RIBBON_USES_EUREKA_DEFAULT);
+ this.keyPairHolder = RsaKeyPairFactory.createKeyPair();
+ properties.setProperty(SYSTEM_PUBLIC_KEY_MODULUS_PROPERTY, this.keyPairHolder.publicKey().getModulus().toString());
+ properties.setProperty(SYSTEM_PUBLIC_KEY_EXPONENT_PROPERTY, this.keyPairHolder.publicKey().getPublicExponent().toString());
+
+ this.systemSecurityEnvironment = new SystemSecurityEnvironment(keyPairHolder.publicKey(), keyPairHolder.privateKey());
+ this.dataStoreTenantInitializers = dataStoreTenantInitializers;
+
+ nextPort = 2020;
+ this.ports = new HashSet<>();
+ this.ports.add(0);
+ this.ports.add(3306); //MySQL
+ this.ports.add(9142); //Cassandra
+ this.ports.add(EurekaForTest.PORT);
+
+ this.applicationNames = new ArrayList<>();
+ }
+
+ @Override
+ protected void before() {
+ tenantDataStoreTestContext = TenantDataStoreTestContext.forRandomTenantName(dataStoreTenantInitializers);
+ }
+
+ @Override
+ protected void after() {
+ tenantDataStoreTestContext.close();
+ }
+
+ Integer getFreshPort() {
+ while (ports.contains(nextPort) || !available(nextPort))
+ {
+ nextPort += 1;
+ }
+
+ ports.add(nextPort);
+ return nextPort;
+ }
+
+ private static boolean available(int port) {
+ try (final Socket ignored = new Socket("localhost", port)) {
+ return false;
+ } catch (final IOException ignored) {
+ return true;
+ }
+ }
+
+ public RSAPublicKey getSeshatPublicKey() {
+ return this.keyPairHolder.publicKey();
+ }
+
+ public RSAPrivateKey getSeshatPrivateKey() {
+ return this.keyPairHolder.privateKey();
+ }
+
+ public SystemSecurityEnvironment getSystemSecurityEnvironment() {
+ return systemSecurityEnvironment;
+ }
+
+ void addApplication(final String applicationName) {
+ applicationNames.add(applicationName);
+ }
+
+ @SuppressWarnings("unused")
+ public AutoUserContext createAutoUserContext(final String userName) {
+ return systemSecurityEnvironment.createAutoUserContext(userName, applicationNames);
+ }
+}
diff --git a/src/main/java/io/mifos/core/test/servicestarter/Microservice.java b/src/main/java/io/mifos/core/test/servicestarter/Microservice.java
new file mode 100644
index 0000000..13db326
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/Microservice.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.core.test.servicestarter;
+
+import io.mifos.core.api.util.ApiFactory;
+import io.mifos.core.test.env.TestEnvironment;
+import org.eclipse.aether.resolution.ArtifactResolutionException;
+import org.junit.rules.ExternalResource;
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import static io.mifos.core.test.env.TestEnvironment.SPRING_CLOUD_DISCOVERY_ENABLED_PROPERTY;
+
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings({"unused", "WeakerAccess"})
+public class Microservice<T> extends ExternalResource {
+
+ private final Class<T> clazz;
+ private final String artifactName;
+ private final String artifactVersion;
+ final TestEnvironment processEnvironment;
+ final IntegrationTestEnvironment integrationTestEnvironment;
+ final String applicationName;
+ private ApiFactory apiFactory;
+ private Process process;
+ private T api;
+
+ public Microservice(
+ final Class<T> clazz,
+ final String artifactName,
+ final String artifactVersion,
+ final IntegrationTestEnvironment integrationTestEnvironment) {
+ this.clazz = clazz;
+ this.artifactName = artifactName;
+ this.artifactVersion = artifactVersion;
+ applicationName = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz, FeignClient.class).getString("value");
+ this.processEnvironment = new TestEnvironment(applicationName);
+ processEnvironment.setProperty(TestEnvironment.SERVER_PORT_PROPERTY, integrationTestEnvironment.getFreshPort().toString());
+ processEnvironment.setKeyPair(integrationTestEnvironment.getSeshatPublicKey(), integrationTestEnvironment.getSeshatPrivateKey());
+
+ //https://github.com/spring-cloud/spring-cloud-netflix/issues/373
+ //http://blog.abhijitsarkar.org/technical/netflix-eureka/
+ processEnvironment.setProperty("eureka.client.serviceUrl.defaultZone", EurekaForTest.DEFAULT_ZONE);
+ processEnvironment.setProperty(SPRING_CLOUD_DISCOVERY_ENABLED_PROPERTY, "true");
+ processEnvironment.setProperty("eureka.instance.hostname", "localhost");
+ processEnvironment.setProperty("eureka.client.fetchRegistry", "true");
+ processEnvironment.setProperty("eureka.registration.enabled", "true");
+ processEnvironment.setProperty("eureka.instance.leaseRenewalIntervalInSeconds", "1"); //Speed up registration for test purposes.
+ processEnvironment.setProperty("eureka.client.initialInstanceInfoReplicationIntervalSeconds", "0"); //Speed up initial registration for test purposes.
+ processEnvironment.setProperty("eureka.client.instanceInfoReplicationIntervalSeconds", "1");
+
+ this.integrationTestEnvironment = integrationTestEnvironment;
+ }
+
+ @Override
+ protected void before() throws InterruptedException, IOException, ArtifactResolutionException {
+ start();
+ }
+
+ @Override
+ protected void after() {
+ try {
+ kill();
+ } catch (final InterruptedException e) {
+ System.out.println("Interrupt raised, but microservice is already going down, so ignoring.");
+ }
+ }
+
+ public void start() throws ArtifactResolutionException, IOException, InterruptedException {
+
+ final ArtifactResolver artifactResolver = new ArtifactResolver(
+ IntegrationTestEnvironment.getArtifactoryDirectory(),
+ IntegrationTestEnvironment.getBintrayUser(),
+ IntegrationTestEnvironment.getBintrayPassword());
+
+ final File jarFile = artifactResolver.getJarFile(artifactName, "io.mifos." + artifactName, "service-boot", artifactVersion);
+
+ final ProcessBuilder processBuilder
+ = new ProcessBuilder(IntegrationTestEnvironment.getJava(), "-jar", jarFile.getAbsolutePath());
+ processEnvironment.populateProcessEnvironment(processBuilder);
+ processBuilder.inheritIO();
+
+ process = processBuilder.start();
+ TimeUnit.SECONDS.sleep(40); //TODO: Replace this with event listening.
+ }
+
+ public int kill() throws InterruptedException {
+ process.destroy();
+ process.waitFor();
+ return process.exitValue();
+ }
+
+ public void setApiFactory(final ApiFactory newValue)
+ {
+ this.apiFactory = newValue;
+ }
+
+ public T api() {
+ if (this.api == null) {
+ this.api = this.apiFactory.create(clazz, processEnvironment.serverURI());
+ }
+ return this.api;
+ }
+
+ public String uri() {
+ return processEnvironment.serverURI();
+ }
+
+ public TestEnvironment getProcessEnvironment()
+ {
+ return processEnvironment;
+ }
+
+ public String name() {
+ return applicationName;
+ }
+}
diff --git a/src/main/java/io/mifos/core/test/servicestarter/aether/Booter.java b/src/main/java/io/mifos/core/test/servicestarter/aether/Booter.java
new file mode 100644
index 0000000..5c9e915
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/aether/Booter.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+package io.mifos.core.test.servicestarter.aether;
+
+import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.repository.LocalRepository;
+
+
+public class Booter {
+
+ public static RepositorySystem newRepositorySystem()
+ {
+ return ManualRepositorySystemFactory.newRepositorySystem();
+ // return org.eclipse.aether.examples.guice.GuiceRepositorySystemFactory.newRepositorySystem();
+ // return org.eclipse.aether.examples.sisu.SisuRepositorySystemFactory.newRepositorySystem();
+ // return org.eclipse.aether.examples.plexus.PlexusRepositorySystemFactory.newRepositorySystem();
+ }
+
+
+ public static DefaultRepositorySystemSession newRepositorySystemSession(RepositorySystem system, String artifactoryDirectory)
+ {
+ DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
+
+ LocalRepository localRepo = new LocalRepository(artifactoryDirectory);
+ session.setLocalRepositoryManager( system.newLocalRepositoryManager( session, localRepo ) );
+
+ session.setTransferListener( new ConsoleTransferListener() );
+ session.setRepositoryListener( new ConsoleRepositoryListener() );
+
+ // uncomment to generate dirty trees
+ // session.setDependencyGraphTransformer( null );
+
+ return session;
+ }
+}
diff --git a/src/main/java/io/mifos/core/test/servicestarter/aether/ConsoleRepositoryListener.java b/src/main/java/io/mifos/core/test/servicestarter/aether/ConsoleRepositoryListener.java
new file mode 100644
index 0000000..353dd06
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/aether/ConsoleRepositoryListener.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+package io.mifos.core.test.servicestarter.aether;
+
+
+import org.eclipse.aether.AbstractRepositoryListener;
+import org.eclipse.aether.RepositoryEvent;
+
+import java.io.PrintStream;
+
+public class ConsoleRepositoryListener
+ extends AbstractRepositoryListener
+{
+ private PrintStream out;
+
+ public ConsoleRepositoryListener()
+ {
+ this( null );
+ }
+
+ public ConsoleRepositoryListener( PrintStream out )
+ {
+ this.out = ( out != null ) ? out : System.out;
+ }
+
+ public void artifactDeployed( RepositoryEvent event )
+ {
+ out.println( "Deployed " + event.getArtifact() + " to " + event.getRepository() );
+ }
+
+ public void artifactDeploying( RepositoryEvent event )
+ {
+ out.println( "Deploying " + event.getArtifact() + " to " + event.getRepository() );
+ }
+
+ public void artifactDescriptorInvalid( RepositoryEvent event )
+ {
+ out.println( "Invalid artifact descriptor for " + event.getArtifact() + ": "
+ + event.getException().getMessage() );
+ }
+
+ public void artifactDescriptorMissing( RepositoryEvent event )
+ {
+ out.println( "Missing artifact descriptor for " + event.getArtifact() );
+ }
+
+ public void artifactInstalled( RepositoryEvent event )
+ {
+ out.println( "Installed " + event.getArtifact() + " to " + event.getFile() );
+ }
+
+ public void artifactInstalling( RepositoryEvent event )
+ {
+ out.println( "Installing " + event.getArtifact() + " to " + event.getFile() );
+ }
+
+ public void artifactResolved( RepositoryEvent event )
+ {
+ out.println( "Resolved artifact " + event.getArtifact() + " from " + event.getRepository() );
+ }
+
+ public void artifactDownloading( RepositoryEvent event )
+ {
+ out.println( "Downloading artifact " + event.getArtifact() + " from " + event.getRepository() );
+ }
+
+ public void artifactDownloaded( RepositoryEvent event )
+ {
+ out.println( "Downloaded artifact " + event.getArtifact() + " from " + event.getRepository() );
+ }
+
+ public void artifactResolving( RepositoryEvent event )
+ {
+ out.println( "Resolving artifact " + event.getArtifact() );
+ }
+
+ public void metadataDeployed( RepositoryEvent event )
+ {
+ out.println( "Deployed " + event.getMetadata() + " to " + event.getRepository() );
+ }
+
+ public void metadataDeploying( RepositoryEvent event )
+ {
+ out.println( "Deploying " + event.getMetadata() + " to " + event.getRepository() );
+ }
+
+ public void metadataInstalled( RepositoryEvent event )
+ {
+ out.println( "Installed " + event.getMetadata() + " to " + event.getFile() );
+ }
+
+ public void metadataInstalling( RepositoryEvent event )
+ {
+ out.println( "Installing " + event.getMetadata() + " to " + event.getFile() );
+ }
+
+ public void metadataInvalid( RepositoryEvent event )
+ {
+ out.println( "Invalid metadata " + event.getMetadata() );
+ }
+
+ public void metadataResolved( RepositoryEvent event )
+ {
+ out.println( "Resolved metadata " + event.getMetadata() + " from " + event.getRepository() );
+ }
+
+ public void metadataResolving( RepositoryEvent event )
+ {
+ out.println( "Resolving metadata " + event.getMetadata() + " from " + event.getRepository() );
+ }
+}
diff --git a/src/main/java/io/mifos/core/test/servicestarter/aether/ConsoleTransferListener.java b/src/main/java/io/mifos/core/test/servicestarter/aether/ConsoleTransferListener.java
new file mode 100644
index 0000000..0bccd0e
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/aether/ConsoleTransferListener.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2013 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+package io.mifos.core.test.servicestarter.aether;
+
+
+import org.eclipse.aether.transfer.AbstractTransferListener;
+import org.eclipse.aether.transfer.MetadataNotFoundException;
+import org.eclipse.aether.transfer.TransferEvent;
+import org.eclipse.aether.transfer.TransferResource;
+
+import java.io.PrintStream;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ConsoleTransferListener extends AbstractTransferListener
+ {
+
+ private PrintStream out;
+
+ private Map<TransferResource, Long> downloads = new ConcurrentHashMap<TransferResource, Long>();
+
+ private int lastLength;
+
+ public ConsoleTransferListener()
+ {
+ this( null );
+ }
+
+ public ConsoleTransferListener( PrintStream out )
+ {
+ this.out = ( out != null ) ? out : System.out;
+ }
+
+ @Override
+ public void transferInitiated( TransferEvent event )
+ {
+ String message = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading";
+
+ out.println( message + ": " + event.getResource().getRepositoryUrl() + event.getResource().getResourceName() );
+ }
+
+ @Override
+ public void transferProgressed( TransferEvent event )
+ {
+ TransferResource resource = event.getResource();
+ downloads.put( resource, Long.valueOf( event.getTransferredBytes() ) );
+
+ StringBuilder buffer = new StringBuilder( 64 );
+
+ for ( Map.Entry<TransferResource, Long> entry : downloads.entrySet() )
+ {
+ long total = entry.getKey().getContentLength();
+ long complete = entry.getValue().longValue();
+
+ buffer.append( getStatus( complete, total ) ).append( " " );
+ }
+
+ int pad = lastLength - buffer.length();
+ lastLength = buffer.length();
+ pad( buffer, pad );
+ buffer.append( '\r' );
+
+ out.print( buffer );
+ }
+
+ private String getStatus( long complete, long total )
+ {
+ if ( total >= 1024 )
+ {
+ return toKB( complete ) + "/" + toKB( total ) + " KB ";
+ }
+ else if ( total >= 0 )
+ {
+ return complete + "/" + total + " B ";
+ }
+ else if ( complete >= 1024 )
+ {
+ return toKB( complete ) + " KB ";
+ }
+ else
+ {
+ return complete + " B ";
+ }
+ }
+
+ private void pad( StringBuilder buffer, int spaces )
+ {
+ String block = " ";
+ while ( spaces > 0 )
+ {
+ int n = Math.min( spaces, block.length() );
+ buffer.append( block, 0, n );
+ spaces -= n;
+ }
+ }
+
+ @Override
+ public void transferSucceeded( TransferEvent event )
+ {
+ transferCompleted( event );
+
+ TransferResource resource = event.getResource();
+ long contentLength = event.getTransferredBytes();
+ if ( contentLength >= 0 )
+ {
+ String type = ( event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded" );
+ String len = contentLength >= 1024 ? toKB( contentLength ) + " KB" : contentLength + " B";
+
+ String throughput = "";
+ long duration = System.currentTimeMillis() - resource.getTransferStartTime();
+ if ( duration > 0 )
+ {
+ long bytes = contentLength - resource.getResumeOffset();
+ DecimalFormat format = new DecimalFormat( "0.0", new DecimalFormatSymbols( Locale.ENGLISH ) );
+ double kbPerSec = ( bytes / 1024.0 ) / ( duration / 1000.0 );
+ throughput = " at " + format.format( kbPerSec ) + " KB/sec";
+ }
+
+ out.println( type + ": " + resource.getRepositoryUrl() + resource.getResourceName() + " (" + len
+ + throughput + ")" );
+ }
+ }
+
+ @Override
+ public void transferFailed( TransferEvent event )
+ {
+ transferCompleted( event );
+
+ if ( !( event.getException() instanceof MetadataNotFoundException) )
+ {
+ event.getException().printStackTrace( out );
+ }
+ }
+
+ private void transferCompleted( TransferEvent event )
+ {
+ downloads.remove( event.getResource() );
+
+ StringBuilder buffer = new StringBuilder( 64 );
+ pad( buffer, lastLength );
+ buffer.append( '\r' );
+ out.print( buffer );
+ }
+
+ public void transferCorrupted( TransferEvent event )
+ {
+ event.getException().printStackTrace( out );
+ }
+
+ protected long toKB( long bytes )
+ {
+ return ( bytes + 1023 ) / 1024;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/io/mifos/core/test/servicestarter/aether/Eclipse Public License - Version 1.0.html b/src/main/java/io/mifos/core/test/servicestarter/aether/Eclipse Public License - Version 1.0.html
new file mode 100644
index 0000000..51b3b87
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/aether/Eclipse Public License - Version 1.0.html
@@ -0,0 +1,259 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- saved from url=(0042)https://www.eclipse.org/legal/epl-v10.html -->
+<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+<title>Eclipse Public License - Version 1.0</title>
+<style type="text/css">
+ body {
+ size: 8.5in 11.0in;
+ margin: 0.25in 0.5in 0.25in 0.5in;
+ tab-interval: 0.5in;
+ }
+ p {
+ margin-left: auto;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+ p.list {
+ margin-left: 0.5in;
+ margin-top: 0.05em;
+ margin-bottom: 0.05em;
+ }
+ </style>
+
+</head>
+
+<body lang="EN-US">
+
+<h2>Eclipse Public License - v 1.0</h2>
+
+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</p>
+
+<p><b>1. DEFINITIONS</b></p>
+
+<p>"Contribution" means:</p>
+
+<p class="list">a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and</p>
+<p class="list">b) in the case of each subsequent Contributor:</p>
+<p class="list">i) changes to the Program, and</p>
+<p class="list">ii) additions to the Program;</p>
+<p class="list">where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.</p>
+
+<p>"Contributor" means any person or entity that distributes
+the Program.</p>
+
+<p>"Licensed Patents" mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.</p>
+
+<p>"Program" means the Contributions distributed in accordance
+with this Agreement.</p>
+
+<p>"Recipient" means anyone who receives the Program under
+this Agreement, including all Contributors.</p>
+
+<p><b>2. GRANT OF RIGHTS</b></p>
+
+<p class="list">a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.</p>
+
+<p class="list">b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.</p>
+
+<p class="list">c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.</p>
+
+<p class="list">d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.</p>
+
+<p><b>3. REQUIREMENTS</b></p>
+
+<p>A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:</p>
+
+<p class="list">a) it complies with the terms and conditions of this
+Agreement; and</p>
+
+<p class="list">b) its license agreement:</p>
+
+<p class="list">i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;</p>
+
+<p class="list">ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;</p>
+
+<p class="list">iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and</p>
+
+<p class="list">iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.</p>
+
+<p>When the Program is made available in source code form:</p>
+
+<p class="list">a) it must be made available under this Agreement; and</p>
+
+<p class="list">b) a copy of this Agreement must be included with each
+copy of the Program.</p>
+
+<p>Contributors may not remove or alter any copyright notices contained
+within the Program.</p>
+
+<p>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.</p>
+
+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
+
+<p>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and
+indemnify every other Contributor ("Indemnified Contributor")
+against any losses, damages and costs (collectively "Losses")
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.</p>
+
+<p>For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.</p>
+
+<p><b>5. NO WARRANTY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.</p>
+
+<p><b>6. DISCLAIMER OF LIABILITY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), 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 OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
+
+<p><b>7. GENERAL</b></p>
+
+<p>If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.</p>
+
+<p>If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.</p>
+
+<p>All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.</p>
+
+<p>Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.</p>
+
+<p>This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.</p>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/src/main/java/io/mifos/core/test/servicestarter/aether/ManualRepositorySystemFactory.java b/src/main/java/io/mifos/core/test/servicestarter/aether/ManualRepositorySystemFactory.java
new file mode 100644
index 0000000..b6c1fc8
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/servicestarter/aether/ManualRepositorySystemFactory.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+package io.mifos.core.test.servicestarter.aether;
+
+import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
+import org.eclipse.aether.impl.DefaultServiceLocator;
+import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
+import org.eclipse.aether.spi.connector.transport.TransporterFactory;
+import org.eclipse.aether.transport.file.FileTransporterFactory;
+import org.eclipse.aether.transport.http.HttpTransporterFactory;
+
+/**
+ * A factory for repository system instances that employs Aether's built-in service locator infrastructure to wire up
+ * the system's components.
+ */
+public class ManualRepositorySystemFactory
+{
+ public static RepositorySystem newRepositorySystem()
+ {
+ /*
+ * Aether's components implement org.eclipse.aether.spi.locator.Service to ease manual wiring and using the
+ * prepopulated DefaultServiceLocator, we only need to register the repository connector and transporter
+ * factories.
+ */
+ DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
+ locator.addService( RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class );
+ locator.addService( TransporterFactory.class, FileTransporterFactory.class );
+ locator.addService( TransporterFactory.class, HttpTransporterFactory.class );
+
+ locator.setErrorHandler( new DefaultServiceLocator.ErrorHandler()
+ {
+ @Override
+ public void serviceCreationFailed( Class<?> type, Class<?> impl, Throwable exception )
+ {
+ exception.printStackTrace();
+ }
+ } );
+
+ return locator.getService( RepositorySystem.class );
+ }
+
+}