diff --git a/build.gradle b/build.gradle index bff241dca..c74524e4b 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,8 @@ group = 'com.github.kusumotolab' // In this section you declare where to find the dependencies of your project repositories { jcenter() + maven { url 'https://repo.gradle.org/gradle/libs-releases' } + maven { url 'https://repo.gradle.org/gradle/libs-snapshots' } } // In this section you declare the dependencies for your production and test code @@ -57,7 +59,6 @@ dependencies { implementation 'commons-codec:commons-codec:1.11' implementation 'io.reactivex.rxjava2:rxjava:2.2.4' implementation 'org.apache.commons:commons-lang3:3.7' - implementation 'org.apache.maven:maven-model:3.5.4' implementation 'org.codehaus.plexus:plexus-utils:3.1.0' implementation 'org.eclipse.jdt:org.eclipse.jdt.core:3.13.102' implementation 'org.eclipse.platform:org.eclipse.equinox.common:3.10.200' @@ -71,6 +72,17 @@ dependencies { testImplementation 'com.google.jimfs:jimfs:1.1' testImplementation 'com.github.stefanbirkner:system-rules:1.19.0' + // to construct maven project + implementation 'org.apache.maven:maven-embedder:3.6.3' + runtimeOnly 'org.apache.maven:maven-compat:3.6.3' + runtimeOnly 'org.apache.maven.resolver:maven-resolver-transport-wagon:1.6.1' + runtimeOnly 'org.apache.maven.resolver:maven-resolver-transport-http:1.6.1' + runtimeOnly 'org.eclipse.aether:aether-connector-basic:1.1.0' + runtimeOnly 'org.eclipse.aether:aether-transport-wagon:1.1.0' + + // to construct gradle project + implementation group: 'org.gradle', name: 'gradle-tooling-api', version: '6.7.1' + // Declare by "runtimeOnly" cuz hamcrest is necessary to execute junit-test dynamically, // but it doesn't seem to be loaded on compile task. runtimeOnly 'org.hamcrest:hamcrest-core:1.3' diff --git a/example/BuildToolGradle/.gitignore b/example/BuildToolGradle/.gitignore new file mode 100644 index 000000000..c9c4251bf --- /dev/null +++ b/example/BuildToolGradle/.gitignore @@ -0,0 +1,3 @@ +.idea +.gradle +target/ diff --git a/example/BuildToolGradle/build.gradle b/example/BuildToolGradle/build.gradle new file mode 100644 index 000000000..d099a1d0e --- /dev/null +++ b/example/BuildToolGradle/build.gradle @@ -0,0 +1,21 @@ +plugins { + id 'java' +} + +repositories { + jcenter() +} + +compileJava { + sourceCompatibility = '1.8' + targetCompatibility = '1.8' +} + +dependencies { + implementation 'org.slf4j:slf4j-api:1.7.30' + runtimeOnly 'ch.qos.logback:logback-classic:1.2.3' // impls for slf4j api + + testImplementation 'junit:junit:4.13' + testImplementation 'org.assertj:assertj-core:3.10.0' + testImplementation 'org.hamcrest:hamcrest:2.2' +} diff --git a/example/BuildToolGradle/gradle/wrapper/gradle-wrapper.jar b/example/BuildToolGradle/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..62d4c0535 Binary files /dev/null and b/example/BuildToolGradle/gradle/wrapper/gradle-wrapper.jar differ diff --git a/example/BuildToolGradle/gradle/wrapper/gradle-wrapper.properties b/example/BuildToolGradle/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..622ab64a3 --- /dev/null +++ b/example/BuildToolGradle/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/example/BuildToolGradle/gradlew b/example/BuildToolGradle/gradlew new file mode 100644 index 000000000..fbd7c5158 --- /dev/null +++ b/example/BuildToolGradle/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/example/BuildToolGradle/gradlew.bat b/example/BuildToolGradle/gradlew.bat new file mode 100644 index 000000000..a9f778a7a --- /dev/null +++ b/example/BuildToolGradle/gradlew.bat @@ -0,0 +1,104 @@ +@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 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/example/BuildToolGradle/pom.xml b/example/BuildToolGradle/pom.xml new file mode 100644 index 000000000..aacd7b880 --- /dev/null +++ b/example/BuildToolGradle/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + example + BuildToolMaven + 0.0.1-SNAPSHOT + + 1.8 + 1.8 + + + + org.slf4j + slf4j-api + 1.7.30 + compile + + + ch.qos.logback + logback-classic + 1.2.3 + runtime + + + junit + junit + 4.13 + test + + + org.assertj + assertj-core + 3.10.0 + test + + + org.hamcrest + hamcrest + 2.2 + test + + + diff --git a/example/BuildToolGradle/settings.gradle b/example/BuildToolGradle/settings.gradle new file mode 100644 index 000000000..5ee58dfd2 --- /dev/null +++ b/example/BuildToolGradle/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'BuildToolGradle' diff --git a/example/BuildToolGradle/src/main/java/example/Foo.java b/example/BuildToolGradle/src/main/java/example/Foo.java new file mode 100644 index 000000000..e696145be --- /dev/null +++ b/example/BuildToolGradle/src/main/java/example/Foo.java @@ -0,0 +1,20 @@ +package example; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Foo { + + // this requires BOTH slf4j and sl4j-api implementations + private final static Logger logger = LoggerFactory.getLogger(Foo.class); + + public int foo(int n) { + if (n > 0) { + n--; + } else { + n++; + } + logger.info("n = {}", n); + return n; + } +} diff --git a/example/BuildToolGradle/src/test/java/example/FooTest.java b/example/BuildToolGradle/src/test/java/example/FooTest.java new file mode 100644 index 000000000..24e1c42fe --- /dev/null +++ b/example/BuildToolGradle/src/test/java/example/FooTest.java @@ -0,0 +1,34 @@ +package example; + +import static org.assertj.core.api.Assertions.assertThat; +import org.hamcrest.Matchers; +import org.hamcrest.MatcherAssert; +import org.junit.Test; + +public class FooTest { + + Foo foo = new Foo(); + + @Test + public void test01() { + assertThat(foo.foo(10)).isEqualTo(9); + } + + @Test + public void test02() { + assertThat(foo.foo(100)).isEqualTo(99); + } + + @Test + public void test03() { + assertThat(foo.foo(0)).isEqualTo(0); // fails + } + + @Test + public void test04() { + assertThat(foo.foo(-10)).isEqualTo(-9); + + // try to use hamcrest instead of assertj + MatcherAssert.assertThat(foo.foo(-10), Matchers.is(-9)); + } +} diff --git a/example/BuildToolMaven/pom.xml b/example/BuildToolMaven/pom.xml new file mode 100644 index 000000000..58103cae6 --- /dev/null +++ b/example/BuildToolMaven/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + example + BuildToolMaven + 0.0.1-SNAPSHOT + + + junit + junit + 4.13.1 + test + + + + 1.8 + ${java.version} + ${java.version} + + diff --git a/example/BuildToolMaven/src/main/java/example/Foo.java b/example/BuildToolMaven/src/main/java/example/Foo.java new file mode 100644 index 000000000..6e45f000f --- /dev/null +++ b/example/BuildToolMaven/src/main/java/example/Foo.java @@ -0,0 +1,13 @@ +package example; + +public class Foo { + + public int foo(int n) { + if (n > 0) { + n--; + } else { + n++; + } + return n; + } +} diff --git a/example/BuildToolMaven/src/test/java/example/FooTest.java b/example/BuildToolMaven/src/test/java/example/FooTest.java new file mode 100644 index 000000000..52bd816eb --- /dev/null +++ b/example/BuildToolMaven/src/test/java/example/FooTest.java @@ -0,0 +1,27 @@ +package example; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class FooTest { + + @Test + public void test01() { + assertEquals(9, new Foo().foo(10)); + } + + @Test + public void test02() { + assertEquals(99, new Foo().foo(100)); + } + + @Test + public void test03() { + assertEquals(0, new Foo().foo(0)); + } + + @Test + public void test04() { + assertEquals(-9, new Foo().foo(-10)); + } +} diff --git a/src/main/java/jp/kusumotolab/kgenprog/project/ProductSourcePath.java b/src/main/java/jp/kusumotolab/kgenprog/project/ProductSourcePath.java index a7a197449..b83f5b0f1 100644 --- a/src/main/java/jp/kusumotolab/kgenprog/project/ProductSourcePath.java +++ b/src/main/java/jp/kusumotolab/kgenprog/project/ProductSourcePath.java @@ -1,5 +1,7 @@ package jp.kusumotolab.kgenprog.project; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; public final class ProductSourcePath extends SourcePath { @@ -23,4 +25,5 @@ public ProductSourcePath(final Path rootPath, final Path path) { public FullyQualifiedName createFullyQualifiedName(final String className) { return new TargetFullyQualifiedName(className); } + } diff --git a/src/main/java/jp/kusumotolab/kgenprog/project/SourcePath.java b/src/main/java/jp/kusumotolab/kgenprog/project/SourcePath.java index 320e2f93b..c40c1475b 100644 --- a/src/main/java/jp/kusumotolab/kgenprog/project/SourcePath.java +++ b/src/main/java/jp/kusumotolab/kgenprog/project/SourcePath.java @@ -25,8 +25,10 @@ protected SourcePath(final Path rootPath, final Path path) { @Override public boolean equals(final Object o) { - return this.toString() - .equals(o.toString()); + if (!(o instanceof SourcePath)) { + return false; + } + return path.equals(((SourcePath) o).path); } @Override diff --git a/src/main/java/jp/kusumotolab/kgenprog/project/factory/BuildToolProjectFactory.java b/src/main/java/jp/kusumotolab/kgenprog/project/factory/BuildToolProjectFactory.java index db6e02a26..f79439435 100644 --- a/src/main/java/jp/kusumotolab/kgenprog/project/factory/BuildToolProjectFactory.java +++ b/src/main/java/jp/kusumotolab/kgenprog/project/factory/BuildToolProjectFactory.java @@ -6,6 +6,7 @@ import java.util.Collection; import java.util.Collections; import java.util.stream.Collectors; +import java.util.stream.Stream; public abstract class BuildToolProjectFactory implements ProjectFactory { @@ -16,16 +17,19 @@ public BuildToolProjectFactory(final Path rootPath) { } protected final Collection getConfigPath() { - try { - return Files.walk(rootPath) - .filter(p -> p.toString() - .endsWith(getConfigFileName())) + try (final Stream stream = Files.walk(rootPath, 1)) { // max depth should be 1 + return stream.filter(p -> p.endsWith(getConfigFileName())) .collect(Collectors.toList()); - } catch (IOException e) { + } catch (final IOException e) { // do nothing } return Collections.emptyList(); } + @Override + public boolean isApplicable() { + return !getConfigPath().isEmpty(); + } + protected abstract String getConfigFileName(); } diff --git a/src/main/java/jp/kusumotolab/kgenprog/project/factory/MavenProjectFactory.java b/src/main/java/jp/kusumotolab/kgenprog/project/factory/MavenProjectFactory.java index 829e53153..d6a3484fb 100644 --- a/src/main/java/jp/kusumotolab/kgenprog/project/factory/MavenProjectFactory.java +++ b/src/main/java/jp/kusumotolab/kgenprog/project/factory/MavenProjectFactory.java @@ -1,20 +1,21 @@ package jp.kusumotolab.kgenprog.project.factory; +import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.nio.file.FileVisitResult; +import java.io.OutputStream; +import java.io.PrintStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import java.util.stream.Stream; +import org.apache.commons.io.output.TeeOutputStream; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.maven.cli.MavenCli; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jp.kusumotolab.kgenprog.project.ClassPath; @@ -23,20 +24,16 @@ public class MavenProjectFactory extends BuildToolProjectFactory { - private static final String CONFIG_FILE_NAME = "pom.xml"; private static final Logger log = LoggerFactory.getLogger(MavenProjectFactory.class); + private static final String CONFIG_FILE_NAME = "pom.xml"; - private final Path rootPath; + public static void main(String[] args) { + MavenProjectFactory m = new MavenProjectFactory(Paths.get("example/BuildToolMaven")); + m.create(); + } public MavenProjectFactory(final Path rootPath) { super(rootPath); - - this.rootPath = rootPath; - } - - @Override - public boolean isApplicable() { - return getConfigPath().size() > 0; } @Override @@ -46,109 +43,99 @@ protected String getConfigFileName() { @Override public TargetProject create() { - final List sourcePathList = resolveSourcePath(rootPath); - final List testSourcePathList = resolveTestPath(rootPath); - final List classPathList = resolveClassPath(rootPath); - return new TargetProject(rootPath, sourcePathList, testSourcePathList, classPathList); - } - - private List resolveSourcePath(final Path rootPath) { - final Path path = rootPath.resolve("src") - .resolve("main") - .resolve("java"); - final List javaFilePaths = searchJavaFilePaths(path); - return javaFilePaths.stream() - .map(p -> ProductSourcePath.relativizeAndCreate(rootPath, p)) - .collect(Collectors.toList()); - } - - private List resolveTestPath(final Path rootPath) { - final Path path = rootPath.resolve("src") - .resolve("test") - .resolve("java"); - final List javaFilePaths = searchJavaFilePaths(path); - return javaFilePaths.stream() - .map(p -> TestSourcePath.relativizeAndCreate(rootPath, p)) - .collect(Collectors.toList()); + final String dependencies = runMaven( + List.of("dependency:build-classpath"), + "Dependencies classpath:\\R(?.+)\\R"); + final String srcDirs = runMaven( + List.of("help:evaluate", "-Dexpression=project.build.sourceDirectory"), + "No artifact parameter specified.*?\\R.*?\\R(?.+)\\R"); + final String testDir = runMaven( + List.of("help:evaluate", "-Dexpression=project.build.testSourceDirectory"), + "No artifact parameter specified.*?\\R.*?\\R(?.+)\\R"); + + return createTargetProject(rootPath, srcDirs, testDir, dependencies); } - private class JavaFileVisitor extends SimpleFileVisitor { + private TargetProject createTargetProject(final Path rootPath, + final String srcDir, final String testDir, final String dependencies) { - private final List javaFilePathList = new ArrayList<>(); - - @Override - public FileVisitResult visitFile(final Path path, final BasicFileAttributes attrs) { - final Path fileName = path.getFileName(); - final String pathString = fileName.toString(); - if (pathString.endsWith(".java")) { - javaFilePathList.add(path); - } - return FileVisitResult.CONTINUE; + // TODO should be handled.. + if (srcDir == null || srcDir.isEmpty() || + testDir == null || testDir.isEmpty() || + dependencies == null || dependencies.isEmpty()) { + log.error("Maven parse failed."); + return null; } - List getJavaFilePathList() { - return javaFilePathList; + return new TargetProject(rootPath, + listSrcFiles(srcDir), + listTestFiles(testDir), + Stream.of(dependencies.split(";")) + .map(Paths::get) + .map(ClassPath::new) + .collect(Collectors.toList())); + } + + private List listSrcFiles(final String dir) { + try (final Stream stream = Files.walk(Paths.get(dir))) { + return stream.filter(p -> !Files.isDirectory(p)) + .map(p -> new ProductSourcePath(rootPath, rootPath.toAbsolutePath().relativize(p))) + .collect(Collectors.toList()); + } catch (final IOException e) { + log.error("Maven parse failed."); // TODO } + return Collections.emptyList(); } - private List searchJavaFilePaths(final Path rootPath) { - final JavaFileVisitor visitor = new JavaFileVisitor(); - try { - Files.walkFileTree(rootPath, visitor); + private List listTestFiles(final String dir) { + try (final Stream stream = Files.walk(Paths.get(dir))) { + return stream.filter(p -> !Files.isDirectory(p)) + .map(p -> new TestSourcePath(rootPath, rootPath.toAbsolutePath().relativize(p))) + .collect(Collectors.toList()); } catch (final IOException e) { - e.printStackTrace(); + log.error("Maven parse failed."); // TODO } - return visitor.getJavaFilePathList(); + return Collections.emptyList(); } - private List resolveClassPath(final Path rootPath) { - final Path pomFilePath = rootPath.resolve(CONFIG_FILE_NAME); - return extractDependencyPaths(pomFilePath).stream() - .map(ClassPath::new) - .collect(Collectors.toList()); + private String runMaven(final List goalParams, final String regex) { + if (getConfigPath().isEmpty()) { + log.error("No {} found.", CONFIG_FILE_NAME); + return null; // TODO handle if no config here + } + + // set a dummy value to the environment var to suppress maven error + System.setProperty("maven.multiModuleProjectDirectory", "dummy"); + + // set maven output to be written to both stdout and baos using TeeOutputStream + // sysout is for show kgp users and baos is for parsing it + final OutputStream outBuffer = new ByteArrayOutputStream(); + final PrintStream outDefault = System.out; //NOSONAR + final OutputStream outTree = new TeeOutputStream(outDefault, outBuffer); + System.setOut(new PrintStream(outTree)); + + final Path pom = getConfigPath().iterator() + .next(); + final String[] params = ArrayUtils.addAll( + new String[] {"-f", pom.toString()}, + goalParams.toArray(String[]::new)); + + // exec + MavenCli.doMain(params, null); + System.setOut(outDefault); + + // return the parsed stdout value based on the given regex + return parseMavenStdout(outBuffer.toString(), regex); } - private List extractDependencyPaths(final Path pomFilePath) { - final List list = new ArrayList<>(); - try { - final String userHome = System.getProperty("user.home"); - final MavenXpp3Reader reader = new MavenXpp3Reader(); - final Model model = reader.read(Files.newBufferedReader(pomFilePath)); - final Path repositoryPath = Paths.get(userHome) - .resolve(".m2") - .resolve("repository"); - - for (final Object object : model.getDependencies()) { - if (!(object instanceof Dependency)) { - continue; - } - final Dependency dependency = (Dependency) object; - - Path path = repositoryPath; - final String groupId = dependency.getGroupId(); - for (final String string : groupId.split("\\.")) { - path = path.resolve(string); - } - - final Path libPath = path.resolve(dependency.getArtifactId()) - .resolve(dependency.getVersion()); - if (!Files.isDirectory(libPath)) { - continue; - } - - Files.find(libPath, Integer.MAX_VALUE, (p, attr) -> p.toString() - .endsWith(".jar")) - .forEach(list::add); - - Files.find(libPath, Integer.MAX_VALUE, (p, attr) -> p.toString() - .endsWith(".pom")) - .map(this::extractDependencyPaths) - .flatMap(Collection::stream) - .forEach(list::add); - } - } catch (final IOException | XmlPullParserException e) { - log.error(e.getMessage()); + private static String parseMavenStdout(final String stdout, final String regex) { + final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE); + final Matcher matcher = pattern.matcher(stdout); + if (!matcher.find()) { + log.error("Maven parse error."); + return "maven parse error"; } - return list; + return matcher.group("res"); } + } diff --git a/src/test/java/jp/kusumotolab/kgenprog/project/factory/MavenProjectFactoryTest.java b/src/test/java/jp/kusumotolab/kgenprog/project/factory/MavenProjectFactoryTest.java index b5b800722..d8f4fb39b 100644 --- a/src/test/java/jp/kusumotolab/kgenprog/project/factory/MavenProjectFactoryTest.java +++ b/src/test/java/jp/kusumotolab/kgenprog/project/factory/MavenProjectFactoryTest.java @@ -5,6 +5,7 @@ import java.nio.file.Paths; import java.util.List; import org.junit.Test; +import jp.kusumotolab.kgenprog.project.ClassPath; import jp.kusumotolab.kgenprog.project.ProductSourcePath; import jp.kusumotolab.kgenprog.project.TestSourcePath; @@ -12,25 +13,23 @@ public class MavenProjectFactoryTest { @Test public void testCreate() { - final Path path = Paths.get("example", "BuildSuccess05"); + final Path path = Paths.get("example", "BuildToolMaven"); final MavenProjectFactory mavenProjectFactory = new MavenProjectFactory(path); final TargetProject targetProject = mavenProjectFactory.create(); final List productSourcePaths = targetProject.getProductSourcePaths(); assertThat(productSourcePaths) - .hasSize(1) - .contains(new ProductSourcePath(path, Paths.get("src/main/java/example/Foo.java"))); + .containsOnly(new ProductSourcePath(path, Paths.get("src/main/java/example/Foo.java"))); final List testSourcePaths = targetProject.getTestSourcePaths(); assertThat(testSourcePaths) - .hasSize(1) - .contains(new TestSourcePath(path, Paths.get("src/test/java/example/FooTest.java"))); + .containsOnly(new TestSourcePath(path, Paths.get("src/test/java/example/FooTest.java"))); - // TODO: fails due to missing feature of dependency resolvement for Maven projects. -// final List classPaths = targetProject.getClassPaths(); -// assertThat(classPaths) -// .hasSize(2) -// .extracting(ClassPath::toString) -// .endsWith("junit-4.13.1.jar"); + final List classPaths = targetProject.getClassPaths(); + assertThat(classPaths) + .hasSize(2) + .extracting(ClassPath::toString) + .anySatisfy(s -> assertThat(s).endsWith("junit-4.13.1.jar")) + .anySatisfy(s -> assertThat(s).endsWith("hamcrest-core-1.3.jar")); } }