diff --git a/docker/controller/Dockerfile b/docker/controller/Dockerfile index f1cc4de4df..7543c487f6 100644 --- a/docker/controller/Dockerfile +++ b/docker/controller/Dockerfile @@ -1,11 +1,37 @@ FROM jeanblanchard/java:serverjre-8 MAINTAINER JunHo Yoon "junoyoon@gmail.com" -RUN apk update; apk add curl bash +RUN apk update; apk add curl bash tar + +ARG MAVEN_VERSION=3.6.3 +ARG MAVEN_DOWNLOAD_BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries + +ARG GRADLE_VERSION=6.7.1 +ARG GRADLE_DOWNLOAD_BASE_URL=https://services.gradle.org/distributions + +# Install maven +RUN mkdir -p /usr/share/maven \ + && echo "Downloading maven" \ + && curl -fsSL -o /tmp/apache-maven.tar.gz ${MAVEN_DOWNLOAD_BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \ + && echo "Unziping maven" \ + && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \ + && rm -f /tmp/apache-maven.tar.gz + +# Install gradle +RUN mkdir -p /usr/share/gradle \ + && echo "Downloading gradle" \ + && curl -fsSL -o /tmp/gradle.zip ${GRADLE_DOWNLOAD_BASE_URL}/gradle-${GRADLE_VERSION}-bin.zip \ + && echo "Unziping gradle" \ + && unzip -d /usr/share/gradle /tmp/gradle.zip \ + && rm -f /tmp/gradle.zip # Set up environment variables ENV BASE_DIR=/opt \ - NGRINDER_HOME=/opt/ngrinder-controller + NGRINDER_HOME=/opt/ngrinder-controller \ + MAVEN_HOME=/usr/share/maven \ + GRADLE_HOME=/usr/share/gradle/gradle-${GRADLE_VERSION} + +ENV PATH=$PATH:$GRADLE_HOME/bin:$MAVEN_HOME/bin # Expose ports EXPOSE 80 16001 12000-12009 diff --git a/docker/controller/scripts/run.sh b/docker/controller/scripts/run.sh index 63b8ad6a7e..1854f0a443 100755 --- a/docker/controller/scripts/run.sh +++ b/docker/controller/scripts/run.sh @@ -1,3 +1,7 @@ #!/usr/bin/env bash -echo "wait a while extracting war files... It takes time for the first run." +echo "Installed build tools." +mvn -version +gradle -version + +echo "Wait a while extracting war files... It takes time for the first run." java -jar ${BASE_DIR}/ngrinder-*.war --port 80 diff --git a/docker/prepare.sh b/docker/prepare.sh index b96f96616f..2ba3c37db6 100755 --- a/docker/prepare.sh +++ b/docker/prepare.sh @@ -2,4 +2,4 @@ echo "copying ngrinder-controller" mkdir -p controller/binary rm controller/binary/ngrinder* -cp ../ngrinder-controller/target/*.war controller/binary/ +cp ../ngrinder-controller/build/libs/*.war controller/binary/ diff --git a/ngrinder-controller/build.gradle b/ngrinder-controller/build.gradle index e4a9ea4868..16d88f1076 100644 --- a/ngrinder-controller/build.gradle +++ b/ngrinder-controller/build.gradle @@ -45,14 +45,6 @@ dependencies { compile (group: "org.python", name: "jython-standalone", version: "2.5.3") compile (group: "com.google.guava", name: "guava", version: "20.0") compile (group: "org.springframework.security", name: "spring-security-taglibs", version: spring_security_version) - - compile (group: "org.apache.maven", name: "maven-embedder", version: "3.6.3") - compile (group: "org.apache.maven", name: "maven-compat", version: "3.6.3") - compile (group: "org.eclipse.aether", name: "aether-connector-basic", version: "1.1.0") - compile (group: "org.eclipse.aether", name: "aether-transport-wagon", version: "1.1.0") - compile (group: "org.apache.maven.wagon", name: "wagon-http", version: "2.8") - compile (group: "org.apache.maven.wagon", name: "wagon-provider-api", version: "2.8") - compile (group: "org.liquibase", name: "liquibase-core", version: "3.5.3") compile (group: "org.hibernate", name: "hibernate-jcache", version: hibernate_version) compile (group: "com.github.ben-manes.caffeine", name: "caffeine", version: "2.6.2") diff --git a/ngrinder-controller/src/main/java/org/ngrinder/common/constant/CacheConstants.java b/ngrinder-controller/src/main/java/org/ngrinder/common/constant/CacheConstants.java index 4eeec65297..4a052b5a46 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/common/constant/CacheConstants.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/common/constant/CacheConstants.java @@ -42,7 +42,7 @@ public interface CacheConstants { String CACHE_USER_ENTITY = "org.ngrinder.model.User"; String LOCAL_CACHE_GITHUB_SCRIPTS = "github_scripts"; - String LOCAL_CACHE_GITHUB_IS_MAVEN_GROOVY = "github_is_maven_groovy"; + String LOCAL_CACHE_GITHUB_GROOVY_PROJECT_SCRIPT_TYPE = "github_groovy_project_script_type"; int REGION_CACHE_TIME_TO_LIVE_SECONDS = 20; } diff --git a/ngrinder-controller/src/main/java/org/ngrinder/infra/config/DynamicCacheConfig.java b/ngrinder-controller/src/main/java/org/ngrinder/infra/config/DynamicCacheConfig.java index dc78f53502..bd681f7204 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/infra/config/DynamicCacheConfig.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/infra/config/DynamicCacheConfig.java @@ -158,7 +158,7 @@ public CacheConfigHolder cacheConfigMap() { cm.addLocalCache(LOCAL_CACHE_RIGHT_PANEL_ENTRIES, 1 * DAY, 1); cm.addLocalCache(LOCAL_CACHE_LEFT_PANEL_ENTRIES, 1 * DAY, 1); cm.addLocalCache(LOCAL_CACHE_CURRENT_PERFTEST_STATISTICS, 5, 1); - cm.addLocalCache(LOCAL_CACHE_GITHUB_IS_MAVEN_GROOVY, 5 * MIN, 300); + cm.addLocalCache(LOCAL_CACHE_GITHUB_GROOVY_PROJECT_SCRIPT_TYPE, 5 * MIN, 300); return cm; } diff --git a/ngrinder-controller/src/main/java/org/ngrinder/infra/spring/listener/ApplicationPreparedListener.java b/ngrinder-controller/src/main/java/org/ngrinder/infra/spring/listener/ApplicationPreparedListener.java index 0cdaa3f5b6..5fe57a4c7f 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/infra/spring/listener/ApplicationPreparedListener.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/infra/spring/listener/ApplicationPreparedListener.java @@ -1,22 +1,25 @@ package org.ngrinder.infra.spring.listener; import com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider; -import org.springframework.boot.context.event.ApplicationPreparedEvent; +import org.springframework.boot.context.event.ApplicationContextInitializedEvent; import org.springframework.context.ApplicationListener; import javax.cache.Caching; import javax.cache.spi.CachingProvider; import java.util.Iterator; +import static org.ngrinder.starter.InstallationChecker.checkAll; + /** * @since 3.5.0 * */ -public class ApplicationPreparedListener implements ApplicationListener { +public class ApplicationPreparedListener implements ApplicationListener { @SuppressWarnings("NullableProblems") @Override - public void onApplicationEvent(ApplicationPreparedEvent event) { + public void onApplicationEvent(ApplicationContextInitializedEvent event) { removeCacheProviderExceptCaffeineCacheProvider(); + checkAll(); } /** @@ -31,4 +34,5 @@ private static void removeCacheProviderExceptCaffeineCacheProvider() { } } } + } diff --git a/ngrinder-controller/src/main/java/org/ngrinder/perftest/service/PerfTestService.java b/ngrinder-controller/src/main/java/org/ngrinder/perftest/service/PerfTestService.java index 9954afe325..89a0c1388e 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/perftest/service/PerfTestService.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/perftest/service/PerfTestService.java @@ -657,7 +657,7 @@ public ScriptHandler prepareDistribution(PerfTest perfTest) throws IOException { String scriptName = perfTest.getScriptName(); gitHubFileEntryService.checkoutGitHubScript(perfTest, ghRepository, gitHubConfig); scriptEntry = gitHubFileEntryService.getOne(ghRepository, gitHubConfig, scriptName); - gitHubFileEntryService.evictGitHubMavenGroovyCache(ghRepository, scriptName, gitHubConfig.getBranch()); + gitHubFileEntryService.evictGitHubGroovyProjectScriptTypeCache(ghRepository, scriptName, gitHubConfig.getBranch()); } else { scriptEntry = checkNotNull( fileEntryService.getOne(user, @@ -680,7 +680,8 @@ public ScriptHandler prepareDistribution(PerfTest perfTest) throws IOException { } catch (IOException e) { noOp(); } - throw processException("Error while file distribution is prepared."); + throw processException("Error while file distribution is prepared.\n" + + "If you run groovy project type script, Please check your build script and make sure Maven or Gradle is installed."); } return handler; } diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyGradleProjectScriptHandler.java b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyGradleProjectScriptHandler.java new file mode 100644 index 0000000000..e9108f0a57 --- /dev/null +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyGradleProjectScriptHandler.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2012-present NAVER Corp. + * + * This file is part of The nGrinder software distribution. Refer to + * the file LICENSE which is part of The nGrinder distribution for + * licensing details. The nGrinder distribution is available on the + * Internet at https://naver.github.io/ngrinder + * + * 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 org.ngrinder.script.handler; + +import org.apache.commons.io.IOUtils; +import org.ngrinder.common.util.PathUtils; +import org.ngrinder.infra.config.Config; +import org.ngrinder.model.User; +import org.ngrinder.script.model.FileEntry; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import static java.lang.System.getenv; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.file.Paths.get; +import static org.apache.commons.io.FileUtils.deleteQuietly; +import static org.apache.commons.io.FilenameUtils.normalize; +import static org.apache.commons.lang.StringUtils.EMPTY; +import static org.apache.commons.lang.StringUtils.isNotEmpty; +import static org.ngrinder.common.util.AccessUtils.getSafe; +import static org.ngrinder.common.util.CollectionUtils.buildMap; +import static org.ngrinder.common.util.ExceptionUtils.processException; +import static org.ngrinder.common.util.UrlUtils.getHost; +import static org.ngrinder.script.model.FileCategory.SCRIPT; +import static org.ngrinder.script.model.FileType.DIR; + +/** + * Groovy gradle project {@link ScriptHandler}. + * + * @since 3.5.3 + */ +@Component +public class GroovyGradleProjectScriptHandler extends GroovyProjectScriptHandler { + + public static final String GRADLE_HOME_ENV_NAME = "GRADLE_HOME"; + + private final String ngrinderHomePath; + private String gradlePath; + + public GroovyGradleProjectScriptHandler(Config config) { + super("groovy_gradle", "", "Groovy Gradle Project", "groovy", "build.gradle", true); + + gradlePath = getSafe(getenv(GRADLE_HOME_ENV_NAME), ""); + if (isNotEmpty(gradlePath)) { + gradlePath += "/bin/"; + } + + ngrinderHomePath = config.getHome().getDirectory().getAbsolutePath(); + } + + @Override + protected String getCopyDependenciesCommand(File distDir) { + String distDirPath = distDir.getAbsolutePath(); + return gradlePath + "gradle -I " + ngrinderHomePath + "/init.gradle -p" + distDirPath + + " __copyDependencies -PoutputDirectory=" + distDirPath + "/lib"; + } + + @Override + protected boolean isSuccess(List results) { + if (results.isEmpty()) { + return false; + } + return results.stream().noneMatch(str -> str.contains("FAILED")); + } + + @Override + public boolean prepareScriptEnv(User user, String path, String fileName, String name, // LF + String url, boolean createLib, String scriptContent) { + path = PathUtils.join(path, fileName); + // Create Dir entry + createBaseDirectory(user, path); + // Create each template entries + createFileEntries(user, path, name, url, scriptContent); + if (createLib) { + createLibraryDirectory(user, path); + } + return false; + } + + @Override + protected void deleteUnnecessaryFilesFromDist(File distDir) { + super.deleteUnnecessaryFilesFromDist(distDir); + deleteQuietly(new File(distDir, ".gradle")); + } + + private void createFileEntries(User user, String path, String name, String url, String scriptContent) { + String[] scriptTemplatePaths = { getBuildScriptName(), "src/main/resources/resource1.txt", "src/main/java/TestRunner.groovy" }; + for (String scriptTemplatePath : scriptTemplatePaths) { + try (InputStream inputStream = new ClassPathResource("/script_template/groovy_gradle/" + scriptTemplatePath).getInputStream()) { + String fileContent = IOUtils.toString(inputStream, UTF_8.name()); + if (scriptTemplatePath.endsWith("TestRunner.groovy")) { + fileContent = scriptContent; + } else { + fileContent = fileContent.replace("${userName}", user.getUserName()); + fileContent = fileContent.replace("${name}", name); + fileContent = fileContent.replace("${url}", url); + } + FileEntry fileEntry = new FileEntry(); + fileEntry.setContent(fileContent); + fileEntry.setPath(normalize(PathUtils.join(path, scriptTemplatePath), true)); + fileEntry.setDescription("create groovy gradle project"); + String hostName = getHost(url); + if (isNotEmpty(hostName) + && fileEntry.getFileType().getFileCategory() == SCRIPT) { + fileEntry.getProperties().put("targetHosts", getHost(url)); + } else { + fileEntry.getProperties().put("targetHosts", EMPTY); + } + getFileEntryRepository().save(user, fileEntry, UTF_8.name()); + } catch (IOException e) { + throw processException("Error while saving " + get(scriptTemplatePath).getFileName(), e); + } + } + } + + private void createBaseDirectory(User user, String path) { + FileEntry dirEntry = new FileEntry(); + dirEntry.setPath(path); + // Make it eclipse default folder ignored. + dirEntry.setProperties(buildMap("svn:ignore", ".project\n.classpath\n.settings\ntarget")); + dirEntry.setFileType(DIR); + dirEntry.setDescription("create groovy gradle project"); + getFileEntryRepository().save(user, dirEntry, null); + } +} diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyMavenProjectScriptHandler.java b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyMavenProjectScriptHandler.java index 8974ad82e6..72cd256f6b 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyMavenProjectScriptHandler.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyMavenProjectScriptHandler.java @@ -13,37 +13,14 @@ */ package org.ngrinder.script.handler; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.maven.cli.MavenCli; -import org.ngrinder.common.exception.NGrinderRuntimeException; -import org.ngrinder.common.util.PathUtils; -import org.ngrinder.common.util.PropertiesWrapper; -import org.ngrinder.common.util.UrlUtils; -import org.ngrinder.model.PerfTest; -import org.ngrinder.model.User; -import org.ngrinder.script.model.FileCategory; -import org.ngrinder.script.model.FileEntry; -import org.ngrinder.script.model.FileType; -import org.ngrinder.script.repository.FileEntryRepository; -import org.ngrinder.script.repository.GitHubFileEntryRepository; -import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Component; -import org.tmatesoft.svn.core.wc.SVNRevision; import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.util.List; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.maven.wagon.PathUtils.filename; -import static org.ngrinder.common.util.CollectionUtils.buildMap; -import static org.ngrinder.common.util.CollectionUtils.newArrayList; -import static org.ngrinder.common.util.ExceptionUtils.processException; -import static org.ngrinder.common.util.LoggingUtils.format; +import static java.lang.System.getenv; +import static org.apache.commons.lang.StringUtils.isNotEmpty; +import static org.ngrinder.common.util.AccessUtils.getSafe; /** * Groovy Maven project {@link ScriptHandler}. @@ -51,257 +28,33 @@ * @since 3.2 */ @Component -public class GroovyMavenProjectScriptHandler extends GroovyScriptHandler implements ProjectHandler { +public class GroovyMavenProjectScriptHandler extends GroovyProjectScriptHandler { - /** - * Constructor. - */ - public GroovyMavenProjectScriptHandler() { - super("groovy_maven", "", "Groovy Maven Project", "groovy"); - } - - private static final String RESOURCES = "src/main/resources/"; - private static final String JAVA = "src/main/java/"; - private static final String GROOVY = "src/main/groovy/"; - private static final String LIB = "lib/"; - - @Override - public boolean canHandle(FileEntry fileEntry) { - String path = fileEntry.getPath(); - if (!FilenameUtils.isExtension(path, "groovy")) { - return false; - } - - //noinspection SimplifiableIfStatement - if (!isGroovyMavenPath(path)) { - return false; - } - - if (isGitHubFileEntry(fileEntry)) { - return StringUtils.equals(fileEntry.getProperties().get("type"), "groovy-maven"); - } else { - if (fileEntry.getCreatedBy() == null) { - return false; - } - return getFileEntryRepository().hasOne(fileEntry.getCreatedBy(), getBasePath(path) + "pom.xml"); - } - } - - @Override - public Integer displayOrder() { - return 400; - } + public static final String MAVEN_HOME_ENV_NAME = "MAVEN_HOME"; - @Override - protected Integer order() { - return 200; - } - - @Override - public List getLibAndResourceEntries(User user, FileEntry scriptEntry, long revision) { - List fileList = newArrayList(); - String basePath = getBasePath(scriptEntry); - FileEntryRepository fileEntryRepository = getFileEntryRepository(); - GitHubFileEntryRepository gitHubFileEntryRepository = getGitHubFileEntryRepository(); - - List resourcesFileEntry; - List javaFileEntry; - List groovyFileEntry; - List libFileEntry; - - if (isGitHubFileEntry(scriptEntry)) { - try { - javaFileEntry = gitHubFileEntryRepository.findAll(basePath + JAVA); - resourcesFileEntry = gitHubFileEntryRepository.findAll(basePath + RESOURCES); - groovyFileEntry = gitHubFileEntryRepository.findAll(basePath + GROOVY); - libFileEntry = gitHubFileEntryRepository.findAll(basePath + LIB); - fileList.add(gitHubFileEntryRepository.findOne(basePath + "pom.xml")); - } catch (IOException e) { - throw new NGrinderRuntimeException(e); - } - } else { - resourcesFileEntry = fileEntryRepository.findAll(user, basePath + RESOURCES, revision, true); - javaFileEntry = fileEntryRepository.findAll(user, basePath + JAVA, revision, true); - groovyFileEntry = fileEntryRepository.findAll(user, basePath + GROOVY, revision, true); - libFileEntry = fileEntryRepository.findAll(user, basePath + LIB, revision, true); - fileList.add(fileEntryRepository.findOne(user, basePath + "pom.xml", SVNRevision.create(revision))); - } - - for (FileEntry eachFileEntry : resourcesFileEntry) { - FileType fileType = eachFileEntry.getFileType(); - if (fileType.isResourceDistributable()) { - fileList.add(eachFileEntry); - } - } - - for (FileEntry eachFileEntry : javaFileEntry) { - FileType fileType = eachFileEntry.getFileType(); - if (fileType.isLibDistributable() && !eachFileEntry.getPath().equals(scriptEntry.getPath())) { - fileList.add(eachFileEntry); - } - } - - for (FileEntry eachFileEntry : groovyFileEntry) { - FileType fileType = eachFileEntry.getFileType(); - if (fileType.isLibDistributable() && !eachFileEntry.getPath().equals(scriptEntry.getPath())) { - fileList.add(eachFileEntry); - } - } - - for (FileEntry eachFileEntry : libFileEntry) { - FileType fileType = eachFileEntry.getFileType(); - if (fileType.isLibDistributable()) { - fileList.add(eachFileEntry); - } - } + private String mavenPath; - return fileList; - } - - @Override - protected String calcDistSubPath(String basePath, FileEntry each) { - String calcDistSubPath = super.calcDistSubPath(basePath, each); - if (calcDistSubPath.startsWith(JAVA)) { - return calcDistSubPath.substring(JAVA.length() - 1); - } else if (calcDistSubPath.startsWith(GROOVY)) { - return calcDistSubPath.substring(GROOVY.length() - 1); - } else if (calcDistSubPath.startsWith(RESOURCES)) { - return calcDistSubPath.substring(RESOURCES.length() - 1); - } - return calcDistSubPath; - } - - @Override - protected void prepareDistMore(PerfTest perfTest, User user, FileEntry script, File distDir, - PropertiesWrapper properties, ProcessingResultPrintStream processingResult) { - String pomPathInSVN = PathUtils.join(getBasePath(script), "pom.xml"); - MavenCli cli = new MavenCli(); - processingResult.println("\nCopy dependencies by running 'mvn dependency:copy-dependencies" - + " -DoutputDirectory=./lib -DexcludeScope=provided'"); - - System.setProperty(MavenCli.MULTIMODULE_PROJECT_DIRECTORY, distDir.getAbsolutePath()); - - int result = cli.doMain(new String[]{ // goal specification - "dependency:copy-dependencies", // run dependency goal - "-DoutputDirectory=./lib", // to the lib folder - "-DexcludeScope=provided" // but exclude the provided - // library - }, distDir.getAbsolutePath(), processingResult, processingResult); - boolean success = (result == 0); - if (success) { - processingResult.printf("\nDependencies in %s was copied.\n", pomPathInSVN); - LOGGER.info(format(perfTest, "Dependencies in {} is copied into {}/lib folder", pomPathInSVN, distDir.getAbsolutePath())); - } else { - processingResult.printf("\nDependencies copy in %s is failed.\n", pomPathInSVN); - LOGGER.info(format(perfTest, "Dependencies copy in {} is failed.", pomPathInSVN)); - } - // Then it's not necessary to include pom.xml anymore. - FileUtils.deleteQuietly(new File(distDir, "pom.xml")); - processingResult.setSuccess(result == 0); - } - - @Override - public boolean prepareScriptEnv(User user, String path, String fileName, String name, // LF - String url, boolean createLib, String scriptContent) { - path = PathUtils.join(path, fileName); - // Create Dir entry - createBaseDirectory(user, path); - // Create each template entries - createFileEntries(user, path, name, url, scriptContent); - if (createLib) { - createLibraryDirectory(user, path); - } - return false; - } - - private void createLibraryDirectory(User user, String path) { - FileEntry fileEntry = new FileEntry(); - fileEntry.setPath(path + "/lib"); - fileEntry.setFileType(FileType.DIR); - fileEntry.setDescription("put private libraries here"); - getFileEntryRepository().save(user, fileEntry, null); - } + public GroovyMavenProjectScriptHandler() { + super("groovy_maven", "", "Groovy Maven Project", "groovy", "pom.xml", false); - private void createFileEntries(User user, String path, String name, String url, String scriptContent) { - String[] scriptTemplatePaths = { "pom.xml", "src/main/resources/resource1.txt", "src/main/java/TestRunner.groovy" }; - for (String scriptTemplatePath : scriptTemplatePaths) { - try (InputStream inputStream = new ClassPathResource("/script_template/groovy_maven/" + scriptTemplatePath).getInputStream()) { - String fileContent = IOUtils.toString(inputStream, UTF_8.name()); - if (scriptTemplatePath.endsWith("TestRunner.groovy")) { - fileContent = scriptContent; - } else { - fileContent = fileContent.replace("${userName}", user.getUserName()); - fileContent = fileContent.replace("${name}", name); - fileContent = fileContent.replace("${url}", url); - } - FileEntry fileEntry = new FileEntry(); - fileEntry.setContent(fileContent); - fileEntry.setPath(FilenameUtils.normalize(PathUtils.join(path, scriptTemplatePath), true)); - fileEntry.setDescription("create groovy maven project"); - String hostName = UrlUtils.getHost(url); - if (StringUtils.isNotEmpty(hostName) - && fileEntry.getFileType().getFileCategory() == FileCategory.SCRIPT) { - fileEntry.getProperties().put("targetHosts", UrlUtils.getHost(url)); - } else { - fileEntry.getProperties().put("targetHosts", StringUtils.EMPTY); - } - getFileEntryRepository().save(user, fileEntry, "UTF8"); - } catch (IOException e) { - throw processException("Error while saving " + filename(scriptTemplatePath), e); - } + mavenPath = getSafe(getenv(MAVEN_HOME_ENV_NAME), ""); + if (isNotEmpty(mavenPath)) { + mavenPath += "/bin/"; } } - private void createBaseDirectory(User user, String path) { - FileEntry dirEntry = new FileEntry(); - dirEntry.setPath(path); - // Make it eclipse default folder ignored. - dirEntry.setProperties(buildMap("svn:ignore", ".project\n.classpath\n.settings\ntarget")); - dirEntry.setFileType(FileType.DIR); - dirEntry.setDescription("create groovy maven project"); - getFileEntryRepository().save(user, dirEntry, null); - } - - /* - * (non-Javadoc) - * - * @see - * org.ngrinder.script.handler.ScriptHandler#getBasePath(java.lang.String) - */ @Override - public String getBasePath(String path) { - if (path.contains(JAVA)) { - return path.substring(0, path.lastIndexOf(JAVA)); - } else { - return path.substring(0, path.lastIndexOf(GROOVY)); - } + protected String getCopyDependenciesCommand(File distDir) { + String distDirPath = distDir.getAbsolutePath(); + return mavenPath + "mvn -f " + distDirPath + " dependency:copy-dependencies -DoutputDirectory=./lib " + + "-DexcludeScope=provided -Dmaven.multiModuleProjectDirectory=" + distDirPath; } @Override - public String getScriptExecutePath(String path) { - if (path.contains(JAVA)) { - return path.substring(path.lastIndexOf(JAVA) + JAVA.length()); - } else { - return path.substring(path.lastIndexOf(GROOVY) + GROOVY.length()); - } - } - - @Override - public FileEntry getDefaultQuickTestFilePath(String path) { - FileEntry fileEntry = new FileEntry(); - fileEntry.setPath(path + "/" + JAVA + "TestRunner.groovy"); - return fileEntry; - } - - public String getGroovyMavenPath(String path) { - if (path.contains(JAVA)) { - return path.substring(path.lastIndexOf(JAVA)); - } else { - return path.substring(path.lastIndexOf(GROOVY)); + protected boolean isSuccess(List results) { + if (results.isEmpty()) { + return false; } - } - - public boolean isGroovyMavenPath(String path) { - return path.contains(JAVA) || path.contains(GROOVY); + return results.stream().noneMatch(str -> str.contains("[ERROR]")); } } diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyProjectScriptHandler.java b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyProjectScriptHandler.java new file mode 100644 index 0000000000..93765404d0 --- /dev/null +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyProjectScriptHandler.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2012-present NAVER Corp. + * + * This file is part of The nGrinder software distribution. Refer to + * the file LICENSE which is part of The nGrinder distribution for + * licensing details. The nGrinder distribution is available on the + * Internet at https://naver.github.io/ngrinder + * + * 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 org.ngrinder.script.handler; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang.StringUtils; +import org.ngrinder.common.exception.NGrinderRuntimeException; +import org.ngrinder.common.util.PathUtils; +import org.ngrinder.common.util.PropertiesWrapper; +import org.ngrinder.model.PerfTest; +import org.ngrinder.model.User; +import org.ngrinder.script.model.FileEntry; +import org.ngrinder.script.model.FileType; +import org.ngrinder.script.repository.FileEntryRepository; +import org.ngrinder.script.repository.GitHubFileEntryRepository; +import org.tmatesoft.svn.core.wc.SVNRevision; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import static org.apache.commons.io.FileUtils.deleteQuietly; +import static org.ngrinder.common.util.CollectionUtils.newArrayList; +import static org.ngrinder.common.util.LoggingUtils.format; +import static org.ngrinder.script.model.FileType.DIR; +import static oshi.util.ExecutingCommand.runNative; + +/** + * Groovy project {@link ScriptHandler}. + * + * @since 3.5.3 + */ +@Getter +@Slf4j +public abstract class GroovyProjectScriptHandler extends GroovyScriptHandler implements ProjectHandler { + + protected static String RESOURCES = "src/main/resources/"; + protected static String JAVA = "src/main/java/"; + protected static String GROOVY = "src/main/groovy/"; + protected static String LIB = "lib/"; + + private final String buildScriptName; + + public GroovyProjectScriptHandler(String key, String extension, String title, + String codeMirrorKey, String buildScriptName, boolean creatable) { + super(key, extension, title, codeMirrorKey, creatable); + this.buildScriptName = buildScriptName; + } + + /** + * Return a command to copy dependencies specified in the build script to dist directory. + * */ + protected abstract String getCopyDependenciesCommand(File distDir); + + /** + * Check if copy dependencies is successful. + * + * @param results Result of executing command created by {@link #getCopyDependenciesCommand} with OSHI. + */ + protected abstract boolean isSuccess(List results); + + @Override + public boolean canHandle(FileEntry fileEntry) { + String path = fileEntry.getPath(); + if (!FilenameUtils.isExtension(path, "groovy")) { + return false; + } + + //noinspection SimplifiableIfStatement + if (!isGroovyProjectScriptPath(path)) { + return false; + } + + if (isGitHubFileEntry(fileEntry)) { + return StringUtils.equals(fileEntry.getProperties().get("type"), getKey()); + } else { + if (fileEntry.getCreatedBy() == null) { + return false; + } + return getFileEntryRepository().hasOne(fileEntry.getCreatedBy(), getBasePath(path) + buildScriptName); + } + } + + @Override + public Integer displayOrder() { + return 400; + } + + @Override + protected Integer order() { + return 200; + } + + @Override + public String getScriptExecutePath(String path) { + if (path.contains(JAVA)) { + return path.substring(path.lastIndexOf(JAVA) + JAVA.length()); + } else { + return path.substring(path.lastIndexOf(GROOVY) + GROOVY.length()); + } + } + + @Override + public FileEntry getDefaultQuickTestFilePath(String path) { + FileEntry fileEntry = new FileEntry(); + fileEntry.setPath(path + "/" + JAVA + "TestRunner.groovy"); + return fileEntry; + } + + @Override + protected String calcDistSubPath(String basePath, FileEntry each) { + String calcDistSubPath = super.calcDistSubPath(basePath, each); + if (calcDistSubPath.startsWith(JAVA)) { + return calcDistSubPath.substring(JAVA.length() - 1); + } else if (calcDistSubPath.startsWith(GROOVY)) { + return calcDistSubPath.substring(GROOVY.length() - 1); + } else if (calcDistSubPath.startsWith(RESOURCES)) { + return calcDistSubPath.substring(RESOURCES.length() - 1); + } + return calcDistSubPath; + } + + /* + * (non-Javadoc) + * + * @see + * org.ngrinder.script.handler.ScriptHandler#getBasePath(java.lang.String) + */ + @Override + public String getBasePath(String path) { + if (path.contains(JAVA)) { + return path.substring(0, path.lastIndexOf(JAVA)); + } else { + return path.substring(0, path.lastIndexOf(GROOVY)); + } + } + + @Override + protected void prepareDistMore(PerfTest perfTest, User user, FileEntry script, File distDir, + PropertiesWrapper properties, ProcessingResultPrintStream processingResult) { + String buildFilePathInSVN = PathUtils.join(getBasePath(script), getBuildScriptName()); + String copyDependenciesCommand = getCopyDependenciesCommand(distDir); + processingResult.println("\nCopy dependencies by running '" + copyDependenciesCommand + "'"); + + boolean success = isSuccess(runNative(copyDependenciesCommand)); + + if (success) { + processingResult.printf("\nDependencies in %s was copied.\n", buildFilePathInSVN); + log.info(format(perfTest, "Dependencies in {} is copied into {}/lib folder", buildFilePathInSVN, distDir.getAbsolutePath())); + } else { + processingResult.printf("\nDependencies copy in %s is failed.\n", buildFilePathInSVN); + log.info(format(perfTest, "Dependencies copy in {} is failed.", buildFilePathInSVN)); + } + + deleteUnnecessaryFilesFromDist(distDir); + processingResult.setSuccess(success); + } + + @Override + public List getLibAndResourceEntries(User user, FileEntry scriptEntry, long revision) { + List fileList = newArrayList(); + String basePath = getBasePath(scriptEntry); + FileEntryRepository fileEntryRepository = getFileEntryRepository(); + GitHubFileEntryRepository gitHubFileEntryRepository = getGitHubFileEntryRepository(); + + List resourcesFileEntry; + List javaFileEntry; + List groovyFileEntry; + List libFileEntry; + + if (isGitHubFileEntry(scriptEntry)) { + try { + javaFileEntry = gitHubFileEntryRepository.findAll(basePath + JAVA); + resourcesFileEntry = gitHubFileEntryRepository.findAll(basePath + RESOURCES); + groovyFileEntry = gitHubFileEntryRepository.findAll(basePath + GROOVY); + libFileEntry = gitHubFileEntryRepository.findAll(basePath + LIB); + fileList.add(gitHubFileEntryRepository.findOne(basePath + buildScriptName)); + } catch (IOException e) { + throw new NGrinderRuntimeException(e); + } + } else { + resourcesFileEntry = fileEntryRepository.findAll(user, basePath + RESOURCES, revision, true); + javaFileEntry = fileEntryRepository.findAll(user, basePath + JAVA, revision, true); + groovyFileEntry = fileEntryRepository.findAll(user, basePath + GROOVY, revision, true); + libFileEntry = fileEntryRepository.findAll(user, basePath + LIB, revision, true); + fileList.add(fileEntryRepository.findOne(user, basePath + buildScriptName, SVNRevision.create(revision))); + } + + for (FileEntry eachFileEntry : resourcesFileEntry) { + FileType fileType = eachFileEntry.getFileType(); + if (fileType.isResourceDistributable()) { + fileList.add(eachFileEntry); + } + } + + for (FileEntry eachFileEntry : javaFileEntry) { + FileType fileType = eachFileEntry.getFileType(); + if (fileType.isLibDistributable() && !eachFileEntry.getPath().equals(scriptEntry.getPath())) { + fileList.add(eachFileEntry); + } + } + + for (FileEntry eachFileEntry : groovyFileEntry) { + FileType fileType = eachFileEntry.getFileType(); + if (fileType.isLibDistributable() && !eachFileEntry.getPath().equals(scriptEntry.getPath())) { + fileList.add(eachFileEntry); + } + } + + for (FileEntry eachFileEntry : libFileEntry) { + FileType fileType = eachFileEntry.getFileType(); + if (fileType.isLibDistributable()) { + fileList.add(eachFileEntry); + } + } + + return fileList; + } + + protected void deleteUnnecessaryFilesFromDist(File distDir) { + deleteQuietly(new File(distDir, getBuildScriptName())); + } + + protected void createLibraryDirectory(User user, String path) { + FileEntry fileEntry = new FileEntry(); + fileEntry.setPath(path + "/lib"); + fileEntry.setFileType(DIR); + fileEntry.setDescription("put private libraries here"); + getFileEntryRepository().save(user, fileEntry, null); + } + + public String getGroovyProjectPath(String path) { + if (path.contains(JAVA)) { + return path.substring(path.lastIndexOf(JAVA)); + } else { + return path.substring(path.lastIndexOf(GROOVY)); + } + } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public boolean isGroovyProjectScriptPath(String path) { + return path.contains(JAVA) || path.contains(GROOVY); + } +} diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyScriptHandler.java b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyScriptHandler.java index 515ad654e1..2c360f01de 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyScriptHandler.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/GroovyScriptHandler.java @@ -1,4 +1,4 @@ -/* +/* * 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 @@ -9,7 +9,7 @@ * 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. + * limitations under the License. */ package org.ngrinder.script.handler; @@ -39,7 +39,7 @@ public class GroovyScriptHandler extends ScriptHandler { * Constructor. */ public GroovyScriptHandler() { - this("groovy", "groovy", "Groovy", "groovy"); + this("groovy", "groovy", "Groovy", "groovy", true); } /** @@ -49,9 +49,10 @@ public GroovyScriptHandler() { * @param extension extension * @param title title * @param codeMirrorKey code mirror key + * @param creatable creatable */ - public GroovyScriptHandler(String key, String extension, String title, String codeMirrorKey) { - super(key, extension, title, codeMirrorKey); + public GroovyScriptHandler(String key, String extension, String title, String codeMirrorKey, boolean creatable) { + super(key, extension, title, codeMirrorKey, creatable); } @Override diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/JythonScriptHandler.java b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/JythonScriptHandler.java index 8a31cc0cd4..7c293e5ae8 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/JythonScriptHandler.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/JythonScriptHandler.java @@ -1,4 +1,4 @@ -/* +/* * 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 @@ -9,7 +9,7 @@ * 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. + * limitations under the License. */ package org.ngrinder.script.handler; @@ -28,7 +28,7 @@ public class JythonScriptHandler extends ScriptHandler { * Constructor. */ public JythonScriptHandler() { - super("jython", "py", "Jython", "python"); + super("jython", "py", "Jython", "python", true); } @Override diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/NullScriptHandler.java b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/NullScriptHandler.java index 26137be9a7..a08bfd18dd 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/NullScriptHandler.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/NullScriptHandler.java @@ -25,6 +25,7 @@ import static org.ngrinder.common.util.CollectionUtils.getValue; import static org.ngrinder.common.util.CollectionUtils.newHashMap; +import static org.ngrinder.script.model.FileType.*; /** * Null {@link ScriptHandler} which implements Null object pattern. @@ -37,10 +38,11 @@ public class NullScriptHandler extends ScriptHandler { private final Map codeMirrorKey = newHashMap(); public NullScriptHandler() { - super("", "", null, null); - codeMirrorKey.put(FileType.PROPERTIES, "properties"); - codeMirrorKey.put(FileType.XML, "xml"); - codeMirrorKey.put(FileType.YAML, "yaml"); + super("", "", null, null, false); + codeMirrorKey.put(PROPERTIES, "properties"); + codeMirrorKey.put(XML, "xml"); + codeMirrorKey.put(YAML, "yaml"); + codeMirrorKey.put(GRADLE, "groovy"); } @Override diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/ScriptHandler.java b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/ScriptHandler.java index 4ecc054dee..1c7d8e00e1 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/ScriptHandler.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/ScriptHandler.java @@ -19,6 +19,7 @@ import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.ngrinder.common.constant.ControllerConstants; @@ -32,8 +33,6 @@ import org.ngrinder.script.model.FileType; import org.ngrinder.script.repository.FileEntryRepository; import org.ngrinder.script.repository.GitHubFileEntryRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.io.File; @@ -58,12 +57,14 @@ * @since 3.2 */ @Getter +@Slf4j public abstract class ScriptHandler implements ControllerConstants { - protected static final Logger LOGGER = LoggerFactory.getLogger(JythonScriptHandler.class); + private final String codemirrorKey; private final String title; private final String extension; private final String key; + private final boolean creatable; /** * Constructor. @@ -73,11 +74,12 @@ public abstract class ScriptHandler implements ControllerConstants { * @param title title of the handler * @param codeMirrorKey code mirror key */ - public ScriptHandler(String key, String extension, String title, String codeMirrorKey) { + public ScriptHandler(String key, String extension, String title, String codeMirrorKey, boolean creatable) { this.key = key; this.extension = extension; this.title = title; this.codemirrorKey = codeMirrorKey; + this.creatable = creatable; } @Autowired @@ -162,7 +164,7 @@ public void prepareDist(PerfTest perfTest, } File toDir = new File(distDir, calcDistSubPath(basePath, each)); processingResult.printf("%s is being written.\n", each.getPath()); - LOGGER.info(format(perfTest, "{} is being written in {}", each.getPath(), toDir)); + log.info(format(perfTest, "{} is being written in {}", each.getPath(), toDir)); if (isGitHubFileEntry(each)) { gitHubFileEntryRepository.writeContentTo(each.getPath(), toDir); } else { diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/ScriptHandlerFactory.java b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/ScriptHandlerFactory.java index 99113cf3aa..b99a64e815 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/script/handler/ScriptHandlerFactory.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/handler/ScriptHandlerFactory.java @@ -15,7 +15,7 @@ /** * ScriptHanderFactory which returns appropriate hander for the given {@link FileEntry}. - * + * * @since 3.2 */ @Component @@ -39,7 +39,7 @@ public void init() { visibleHandlers = newArrayList(); for (ScriptHandler each : this.scriptHandlers) { - if (!(each instanceof NullScriptHandler)) { + if (each.isCreatable()) { visibleHandlers.add(each); } } @@ -49,7 +49,7 @@ public void init() { /** * Get the appropriate {@link ScriptHandler} for the given fileEntry. - * + * * @param fileEntry fileEntry to be handled * @return {@link ScriptHandler}. {@link NullScriptHandler} if none is available. */ @@ -65,7 +65,7 @@ public ScriptHandler getHandler(FileEntry fileEntry) { /** * Get the appropriate {@link ScriptHandler} for the given key. - * + * * @param key ScriptHandler key * @return {@link ScriptHandler}. {@link NullScriptHandler} if none is available. */ diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/model/FileType.java b/ngrinder-controller/src/main/java/org/ngrinder/script/model/FileType.java index 586230ee93..1d6b1586d1 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/script/model/FileType.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/model/FileType.java @@ -29,7 +29,10 @@ public enum FileType { GROOVY_SCRIPT("Groovy Script", "groovy", FileCategory.SCRIPT, true, false), /** Groovy Maven project. */ - GROOVY_MAVEN_PROJECT("Groovy maven project", "pom", FileCategory.PROJECT, true, false), + GROOVY_MAVEN_PROJECT("Groovy maven project", "", FileCategory.PROJECT, true, false), + + /** Groovy Gradle project. */ + GROOVY_GRADLE_PROJECT("Groovy gradle project", "", FileCategory.PROJECT, true, false), /** Xml. */ XML("xml", "xml", FileCategory.DATA, true, true), @@ -41,6 +44,8 @@ public enum FileType { JSON("json", "json", FileCategory.DATA, false, true), /** YAML. */ YAML("yaml", "yml", FileCategory.DATA, false, false), + /** GRADLE. */ + GRADLE("Gradle build script", "gradle", FileCategory.DATA, false, false), /** Properties. */ PROPERTIES("properties", "properties", FileCategory.DATA, false, true), /** Classes. */ diff --git a/ngrinder-controller/src/main/java/org/ngrinder/script/service/GitHubFileEntryService.java b/ngrinder-controller/src/main/java/org/ngrinder/script/service/GitHubFileEntryService.java index 6d1f1958ea..01c4758b99 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/script/service/GitHubFileEntryService.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/script/service/GitHubFileEntryService.java @@ -14,6 +14,7 @@ import org.ngrinder.model.Status; import org.ngrinder.model.User; import org.ngrinder.perftest.service.PerfTestService; +import org.ngrinder.script.handler.GroovyGradleProjectScriptHandler; import org.ngrinder.script.handler.GroovyMavenProjectScriptHandler; import org.ngrinder.script.model.FileEntry; import org.ngrinder.script.model.GitHubConfig; @@ -42,7 +43,7 @@ import static org.apache.commons.io.FilenameUtils.getName; import static org.apache.commons.lang.StringUtils.isEmpty; import static org.apache.commons.lang.StringUtils.isNotEmpty; -import static org.ngrinder.common.constant.CacheConstants.LOCAL_CACHE_GITHUB_IS_MAVEN_GROOVY; +import static org.ngrinder.common.constant.CacheConstants.LOCAL_CACHE_GITHUB_GROOVY_PROJECT_SCRIPT_TYPE; import static org.ngrinder.common.constant.CacheConstants.LOCAL_CACHE_GITHUB_SCRIPTS; import static org.ngrinder.common.constant.ControllerConstants.PROP_CONTROLLER_GITHUB_BASE_URL; import static org.ngrinder.common.util.AopUtils.proxy; @@ -77,24 +78,29 @@ public class GitHubFileEntryService { private final GroovyMavenProjectScriptHandler groovyMavenProjectScriptHandler; + private final GroovyGradleProjectScriptHandler groovyGradleProjectScriptHandler; + private static final RateLimitHandlerEx rateLimitHandlerEx = new RateLimitHandlerEx(); public GitHubFileEntryService(FileEntryService fileEntryService, ObjectMapper objectMapper, Config config, @Lazy PerfTestService perfTestService, - GroovyMavenProjectScriptHandler groovyMavenProjectScriptHandler) { + GroovyMavenProjectScriptHandler groovyMavenProjectScriptHandler, + GroovyGradleProjectScriptHandler groovyGradleProjectScriptHandler) { this.fileEntryService = fileEntryService; this.objectMapper = objectMapper; this.config = config; this.perfTestService = perfTestService; this.groovyMavenProjectScriptHandler = groovyMavenProjectScriptHandler; + this.groovyGradleProjectScriptHandler = groovyGradleProjectScriptHandler; } public FileEntry getOne(GHRepository ghRepository, GitHubConfig gitHubConfig, String scriptPath) { String fullPath = getCheckoutDirPath(ghRepository, gitHubConfig, scriptPath); - if (proxy(this).isGroovyMavenProject(ghRepository, scriptPath, gitHubConfig.getBranch())) { - fullPath += groovyMavenProjectScriptHandler.getGroovyMavenPath(scriptPath); + String activeBranch = gitHubConfig.getBranch(); + if (isGroovyProjectScript(ghRepository, scriptPath, activeBranch)) { + fullPath += groovyMavenProjectScriptHandler.getGroovyProjectPath(scriptPath); FileEntry fileEntry = createGitHubScriptFileEntry(fullPath); - fileEntry.getProperties().put("type", "groovy-maven"); + fileEntry.getProperties().put("type", proxy(this).getGroovyProjectType(ghRepository, scriptPath, activeBranch)); fileEntry.getProperties().put("scriptPath", scriptPath); return fileEntry; } else { @@ -185,18 +191,31 @@ private boolean isSvnWorkingCopyDir(File directory) { return new File(directory.getPath() + "/.svn").exists(); } - @Cacheable(value = LOCAL_CACHE_GITHUB_IS_MAVEN_GROOVY, key = "#ghRepository.svnUrl + #scriptPath + #activeBranch") - public boolean isGroovyMavenProject(GHRepository ghRepository, String scriptPath, String activeBranch) { - if (!groovyMavenProjectScriptHandler.isGroovyMavenPath(scriptPath)) { + public boolean isGroovyProjectScript(GHRepository ghRepository, String scriptPath, String activeBranch) { + if (!groovyMavenProjectScriptHandler.isGroovyProjectScriptPath(scriptPath)) { return false; } + return proxy(this).getGroovyProjectType(ghRepository, scriptPath, activeBranch) != null; + } + @Cacheable(value = LOCAL_CACHE_GITHUB_GROOVY_PROJECT_SCRIPT_TYPE, key = "#ghRepository.svnUrl + #scriptPath + #activeBranch") + public String getGroovyProjectType(GHRepository ghRepository, String scriptPath, String activeBranch) { try { List ghContents = ghRepository.getDirectoryContent(groovyMavenProjectScriptHandler.getBasePath(scriptPath), activeBranch); - return ghContents.stream().anyMatch(ghContent -> ghContent.getName().equals("pom.xml")); - } catch (IOException e) { - return false; + for (GHContent ghContent : ghContents) { + String fileName = ghContent.getName(); + if (StringUtils.equals(fileName, groovyMavenProjectScriptHandler.getBuildScriptName())) { + return groovyMavenProjectScriptHandler.getKey(); + } + + if (StringUtils.equals(fileName, groovyGradleProjectScriptHandler.getBuildScriptName())) { + return groovyGradleProjectScriptHandler.getKey(); + } + } + } catch (IOException ignored) { + noOp(); } + return null; } private FileEntry createGitHubScriptFileEntry(String fullPath) { @@ -230,7 +249,7 @@ private String getCheckoutDirPath(GHRepository ghRepository, GitHubConfig gitHub try { String checkoutScriptPath; URI uri = new URI(getGitHubBaseUrl(gitHubConfig)); - if (proxy(this).isGroovyMavenProject(ghRepository, scriptPath, gitHubConfig.getBranch())) { + if (isGroovyProjectScript(ghRepository, scriptPath, gitHubConfig.getBranch())) { checkoutScriptPath = groovyMavenProjectScriptHandler.getBasePath(scriptPath); } else { checkoutScriptPath = getFullPath(scriptPath); @@ -370,7 +389,7 @@ private SVNURL createCheckoutUrl(GHRepository ghRepository, String checkoutBaseUrl = ghRepository.getSvnUrl(); checkoutBaseUrl += isDefaultBranch ? "/trunk" : "/branches/" + activeBranch; SVNURL checkoutUrl; - if (proxy(this).isGroovyMavenProject(ghRepository, scriptPath, activeBranch)) { + if (isGroovyProjectScript(ghRepository, scriptPath, activeBranch)) { checkoutUrl = parseURIEncoded(checkoutBaseUrl + "/" + groovyMavenProjectScriptHandler.getBasePath(scriptPath)); } else { checkoutUrl = parseURIEncoded(checkoutBaseUrl + "/" + getFullPath(scriptPath)); @@ -429,8 +448,8 @@ public void evictGitHubScriptCache(User user) { noOp(); } - @CacheEvict(value = LOCAL_CACHE_GITHUB_IS_MAVEN_GROOVY, key = "#ghRepository.svnUrl + #scriptPath + #activeBranch") - public void evictGitHubMavenGroovyCache(GHRepository ghRepository, String scriptPath, String activeBranch) { + @CacheEvict(value = LOCAL_CACHE_GITHUB_GROOVY_PROJECT_SCRIPT_TYPE, key = "#ghRepository.svnUrl + #scriptPath + #activeBranch") + public void evictGitHubGroovyProjectScriptTypeCache(GHRepository ghRepository, String scriptPath, String activeBranch) { noOp(); } diff --git a/ngrinder-controller/src/main/java/org/ngrinder/starter/InstallationChecker.java b/ngrinder-controller/src/main/java/org/ngrinder/starter/InstallationChecker.java new file mode 100644 index 0000000000..5d15e2b6b9 --- /dev/null +++ b/ngrinder-controller/src/main/java/org/ngrinder/starter/InstallationChecker.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2012-present NAVER Corp. + * + * This file is part of The nGrinder software distribution. Refer to + * the file LICENSE which is part of The nGrinder distribution for + * licensing details. The nGrinder distribution is available on the + * Internet at https://naver.github.io/ngrinder + * + * 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 org.ngrinder.starter; + +import java.util.List; + +import static java.lang.System.*; +import static org.ngrinder.script.handler.GroovyGradleProjectScriptHandler.GRADLE_HOME_ENV_NAME; +import static org.ngrinder.script.handler.GroovyMavenProjectScriptHandler.MAVEN_HOME_ENV_NAME; +import static oshi.util.ExecutingCommand.runNative; + +/** + * + * Check If specific program is installed. + * + * @since 3.5.3 + * + * */ +public enum InstallationChecker { + + MAVEN(MAVEN_HOME_ENV_NAME, "mvn -version", + "Maven isn't installed, You can't run Maven groovy scripts. Please install Maven and set MAVEN_HOME. "), + GRADLE(GRADLE_HOME_ENV_NAME, "gradle -version", + "Gradle isn't installed, You can't run Gradle groovy scripts. Please install Gradle and set GRADLE_HOME."); + + private static final String CONSOLE_COLOR_YELLOW = "\033[0;33m"; + private static final String CONSOLE_COLOR_RESET = "\033[0m"; + + private final String homePath; + private final String installationCheckingCommand; + private final String warningMessage; + + InstallationChecker(String homeEnvName, String installationCheckingCommand, String warningMessage) { + this.warningMessage = warningMessage; + this.installationCheckingCommand = installationCheckingCommand; + + homePath = getenv(homeEnvName) == null ? "" : getenv(homeEnvName) + "/bin/"; + } + + public static void checkAll() { + for (InstallationChecker installationChecker : InstallationChecker.values()) { + if (!installationChecker.isInstalled()) { + installationChecker.printWarningMessage(); + } + } + } + + private boolean isInstalled() { + List result = runNative(homePath + installationCheckingCommand); + return !result.isEmpty(); + } + + private void printWarningMessage() { + out.print(CONSOLE_COLOR_YELLOW); + out.println("####################################################################################################################"); + out.println("# #"); + out.println("# WARNING: " + warningMessage + " #"); + out.println("# #"); + out.println("####################################################################################################################"); + out.print(CONSOLE_COLOR_RESET); + } + +} diff --git a/ngrinder-controller/src/main/resources/ngrinder_home_template/init.gradle b/ngrinder-controller/src/main/resources/ngrinder_home_template/init.gradle new file mode 100644 index 0000000000..589b6c074e --- /dev/null +++ b/ngrinder-controller/src/main/resources/ngrinder_home_template/init.gradle @@ -0,0 +1,8 @@ +allprojects { + apply plugin: "java" + + task __copyDependencies(type: Copy) { + from configurations.default + into project.hasProperty("outputDirectory") ? outputDirectory : "lib" + } +} diff --git a/ngrinder-controller/src/main/resources/script_template/groovy_gradle/build.gradle b/ngrinder-controller/src/main/resources/script_template/groovy_gradle/build.gradle new file mode 100644 index 0000000000..85840b5a4c --- /dev/null +++ b/ngrinder-controller/src/main/resources/script_template/groovy_gradle/build.gradle @@ -0,0 +1,24 @@ +apply plugin: "java" + +group = "ngrinder" +version = "0.0.1" + +sourceCompatibility = "1.8" +targetCompatibility = "1.8" + +compileJava.options.encoding = "UTF-8" +compileTestJava.options.encoding = "UTF-8" + +repositories { + mavenCentral() + jcenter() +} + +ext { + ngrinder_version = "3.5.2" +} + +dependencies { + compileOnly (group: "org.ngrinder", name: "ngrinder-groovy", version: ngrinder_version) + // implementation (group: "commons-io", name: "commons-io", version: "2.0.1") +} diff --git a/ngrinder-controller/src/main/resources/script_template/groovy_maven/src/main/java/TestRunner.groovy b/ngrinder-controller/src/main/resources/script_template/groovy_gradle/src/main/java/TestRunner.groovy similarity index 100% rename from ngrinder-controller/src/main/resources/script_template/groovy_maven/src/main/java/TestRunner.groovy rename to ngrinder-controller/src/main/resources/script_template/groovy_gradle/src/main/java/TestRunner.groovy diff --git a/ngrinder-controller/src/main/resources/script_template/groovy_maven/src/main/resources/resource1.txt b/ngrinder-controller/src/main/resources/script_template/groovy_gradle/src/main/resources/resource1.txt similarity index 100% rename from ngrinder-controller/src/main/resources/script_template/groovy_maven/src/main/resources/resource1.txt rename to ngrinder-controller/src/main/resources/script_template/groovy_gradle/src/main/resources/resource1.txt diff --git a/ngrinder-controller/src/main/resources/script_template/groovy_maven/pom.xml b/ngrinder-controller/src/main/resources/script_template/groovy_maven/pom.xml deleted file mode 100644 index 746c74842f..0000000000 --- a/ngrinder-controller/src/main/resources/script_template/groovy_maven/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - 4.0.0 - ngrinder - ${name} - 0.0.1 - - - 3.5.2 - 1.8 - 1.8 - UTF-8 - - - - - ngrinder.maven.repo - https://github.com/naver/ngrinder/raw/ngrinder.maven.repo/releases - - - - - org.ngrinder - ngrinder-groovy - ${ngrinder.version} - provided - - - - - - - - - - - - org.apache.maven.plugins - maven-eclipse-plugin - 2.9 - - - - org.eclipse.jdt.groovy.core.groovyNature - - - org.eclipse.m2e.core.maven2Nature - - - - - - -