From c2866fce59102ce1233e5770a3881e3838b08d89 Mon Sep 17 00:00:00 2001 From: Guillermo Calvo Date: Fri, 8 Mar 2024 09:15:30 +0100 Subject: [PATCH 1/2] Delete subproject grails-shell --- grails-shell/README.md | 3 - grails-shell/build.gradle | 66 -- .../groovy/org/grails/cli/GrailsCli.groovy | 737 ----------------- ...sApplicationCompilerAutoConfiguration.java | 189 ----- .../cli/boot/GrailsDependencyVersions.groovy | 113 --- ...GrailsTestCompilerAutoConfiguration.groovy | 66 -- .../org/grails/cli/boot/SpringInvoker.groovy | 101 --- .../cli/gradle/ClasspathBuildAction.groovy | 33 - .../FetchAllTaskSelectorsBuildAction.java | 85 -- .../cli/gradle/GradleAsyncInvoker.groovy | 62 -- .../grails/cli/gradle/GradleInvoker.groovy | 72 -- .../org/grails/cli/gradle/GradleUtil.groovy | 140 ---- .../gradle/cache/CachedGradleOperation.groovy | 97 --- .../ListReadingCachedGradleOperation.groovy | 47 -- .../MapReadingCachedGradleOperation.groovy | 68 -- .../cli/gradle/commands/GradleCommand.groovy | 72 -- .../commands/GradleTaskCommandAdapter.groovy | 77 -- .../gradle/commands/ReadGradleTasks.groovy | 68 -- .../completers/AllClassCompleter.groovy | 34 - .../completers/ClassNameCompleter.groovy | 99 --- .../completers/ClosureCompleter.groovy | 47 -- .../completers/DomainClassCompleter.groovy | 39 - .../EscapingFileNameCompletor.groovy | 46 -- .../completers/RegexCompletor.groovy | 56 -- .../SimpleOrFileNameCompletor.groovy | 58 -- .../completers/SortedAggregateCompleter.java | 133 --- .../completers/StringsCompleter.java | 75 -- .../completers/TestsCompleter.groovy | 41 - .../grails/cli/profile/AbstractProfile.groovy | 522 ------------ .../grails/cli/profile/AbstractStep.groovy | 45 - .../org/grails/cli/profile/Command.groovy | 42 - .../grails/cli/profile/CommandArgument.groovy | 49 -- .../profile/CommandCancellationListener.java | 29 - .../cli/profile/CommandDescription.groovy | 152 ---- .../cli/profile/CommandException.groovy | 27 - .../grails/cli/profile/DefaultFeature.groovy | 98 --- .../grails/cli/profile/ExecutionContext.java | 45 - .../org/grails/cli/profile/Feature.groovy | 70 -- .../cli/profile/FileSystemProfile.groovy | 38 - .../cli/profile/MultiStepCommand.groovy | 57 -- .../org/grails/cli/profile/Profile.java | 183 ---- .../grails/cli/profile/ProfileCommand.groovy | 37 - .../cli/profile/ProfileRepository.groovy | 74 -- .../cli/profile/ProfileRepositoryAware.groovy | 26 - .../org/grails/cli/profile/ProfileUtil.groovy | 32 - .../grails/cli/profile/ProjectCommand.groovy | 25 - .../grails/cli/profile/ProjectContext.java | 62 -- .../cli/profile/ProjectContextAware.groovy | 27 - .../grails/cli/profile/ResourceProfile.groovy | 66 -- .../groovy/org/grails/cli/profile/Step.groovy | 50 -- .../commands/ArgumentCompletingCommand.groovy | 66 -- .../commands/ClosureExecutingCommand.groovy | 50 -- .../profile/commands/CommandCompleter.groovy | 51 -- .../profile/commands/CommandRegistry.groovy | 101 --- .../profile/commands/CreateAppCommand.groovy | 778 ------------------ .../commands/CreatePluginCommand.groovy | 60 -- .../commands/CreateProfileCommand.groovy | 45 - .../commands/DefaultMultiStepCommand.groovy | 111 --- .../cli/profile/commands/HelpCommand.groovy | 151 ---- .../commands/ListProfilesCommand.groovy | 53 -- .../cli/profile/commands/OpenCommand.groovy | 72 -- .../commands/ProfileInfoCommand.groovy | 128 --- .../commands/events/CommandEvents.groovy | 78 -- .../commands/events/EventStorage.groovy | 46 -- .../ApplicationContextCommandFactory.groovy | 52 -- .../ClasspathCommandResourceResolver.groovy | 57 -- .../commands/factory/CommandFactory.groovy | 40 - .../factory/CommandResourceResolver.groovy | 42 - .../FileSystemCommandResourceResolver.groovy | 59 -- .../factory/GroovyScriptCommandFactory.groovy | 88 -- .../ResourceResolvingCommandFactory.groovy | 96 --- .../factory/ServiceCommandFactory.groovy | 40 - .../factory/YamlCommandFactory.groovy | 75 -- .../commands/io/FileSystemInteraction.groovy | 142 ---- .../io/FileSystemInteractionImpl.groovy | 284 ------- .../commands/io/GradleDependency.groovy | 86 -- .../commands/io/ServerInteraction.groovy | 61 -- .../script/GroovyScriptCommand.groovy | 195 ----- .../GroovyScriptCommandTransform.groovy | 138 ---- .../commands/templates/SimpleTemplate.groovy | 18 - .../templates/TemplateException.groovy | 29 - .../templates/TemplateRenderer.groovy | 171 ---- .../templates/TemplateRendererImpl.groovy | 276 ------- .../AbstractJarProfileRepository.groovy | 142 ---- .../GrailsAetherGrapeEngineFactory.groovy | 91 -- .../GrailsRepositoryConfiguration.groovy | 93 --- .../repository/MavenProfileRepository.groovy | 158 ---- .../StaticJarProfileRepository.groovy | 48 -- .../profile/steps/DefaultStepFactory.groovy | 45 - .../cli/profile/steps/ExecuteStep.groovy | 67 -- .../cli/profile/steps/GradleStep.groovy | 106 --- .../grails/cli/profile/steps/MkdirStep.groovy | 62 -- .../cli/profile/steps/RenderStep.groovy | 136 --- .../cli/profile/steps/StepFactory.groovy | 40 - .../cli/profile/steps/StepRegistry.groovy | 58 -- .../support/ArtefactVariableResolver.groovy | 75 -- .../services/org.grails.cli.profile.Command | 10 - ...li.profile.commands.factory.CommandFactory | 4 - .../org.grails.cli.profile.steps.StepFactory | 1 - ...oot.cli.compiler.CompilerAutoConfiguration | 2 - .../src/main/resources/unixStartScript.txt | 167 ---- .../groovy/org/grails/cli/TestTerminal.java | 11 - .../completers/RegexCompletorSpec.groovy | 40 - .../cli/profile/ResourceProfileSpec.groovy | 245 ------ .../CommandScriptTransformSpec.groovy | 63 -- .../commands/CreateAppCommandSpec.groovy | 105 --- .../CommandEventsTraitGeneratedSpec.groovy | 20 - .../repository/MavenRepositorySpec.groovy | 37 - .../cli/profile/steps/StepRegistrySpec.groovy | 31 - .../test/resources/gradle-sample/build.gradle | 5 - .../gradle/wrapper/gradle-wrapper.jar | Bin 51017 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - .../src/test/resources/gradle-sample/gradlew | 164 ---- .../test/resources/gradle-sample/gradlew.bat | 90 -- .../resources/gradle-sample/settings.gradle | 1 - .../gradle-sample/subproj/build.gradle | 3 - .../gradle-sample/subproj2/build.gradle | 3 - .../profiles/web/commands/TestGroovy.groovy | 3 - settings.gradle | 1 - 119 files changed, 10352 deletions(-) delete mode 100644 grails-shell/README.md delete mode 100644 grails-shell/build.gradle delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/GrailsCli.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/boot/GrailsApplicationCompilerAutoConfiguration.java delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/boot/GrailsDependencyVersions.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/boot/GrailsTestCompilerAutoConfiguration.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/boot/SpringInvoker.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/ClasspathBuildAction.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/FetchAllTaskSelectorsBuildAction.java delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/GradleAsyncInvoker.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/GradleInvoker.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/GradleUtil.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/cache/CachedGradleOperation.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/cache/ListReadingCachedGradleOperation.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/cache/MapReadingCachedGradleOperation.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/commands/GradleCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/commands/GradleTaskCommandAdapter.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/gradle/commands/ReadGradleTasks.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/AllClassCompleter.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/ClassNameCompleter.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/ClosureCompleter.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/DomainClassCompleter.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/EscapingFileNameCompletor.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/RegexCompletor.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/SimpleOrFileNameCompletor.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/SortedAggregateCompleter.java delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/StringsCompleter.java delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/interactive/completers/TestsCompleter.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/AbstractProfile.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/AbstractStep.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/Command.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/CommandArgument.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/CommandCancellationListener.java delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/CommandDescription.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/CommandException.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/DefaultFeature.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ExecutionContext.java delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/Feature.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/FileSystemProfile.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/MultiStepCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/Profile.java delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ProfileCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ProfileRepository.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ProfileRepositoryAware.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ProfileUtil.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ProjectCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ProjectContext.java delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ProjectContextAware.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/ResourceProfile.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/Step.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/ArgumentCompletingCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/ClosureExecutingCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/CommandCompleter.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/CommandRegistry.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateAppCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreatePluginCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateProfileCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/DefaultMultiStepCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/HelpCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/ListProfilesCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/OpenCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/ProfileInfoCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/events/CommandEvents.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/events/EventStorage.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ApplicationContextCommandFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ClasspathCommandResourceResolver.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/CommandFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/CommandResourceResolver.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/FileSystemCommandResourceResolver.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/GroovyScriptCommandFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ResourceResolvingCommandFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ServiceCommandFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/YamlCommandFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/FileSystemInteraction.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/FileSystemInteractionImpl.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/GradleDependency.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/ServerInteraction.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/script/GroovyScriptCommand.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/script/GroovyScriptCommandTransform.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/SimpleTemplate.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateException.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateRenderer.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateRendererImpl.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/repository/AbstractJarProfileRepository.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/repository/GrailsAetherGrapeEngineFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/repository/GrailsRepositoryConfiguration.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/repository/MavenProfileRepository.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/repository/StaticJarProfileRepository.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/steps/DefaultStepFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/steps/ExecuteStep.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/steps/GradleStep.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/steps/MkdirStep.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/steps/RenderStep.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/steps/StepFactory.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/steps/StepRegistry.groovy delete mode 100644 grails-shell/src/main/groovy/org/grails/cli/profile/support/ArtefactVariableResolver.groovy delete mode 100644 grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.Command delete mode 100644 grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.commands.factory.CommandFactory delete mode 100644 grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.steps.StepFactory delete mode 100644 grails-shell/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration delete mode 100644 grails-shell/src/main/resources/unixStartScript.txt delete mode 100644 grails-shell/src/test/groovy/org/grails/cli/TestTerminal.java delete mode 100644 grails-shell/src/test/groovy/org/grails/cli/interactive/completers/RegexCompletorSpec.groovy delete mode 100644 grails-shell/src/test/groovy/org/grails/cli/profile/ResourceProfileSpec.groovy delete mode 100644 grails-shell/src/test/groovy/org/grails/cli/profile/commands/CommandScriptTransformSpec.groovy delete mode 100644 grails-shell/src/test/groovy/org/grails/cli/profile/commands/CreateAppCommandSpec.groovy delete mode 100644 grails-shell/src/test/groovy/org/grails/cli/profile/commands/events/CommandEventsTraitGeneratedSpec.groovy delete mode 100644 grails-shell/src/test/groovy/org/grails/cli/profile/repository/MavenRepositorySpec.groovy delete mode 100644 grails-shell/src/test/groovy/org/grails/cli/profile/steps/StepRegistrySpec.groovy delete mode 100644 grails-shell/src/test/resources/gradle-sample/build.gradle delete mode 100644 grails-shell/src/test/resources/gradle-sample/gradle/wrapper/gradle-wrapper.jar delete mode 100644 grails-shell/src/test/resources/gradle-sample/gradle/wrapper/gradle-wrapper.properties delete mode 100755 grails-shell/src/test/resources/gradle-sample/gradlew delete mode 100644 grails-shell/src/test/resources/gradle-sample/gradlew.bat delete mode 100644 grails-shell/src/test/resources/gradle-sample/settings.gradle delete mode 100644 grails-shell/src/test/resources/gradle-sample/subproj/build.gradle delete mode 100644 grails-shell/src/test/resources/gradle-sample/subproj2/build.gradle delete mode 100644 grails-shell/src/test/resources/profiles-repository/profiles/web/commands/TestGroovy.groovy diff --git a/grails-shell/README.md b/grails-shell/README.md deleted file mode 100644 index 4ecb23353d5..00000000000 --- a/grails-shell/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## grails-shell - -This subproject provides code related to the Grails CLI and plugin commands. diff --git a/grails-shell/build.gradle b/grails-shell/build.gradle deleted file mode 100644 index 8092bda6bf9..00000000000 --- a/grails-shell/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin:'application' - -mainClassName = "org.grails.cli.GrailsCli" - -repositories { - mavenCentral() -} - -ext { - gradleToolingApiVersion = '7.3-20210825160000+0000' -} - -dependencies { - api project(":grails-bootstrap") - api project(":grails-gradle-model") - api "org.apache.ant:ant:$antVersion" - api "org.codehaus.groovy:groovy-ant:$groovyVersion" - api "org.codehaus.groovy:groovy-json:$groovyVersion" - api "org.codehaus.groovy:groovy-jmx:$groovyVersion" - api "org.fusesource.jansi:jansi:$jansiVersion" - api "jline:jline:$jlineVersion" - api "org.gradle:gradle-tooling-api:$gradleToolingApiVersion" - - api "org.springframework.boot:spring-boot-cli:$springBootVersion", { - exclude group: "org.codehaus.groovy", module: "groovy" - } - implementation("org.apache.maven:maven-resolver-provider:3.9.6") { - exclude group: "com.google.guava", module: "guava" - } - - implementation("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") - implementation("org.apache.maven.resolver:maven-resolver-impl:1.9.18") - implementation("org.apache.maven.resolver:maven-resolver-transport-file:1.9.18") - implementation("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18") { - exclude group: "org.slf4j", module:"jcl-over-slf4j" - exclude group: "commons-codec", module:"commons-codec" - } - implementation("commons-codec:commons-codec:1.16.0") - - testImplementation "net.sf.expectit:expectit-core:0.9.0" - testImplementation "com.github.jnr:jnr-posix:3.1.18" - - runtimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" - runtimeOnly "org.codehaus.plexus:plexus-component-api:1.0-alpha-33" - -} - -eclipse { - classpath { - file { - whenMerged { classpath -> - classpath.entries.find { entry -> entry.kind == 'src' && entry.path == "src/test/resources" }?.excludes=["profiles-repository/**", "gradle-sample/**"] - } - } - } -} - -apply from: "../gradle/integration-test.gradle" - -integrationTest { - // jline doesn't use jline.terminal system property when TERM is dumb so use different TERM value for tests - // https://github.com/jline/jline2/blob/6a1b6bf/src/main/java/jline/TerminalFactory.java#L54-L57 - environment 'TERM', 'xterm' - // execute in single thread - maxParallelForks = 1 -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/GrailsCli.groovy b/grails-shell/src/main/groovy/org/grails/cli/GrailsCli.groovy deleted file mode 100644 index dfa9874ab2a..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/GrailsCli.groovy +++ /dev/null @@ -1,737 +0,0 @@ -/* - * Copyright 2014 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 - * - * 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.grails.cli - -import grails.build.logging.GrailsConsole -import grails.build.proxy.SystemPropertiesAuthenticator -import grails.config.ConfigMap -import grails.io.support.SystemOutErrCapturer -import grails.io.support.SystemStreamsRedirector -import grails.util.BuildSettings -import grails.util.Environment -import groovy.transform.Canonical -import groovy.transform.CompileStatic -import jline.UnixTerminal -import jline.console.UserInterruptException -import jline.console.completer.ArgumentCompleter -import jline.console.completer.Completer -import jline.internal.NonBlockingInputStream -import org.gradle.tooling.BuildActionExecuter -import org.gradle.tooling.BuildCancelledException -import org.gradle.tooling.ProjectConnection -import org.grails.build.parsing.CommandLine -import org.grails.build.parsing.CommandLineParser -import org.grails.build.parsing.DefaultCommandLine -import org.grails.cli.gradle.ClasspathBuildAction -import org.grails.cli.gradle.GradleAsyncInvoker -import org.grails.cli.gradle.cache.MapReadingCachedGradleOperation -import org.grails.cli.interactive.completers.EscapingFileNameCompletor -import org.grails.cli.interactive.completers.RegexCompletor -import org.grails.cli.interactive.completers.SortedAggregateCompleter -import org.grails.cli.interactive.completers.StringsCompleter -import org.grails.cli.profile.* -import org.grails.cli.profile.commands.CommandCompleter -import org.grails.cli.profile.commands.CommandRegistry -import org.grails.cli.profile.repository.GrailsRepositoryConfiguration -import org.grails.cli.profile.repository.MavenProfileRepository -import org.grails.cli.profile.repository.StaticJarProfileRepository -import org.grails.config.CodeGenConfig -import org.grails.config.NavigableMap -import org.grails.exceptions.ExceptionUtils - -import java.util.concurrent.* - -/** - * Main class for the Grails command line. Handles interactive mode and running Grails commands within the context of a profile - * - * @author Lari Hotari - * @author Graeme Rocher - * - * @since 3.0 - */ -@CompileStatic -class GrailsCli { - static final String ARG_SPLIT_PATTERN = /(? profileRepositories = [MavenProfileRepository.DEFAULT_REPO] - - /** - * Obtains a value from USER_HOME/.grails/settings.yml - * - * @param key the property name to resolve - * @param targetType the expected type of the property value - * @param defaultValue The default value - */ - public static T getSetting(String key, Class targetType = Object.class, T defaultValue = null) { - def value = SETTINGS_MAP.get(key, defaultValue) - if(value == null) { - return null - } - - else if(targetType.isInstance(value)) { - return (T)value - } - else { - try { - return value.asType(targetType) - } catch (Throwable e) { - return null - } - } - } - /** - * Main method for running via the command line - * - * @param args The arguments - */ - public static void main(String[] args) { - - Authenticator.setDefault( getSetting( BuildSettings.AUTHENTICATOR, Authenticator, new SystemPropertiesAuthenticator() ) ) - def proxySelector = getSetting(BuildSettings.PROXY_SELECTOR, ProxySelector) - if(proxySelector != null) { - ProxySelector.setDefault( proxySelector ) - } - - GrailsCli cli=new GrailsCli() - try { - exit(cli.execute(args)) - } - catch(BuildCancelledException e) { - GrailsConsole.instance.addStatus("Build stopped.") - exit(0) - } - catch (Throwable e) { - e = ExceptionUtils.getRootCause(e) - GrailsConsole.instance.error("Error occurred running Grails CLI: $e.message", e) - exit(1) - } - } - - static void exit(int code) { - GrailsConsole.instance.cleanlyExit(code) - } - - static boolean isInteractiveModeActive() { - return interactiveModeActive - } - - static void tiggerAppLoad() { - GrailsCli.tiggerAppLoad = true - } - - private int getBaseUsage() { - System.out.println "Usage: \n\t $USAGE_MESSAGE \n\t $PLUGIN_USAGE_MESSAGE \n\n" - this.execute "list-profiles" - System.out.println "\nType 'grails help' or 'grails -h' for more information." - - return 1 - } - - /** - * Execute the given command - * - * @param args The arguments - * @return The exit status code - */ - public int execute(String... args) { - CommandLine mainCommandLine=cliParser.parse(args) - - if(mainCommandLine.hasOption(CommandLine.VERBOSE_ARGUMENT)) { - System.setProperty("grails.verbose", "true") - System.setProperty("grails.full.stacktrace", "true") - } - if(mainCommandLine.hasOption(CommandLine.STACKTRACE_ARGUMENT)) { - System.setProperty("grails.show.stacktrace", "true") - } - - if(mainCommandLine.hasOption(CommandLine.VERSION_ARGUMENT) || mainCommandLine.hasOption('v')) { - def console = GrailsConsole.instance - console.addStatus("Grails Version: ${GrailsCli.getPackage().implementationVersion}") - console.addStatus("JVM Version: ${System.getProperty('java.version')}") - exit(0) - } - - - - if(mainCommandLine.hasOption(CommandLine.HELP_ARGUMENT) || mainCommandLine.hasOption('h')) { - profileRepository = createMavenProfileRepository() - def cmd = CommandRegistry.getCommand("help", profileRepository) - cmd.handle(createExecutionContext(mainCommandLine)) - exit(0) - } - - if(mainCommandLine.environmentSet) { - System.setProperty(Environment.KEY, mainCommandLine.environment) - Environment.reset() - } - - File grailsAppDir=new File("grails-app") - File applicationGroovy =new File("Application.groovy") - File profileYml =new File("profile.yml") - if(!grailsAppDir.isDirectory() && !applicationGroovy.exists() && !profileYml.exists()) { - profileRepository = createMavenProfileRepository() - if(!mainCommandLine || !mainCommandLine.commandName) { - integrateGradle = false - def console = GrailsConsole.getInstance() - // force resolve of all profiles - profileRepository.getAllProfiles() - def commandNames = CommandRegistry.findCommands(profileRepository).collect() { Command cmd -> cmd.name } - console.reader.addCompleter(new StringsCompleter(commandNames)) - console.reader.addCompleter(new CommandCompleter(CommandRegistry.findCommands(profileRepository))) - profile = [handleCommand: { ExecutionContext context -> - - def cl = context.commandLine - def name = cl.commandName - def cmd = CommandRegistry.getCommand(name, profileRepository) - if(cmd != null) { - return executeCommandWithArgumentValidation(cmd, cl) - } - else { - console.error("Command not found [$name]") - return false - } - } ] as Profile - - startInteractiveMode(console) - return 0 - } - def cmd = CommandRegistry.getCommand(mainCommandLine.commandName, profileRepository) - if(cmd) { - return executeCommandWithArgumentValidation(cmd, mainCommandLine) ? 0 : 1 - } - else { - return getBaseUsage() - } - - } else { - initializeApplication(mainCommandLine) - if(mainCommandLine.commandName) { - return handleCommand(mainCommandLine) ? 0 : 1 - } else { - handleInteractiveMode() - } - } - return 0 - } - - protected boolean executeCommandWithArgumentValidation(Command cmd, CommandLine mainCommandLine) { - def arguments = cmd.description.arguments - def requiredArgs = arguments.count { CommandArgument arg -> arg.required } - if (mainCommandLine.remainingArgs.size() < requiredArgs) { - outputMissingArgumentsMessage cmd - return false - } else { - return cmd.handle(createExecutionContext(mainCommandLine)) - } - } - - protected void initializeApplication(CommandLine mainCommandLine) { - applicationConfig = loadApplicationConfig() - File profileYml = new File("profile.yml") - if (profileYml.exists()) { - // use the profile for profiles - applicationConfig.put(BuildSettings.PROFILE, "profile") - } - - GrailsConsole console = GrailsConsole.instance - console.ansiEnabled = !mainCommandLine.hasOption(CommandLine.NOANSI_ARGUMENT) - console.defaultInputMask = defaultInputMask - if (ansiEnabled != null) { - console.ansiEnabled = ansiEnabled - } - File baseDir = new File(".").canonicalFile - projectContext = new ProjectContextImpl(console, baseDir, applicationConfig) - initializeProfile() - } - - protected MavenProfileRepository createMavenProfileRepository() { - def profileRepos = getSetting(BuildSettings.PROFILE_REPOSITORIES, Map.class, Collections.emptyMap()) - if(!profileRepos.isEmpty()) { - profileRepositories.clear() - for (repoName in profileRepos.keySet()) { - def data = profileRepos.get(repoName) - if(data instanceof Map) { - def uri = data.get("url") - def snapshots = data.get('snapshotsEnabled') - if(uri != null) { - boolean enableSnapshots = snapshots != null ? Boolean.valueOf(snapshots.toString()) : false - GrailsRepositoryConfiguration repositoryConfiguration - final String username = data.get('username') - final String password = data.get('password') - if (username != null && password != null) { - repositoryConfiguration = new GrailsRepositoryConfiguration(repoName.toString(), new URI(uri.toString()), enableSnapshots, username, password) - } else { - repositoryConfiguration = new GrailsRepositoryConfiguration(repoName.toString(), new URI(uri.toString()), enableSnapshots) - } - profileRepositories.add(repositoryConfiguration) - } - } - } - } - return new MavenProfileRepository(profileRepositories) - } - - protected void outputMissingArgumentsMessage(Command cmd) { - def console = GrailsConsole.instance - console.error("Command $cmd.name is missing required arguments:") - for (CommandArgument arg in cmd.description.arguments.findAll { CommandArgument ca -> ca.required }) { - console.log("* $arg.name - $arg.description") - } - } - - ExecutionContext createExecutionContext(CommandLine commandLine) { - new ExecutionContextImpl(commandLine, projectContext) - } - - Boolean handleCommand( CommandLine commandLine ) { - - handleCommand(createExecutionContext(commandLine)) - } - - Boolean handleCommand( ExecutionContext context ) { - def console = GrailsConsole.getInstance() - synchronized(GrailsCli) { - try { - currentExecutionContext = context - if (handleBuiltInCommands(context)) { - return true - } - - def mainCommandLine = context.getCommandLine() - if(mainCommandLine.hasOption(CommandLine.STACKTRACE_ARGUMENT)) { - console.setStacktrace(true); - } else { - console.setStacktrace(false); - } - - if(mainCommandLine.hasOption(CommandLine.VERBOSE_ARGUMENT)) { - System.setProperty("grails.verbose", "true") - System.setProperty("grails.full.stacktrace", "true") - } - else { - System.setProperty("grails.verbose", "false") - System.setProperty("grails.full.stacktrace", "false") - } - if (profile.handleCommand(context)) { - if(tiggerAppLoad) { - console.updateStatus("Initializing application. Please wait...") - try { - initializeApplication(context.commandLine) - setupCompleters() - } finally { - tiggerAppLoad = false - } - } - return true; - } - return false - } - catch(Throwable e) { - console.error("Command [${context.commandLine.commandName}] error: ${e.message}", e) - return false - } finally { - currentExecutionContext = null - } - } - } - - - private void handleInteractiveMode() { - GrailsConsole console = setupCompleters() - startInteractiveMode(console) - } - - protected GrailsConsole setupCompleters() { - System.setProperty(Environment.INTERACTIVE_MODE_ENABLED, "true") - GrailsConsole console = projectContext.console - - def consoleReader = console.reader - consoleReader.setHandleUserInterrupt(true) - def completers = aggregateCompleter.getCompleters() - - console.resetCompleters() - // add bang operator completer - completers.add(new ArgumentCompleter( - new RegexCompletor("!\\w+"), new EscapingFileNameCompletor()) - ) - - completers.addAll((profile.getCompleters(projectContext) ?: []) as Collection) - consoleReader.addCompleter(aggregateCompleter) - return console - } - - protected void startInteractiveMode(GrailsConsole console) { - console.updateStatus("Starting interactive mode...") - ExecutorService commandExecutor = Executors.newFixedThreadPool(1) - try { - interactiveModeLoop(console, commandExecutor) - } finally { - commandExecutor.shutdownNow() - } - } - - private void interactiveModeLoop(GrailsConsole console, ExecutorService commandExecutor) { - NonBlockingInputStream nonBlockingInput = (NonBlockingInputStream)console.reader.getInput() - interactiveModeActive = true - boolean firstRun = true - while(keepRunning) { - try { - if(firstRun) { - console.addStatus("Enter a command name to run. Use TAB for completion:") - firstRun = false - } - String commandLine = console.showPrompt() - if(commandLine==null) { - // CTRL-D was pressed, exit interactive mode - exitInteractiveMode() - } else if (commandLine.trim()) { - if(nonBlockingInput.isNonBlockingEnabled()) { - handleCommandWithCancellationSupport(console, commandLine, commandExecutor, nonBlockingInput) - } else { - handleCommand( cliParser.parseString(commandLine)) - } - } - } catch (BuildCancelledException cancelledException) { - console.updateStatus("Build stopped.") - }catch (UserInterruptException e) { - exitInteractiveMode() - } catch (Throwable e) { - console.error "Caught exception ${e.message}", e - } - } - } - - private Boolean handleCommandWithCancellationSupport(GrailsConsole console, String commandLine, ExecutorService commandExecutor, NonBlockingInputStream nonBlockingInput) { - ExecutionContext executionContext = createExecutionContext( cliParser.parseString(commandLine)) - Future commandFuture = commandExecutor.submit({ handleCommand(executionContext) } as Callable) - def terminal = console.reader.terminal - if (terminal instanceof UnixTerminal) { - ((UnixTerminal) terminal).disableInterruptCharacter() - } - try { - while(!commandFuture.done) { - if(nonBlockingInput.nonBlockingEnabled) { - int peeked = nonBlockingInput.peek(100L) - if(peeked > 0) { - // read peeked character from buffer - nonBlockingInput.read(1L) - if(peeked == KEYPRESS_CTRL_C || peeked == KEYPRESS_ESC) { - executionContext.console.log(' ') - executionContext.console.updateStatus("Stopping build. Please wait...") - executionContext.cancel() - } - } - } - } - } finally { - if (terminal instanceof UnixTerminal) { - ((UnixTerminal) terminal).enableInterruptCharacter() - } - } - if(!commandFuture.isCancelled()) { - try { - return commandFuture.get() - } catch (ExecutionException e) { - throw e.cause - } - } else { - return false - } - } - - private initializeProfile() { - BuildSettings.TARGET_DIR?.mkdirs() - - if(!new File(BuildSettings.BASE_DIR, "profile.yml").exists()) { - populateContextLoader() - } - else { - this.profileRepository = createMavenProfileRepository() - } - - String profileName = applicationConfig.get(BuildSettings.PROFILE) ?: getSetting(BuildSettings.PROFILE, String, DEFAULT_PROFILE_NAME) - this.profile = profileRepository.getProfile(profileName) - - if(profile == null) { - throw new IllegalStateException("No profile found for name [$profileName].") - } - } - - protected void populateContextLoader() { - try { - if(new File(BuildSettings.BASE_DIR, "build.gradle").exists()) { - def dependencyMap = new MapReadingCachedGradleOperation>(projectContext, ".dependencies") { - - @Override - void updateStatusMessage() { - GrailsConsole.instance.updateStatus("Resolving Dependencies. Please wait...") - } - - @Override - List createMapValue(Object value) { - if(value instanceof List) { - return ((List)value).collect() { new URL(it.toString()) } as List - } - else { - return [] - } - } - - - @Override - Map> readFromGradle(ProjectConnection connection) { - def config = applicationConfig - - BuildActionExecuter buildActionExecuter = connection.action(new ClasspathBuildAction()) - buildActionExecuter.standardOutput = System.out - buildActionExecuter.standardError = System.err - buildActionExecuter.withArguments("-Dgrails.profile=${config.navigate("grails", "profile")}") - - def grailsClasspath = buildActionExecuter.run() - if(grailsClasspath.error) { - GrailsConsole.instance.error("${grailsClasspath.error} Type 'gradle dependencies' for more information") - exit 1 - } - return [ - dependencies: grailsClasspath.dependencies, - profiles: grailsClasspath.profileDependencies - ] - } - }.call() - - def urls = (List)dependencyMap.get("dependencies") - try { - // add tools.jar - urls.add(new File("${System.getenv('JAVA_HOME')}/lib/tools.jar").toURI().toURL()) - } catch (Throwable e) { - // ignore - } - def profiles = (List)dependencyMap.get("profiles") - URLClassLoader classLoader = new URLClassLoader(urls as URL[], Thread.currentThread().contextClassLoader) - this.profileRepository = new StaticJarProfileRepository(classLoader, profiles as URL[]) - Thread.currentThread().contextClassLoader = classLoader - } - } catch (Throwable e) { - e = ExceptionUtils.getRootCause(e) - GrailsConsole.instance.error("Error initializing classpath: $e.message", e) - exit(1) - } - } - - - private CodeGenConfig loadApplicationConfig() { - CodeGenConfig config = new CodeGenConfig() - File applicationYml = new File("grails-app/conf/application.yml") - File applicationGroovy = new File("grails-app/conf/application.groovy") - if(applicationYml.exists()) { - config.loadYml(applicationYml) - } - if(applicationGroovy.exists()) { - config.loadGroovy(applicationGroovy) - } - config - } - - private boolean handleBuiltInCommands(ExecutionContext context) { - CommandLine commandLine = context.commandLine - def commandName = commandLine.commandName - - if(commandName && commandName.size()>1 && commandName.startsWith('!')) { - return executeProcess(context, commandLine.rawArguments) - } - else { - switch(commandName) { - case '!': - return bang(context) - case 'exit': - exitInteractiveMode() - return true - break - case 'quit': - exitInteractiveMode() - return true - break - } - } - - return false - } - - protected boolean executeProcess(ExecutionContext context, String[] args) { - def console = context.console - try { - args[0] = args[0].substring(1) - def process = new ProcessBuilder(args).redirectErrorStream(true).start() - console.log process.inputStream.getText('UTF-8') - return true - } catch (e) { - console.error "Error occurred executing process: $e.message" - return false - } - } - - /** - * Removes '\' escape characters from the given string. - */ - private String unescape(String str) { - return str.replace('\\', '') - } - - protected Boolean bang(ExecutionContext context) { - def console = context.console - def history = console.reader.history - - //move one step back to ! - history.previous() - - if (!history.previous()) { - console.error "! not valid. Can not repeat without history" - } - - //another step to previous command - String historicalCommand = history.current() - if (historicalCommand.startsWith("!")) { - console.error "Can not repeat command: $historicalCommand" - } - else { - return handleCommand(cliParser.parseString(historicalCommand)) - } - return false - } - - private void exitInteractiveMode() { - keepRunning = false - try { - GradleAsyncInvoker.POOL.shutdownNow() - } catch (Throwable e) { - // ignore - } - } - - - static class ExecutionContextImpl implements ExecutionContext { - CommandLine commandLine - @Delegate(excludes = ['getConsole', 'getBaseDir']) ProjectContext projectContext - GrailsConsole console = GrailsConsole.getInstance() - - ExecutionContextImpl(CodeGenConfig config) { - this(new DefaultCommandLine(), new ProjectContextImpl(GrailsConsole.instance, new File("."), config)) - } - - ExecutionContextImpl(CommandLine commandLine, ProjectContext projectContext) { - this.commandLine = commandLine - this.projectContext = projectContext - if(projectContext?.console) { - console = projectContext.console - } - } - - private List cancelListeners=[] - - @Override //Fully qualified name to work around Groovy bug - void addCancelledListener(org.grails.cli.profile.CommandCancellationListener listener) { - cancelListeners << listener - } - - @Override - void cancel() { - for(CommandCancellationListener listener : cancelListeners) { - try { - listener.commandCancelled() - } catch (Exception e) { - console.error("Error notifying listener about cancelling command", e) - } - } - } - - @Override - File getBaseDir() { - this.projectContext?.baseDir ?: new File(".") - } - } - - @Canonical - private static class ProjectContextImpl implements ProjectContext { - GrailsConsole console = GrailsConsole.getInstance() - File baseDir - CodeGenConfig grailsConfig - - @Override - public String navigateConfig(String... path) { - grailsConfig.navigate(path) - } - - @Override - ConfigMap getConfig() { - return grailsConfig - } - - @Override - public T navigateConfigForType(Class requiredType, String... path) { - grailsConfig.navigate(requiredType, path) - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsApplicationCompilerAutoConfiguration.java b/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsApplicationCompilerAutoConfiguration.java deleted file mode 100644 index 62349e84a63..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsApplicationCompilerAutoConfiguration.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.boot; - -import grails.util.Environment; -import groovy.lang.Grab; -import groovy.lang.GroovyClassLoader; -import org.codehaus.groovy.ast.AnnotationNode; -import org.codehaus.groovy.ast.ClassHelper; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.Parameter; -import org.codehaus.groovy.ast.expr.ClassExpression; -import org.codehaus.groovy.ast.expr.ConstantExpression; -import org.codehaus.groovy.ast.stmt.ReturnStatement; -import org.codehaus.groovy.classgen.GeneratorContext; -import org.codehaus.groovy.control.CompilationFailedException; -import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.control.customizers.ImportCustomizer; -import org.springframework.boot.cli.compiler.AstUtils; -import org.springframework.boot.cli.compiler.CompilerAutoConfiguration; -import org.springframework.boot.cli.compiler.DependencyCustomizer; -import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration; -import org.springframework.boot.cli.compiler.autoconfigure.SpringMvcCompilerAutoConfiguration; -import org.springframework.boot.cli.compiler.dependencies.Dependency; -import org.springframework.boot.cli.compiler.dependencies.DependencyManagement; -import org.springframework.boot.cli.compiler.grape.DependencyResolutionContext; - -import java.lang.reflect.Modifier; -import java.util.*; - - -/** - * A {@link org.springframework.boot.cli.compiler.CompilerAutoConfiguration} for Grails Micro Service applications - * - * @author Graeme Rocher - * @since 3.0 - */ -public class GrailsApplicationCompilerAutoConfiguration extends CompilerAutoConfiguration { - - public static final String[] DEFAULT_IMPORTS = new String[]{ - "grails.persistence", - "grails.gorm", - "grails.rest", - "grails.artefact", - "grails.web", - "grails.boot.config" }; - public static final String ENABLE_AUTO_CONFIGURATION = "org.springframework.boot.autoconfigure.EnableAutoConfiguration"; - public static final ClassNode ENABLE_AUTO_CONFIGURATION_CLASS_NODE = ClassHelper.make(ENABLE_AUTO_CONFIGURATION); - ClassNode lastMatch = null; - - @Override - public boolean matches(ClassNode classNode) { - boolean matches = AstUtils.hasAtLeastOneAnnotation(classNode, "grails.persistence.Entity", "grails.rest.Resource", "Resource", "grails.artefact.Artefact", "grails.web.Controller"); - if(matches) lastMatch = classNode; - return matches; - } - - - @Override - public void applyDependencies(DependencyCustomizer dependencies) throws CompilationFailedException { - addManagedDependencies(dependencies); - if(lastMatch != null) { - lastMatch.addAnnotation(createGrabAnnotation("org.grails", "grails-dependencies", Environment.class.getPackage().getImplementationVersion(), null, "pom", true)); - lastMatch.addAnnotation(createGrabAnnotation("org.grails", "grails-web-boot", Environment.class.getPackage().getImplementationVersion(), null, null, true)); - } - new SpringMvcCompilerAutoConfiguration().applyDependencies(dependencies); - } - - private void addManagedDependencies(DependencyCustomizer dependencies) { - final List current = dependencies - .getDependencyResolutionContext().getManagedDependencies(); - final DependencyResolutionContext resolutionContext = dependencies.getDependencyResolutionContext(); - resolutionContext.addDependencyManagement(new GrailsDependencies(current)); - resolutionContext.addDependencyManagement(getAdditionalDependencies()); - } - - protected DependencyManagement getAdditionalDependencies() { - return new GrailsDependencyVersions(); - } - - - public static AnnotationNode createGrabAnnotation(String group, String module, - String version, String classifier, String type, boolean transitive) { - AnnotationNode annotationNode = new AnnotationNode(new ClassNode(Grab.class)); - annotationNode.addMember("group", new ConstantExpression(group)); - annotationNode.addMember("module", new ConstantExpression(module)); - annotationNode.addMember("version", new ConstantExpression(version)); - if (classifier != null) { - annotationNode.addMember("classifier", new ConstantExpression(classifier)); - } - if (type != null) { - annotationNode.addMember("type", new ConstantExpression(type)); - } - annotationNode.addMember("transitive", new ConstantExpression(transitive)); - annotationNode.addMember("initClass", new ConstantExpression(false)); - return annotationNode; - } - - - @Override - public void applyImports(ImportCustomizer imports) throws CompilationFailedException { - imports.addStarImports(DEFAULT_IMPORTS); - new SpringMvcCompilerAutoConfiguration().applyImports(imports); - } - - @Override - public void applyToMainClass(GroovyClassLoader loader, GroovyCompilerConfiguration configuration, GeneratorContext generatorContext, SourceUnit source, ClassNode classNode) throws CompilationFailedException { - - // if we arrive here then there is no 'Application' class and we need to add one automatically - ClassNode applicationClassNode = new ClassNode("Application", Modifier.PUBLIC, ClassHelper.make("grails.boot.config.GrailsAutoConfiguration")); - AnnotationNode enableAutoAnnotation = new AnnotationNode(ENABLE_AUTO_CONFIGURATION_CLASS_NODE); - try { - enableAutoAnnotation.addMember("exclude", new ClassExpression( ClassHelper.make("org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration")) ); - } catch (Throwable e) { - // ignore - } - applicationClassNode.addAnnotation(enableAutoAnnotation); - applicationClassNode.setModule(source.getAST()); - applicationClassNode.addMethod("shouldScanDefaultPackage", Modifier.PUBLIC, ClassHelper.Boolean_TYPE, new Parameter[0], null, new ReturnStatement(new ConstantExpression(Boolean.TRUE))); - source.getAST().getClasses().add(0, applicationClassNode); - classNode.addAnnotation(new AnnotationNode(ClassHelper.make("org.grails.boot.internal.EnableAutoConfiguration"))); - } - - class GrailsDependencies implements DependencyManagement { - - private Map groupAndArtifactToDependency = new HashMap(); - - private Map artifactToGroupAndArtifact = new HashMap(); - private List dependencies = new ArrayList(); - - public GrailsDependencies(List dependencies) { - for (org.eclipse.aether.graph.Dependency dependency : dependencies) { - String groupId = dependency.getArtifact().getGroupId(); - String artifactId = dependency.getArtifact().getArtifactId(); - String version = dependency.getArtifact().getVersion(); - - List exclusions = new ArrayList(); - Dependency value = new Dependency(groupId, artifactId, version, exclusions); - this.dependencies.add(value); - groupAndArtifactToDependency.put(groupId + ":" + artifactId, value); - artifactToGroupAndArtifact.put(artifactId, groupId + ":" + artifactId); - } - } - -// @Override -// public Dependency find(String groupId, String artifactId) { -// return groupAndArtifactToDependency.get(groupId + ":" + artifactId); -// } - - - @Override - public List getDependencies() { - return dependencies; - } - - @Override - public String getSpringBootVersion() { - return find("spring-boot").getVersion(); - } - - @Override - public Dependency find(String artifactId) { - String groupAndArtifact = artifactToGroupAndArtifact.get(artifactId); - if (groupAndArtifact==null) { - return null; - } - return groupAndArtifactToDependency.get(groupAndArtifact); - } - -// @Override -// public Iterator iterator() { -// return groupAndArtifactToDependency.values().iterator(); -// } - } - -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsDependencyVersions.groovy b/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsDependencyVersions.groovy deleted file mode 100644 index f0704d4589c..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsDependencyVersions.groovy +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.boot - -import groovy.grape.Grape -import groovy.grape.GrapeEngine -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import groovy.util.slurpersupport.GPathResult -import org.springframework.boot.cli.compiler.dependencies.Dependency -import org.springframework.boot.cli.compiler.dependencies.DependencyManagement - - -/** - * Introduces dependency management based on a published BOM file - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class GrailsDependencyVersions implements DependencyManagement { - - protected Map groupAndArtifactToDependency = [:] - protected Map artifactToGroupAndArtifact = [:] - protected List dependencies = [] - protected Map versionProperties = [:] - - GrailsDependencyVersions() { - this(getDefaultEngine()) - } - - GrailsDependencyVersions(Map bomCoords) { - this(getDefaultEngine(), bomCoords) - } - - GrailsDependencyVersions(GrapeEngine grape) { - this(grape, [group: "org.grails", module: "grails-bom", version: GrailsDependencyVersions.package.implementationVersion, type: "pom"]) - } - - GrailsDependencyVersions(GrapeEngine grape, Map bomCoords) { - def results = grape.resolve(null, bomCoords) - - for(URI u in results) { - def pom = new XmlSlurper().parseText(u.toURL().text) - addDependencyManagement(pom) - } - } - - static GrapeEngine getDefaultEngine() { - def grape = Grape.getInstance() - grape.addResolver([name:"grailsCentral", root:"https://repo.grails.org/grails/core"] as Map) - grape - } - - @CompileDynamic - void addDependencyManagement(GPathResult pom) { - pom.dependencyManagement.dependencies.dependency.each { dep -> - addDependency(dep.groupId.text(), dep.artifactId.text(), dep.version.text()) - } - versionProperties = pom.properties.'*'.collectEntries { [(it.name()): it.text()] } - } - - protected void addDependency(String group, String artifactId, String version) { - def groupAndArtifactId = "$group:$artifactId".toString() - artifactToGroupAndArtifact[artifactId] = groupAndArtifactId - - def dep = new Dependency(group, artifactId, version) - dependencies.add(dep) - groupAndArtifactToDependency[groupAndArtifactId] = dep - } - - Dependency find(String groupId, String artifactId) { - return groupAndArtifactToDependency["$groupId:$artifactId".toString()] - } - - @Override - List getDependencies() { - return dependencies - } - - Map getVersionProperties() { - return versionProperties - } - - @Override - String getSpringBootVersion() { - return find("spring-boot").getVersion() - } - - @Override - Dependency find(String artifactId) { - def groupAndArtifact = artifactToGroupAndArtifact[artifactId] - if(groupAndArtifact) - return groupAndArtifactToDependency[groupAndArtifact] - } - - Iterator iterator() { - return groupAndArtifactToDependency.values().iterator() - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsTestCompilerAutoConfiguration.groovy b/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsTestCompilerAutoConfiguration.groovy deleted file mode 100644 index 794a2184776..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/boot/GrailsTestCompilerAutoConfiguration.groovy +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.boot - -import grails.util.Environment -import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.AnnotationNode -import org.codehaus.groovy.ast.ClassNode -import org.codehaus.groovy.control.CompilationFailedException -import org.codehaus.groovy.control.customizers.ImportCustomizer -import org.springframework.boot.cli.compiler.AstUtils -import org.springframework.boot.cli.compiler.CompilerAutoConfiguration -import org.springframework.boot.cli.compiler.DependencyCustomizer - - -/** - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class GrailsTestCompilerAutoConfiguration extends CompilerAutoConfiguration { - - public static final String[] DEFAULT_IMPORTS = [ - "spock.lang", - "grails.test.mixin", - "grails.test.mixin.integration", - "grails.test.mixin.support", - "grails.artefact" ] as String[] - - ClassNode lastMatch = null - - @Override - boolean matches(ClassNode classNode) { - def matches = AstUtils.subclasses(classNode, "Specification") - if(matches) { - lastMatch = classNode - } - return matches - } - - @Override - void applyImports(ImportCustomizer imports) throws CompilationFailedException { - imports.addStarImports(DEFAULT_IMPORTS); - } - - @Override - void applyDependencies(DependencyCustomizer dependencies) throws CompilationFailedException { - if(lastMatch != null) { - def annotation = GrailsApplicationCompilerAutoConfiguration.createGrabAnnotation("org.grails", "grails-plugin-testing", Environment.class.getPackage().getImplementationVersion(), null, null, true) - lastMatch.addAnnotation(annotation); - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/boot/SpringInvoker.groovy b/grails-shell/src/main/groovy/org/grails/cli/boot/SpringInvoker.groovy deleted file mode 100644 index f6b246e8e69..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/boot/SpringInvoker.groovy +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.boot - -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.springframework.boot.cli.command.CommandFactory -import org.springframework.boot.cli.command.CommandRunner - - -/** - * Allows invocation of Spring commands from command scripts - * - * @author Graeme Rocher - * @since 3.0 - */ -@Singleton(strict = false) -@CompileStatic -class SpringInvoker { - - CommandRunner runner = new CommandRunner("spring"); - - private SpringInvoker() { - addServiceLoaderCommands(runner) - } - - private static void addServiceLoaderCommands(CommandRunner runner) { - ServiceLoader factories = ServiceLoader.load( - CommandFactory.class, Thread.currentThread().contextClassLoader) - factories.each { CommandFactory factory -> - runner.addCommands factory.getCommands() - } - } - - @Override - Object invokeMethod(String name, Object args) { - if(args instanceof Object[]) { - - List argList = [name] - argList.addAll( ((Object[])args).collect() { it.toString() } ) - - def currentThread = Thread.currentThread() - def existing = currentThread.contextClassLoader - try { - currentThread.contextClassLoader = new Slf4jBindingAwareClassLoader() - return runner.runAndHandleErrors(argList as String[]) - } finally { - currentThread.contextClassLoader = existing - } - } - return null - } - - @InheritConstructors - static class Slf4jBindingAwareClassLoader extends URLClassLoader { - @Override - Enumeration getResources(String name) throws IOException { - if("org/slf4j/impl/StaticLoggerBinder.class" == name) { - def resources = super.getResources(name) - def oneRes = (URL)resources.find() { URL url -> !url.toString().contains('slf4j-simple') } - if(oneRes) { - - return new Enumeration() { - URL current = oneRes - @Override - boolean hasMoreElements() { - current != null - } - - @Override - URL nextElement() { - URL i = current - current = null - return i - } - } - } - else { - return resources - } - } - else { - return super.getResources(name) - } - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/ClasspathBuildAction.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/ClasspathBuildAction.groovy deleted file mode 100644 index 7f884ea6d6c..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/ClasspathBuildAction.groovy +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle - -import org.gradle.tooling.BuildAction -import org.gradle.tooling.BuildController -import org.grails.gradle.plugin.model.GrailsClasspath - -/** - * Gets the EclipseProject which helps obtain the classpath necessary - * - * @author Graeme Rocher - * @since 3.0 - */ -class ClasspathBuildAction implements BuildAction, Serializable { - @Override - GrailsClasspath execute(BuildController controller) { - controller.getModel(GrailsClasspath) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/FetchAllTaskSelectorsBuildAction.java b/grails-shell/src/main/groovy/org/grails/cli/gradle/FetchAllTaskSelectorsBuildAction.java deleted file mode 100644 index 1fb440e1828..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/FetchAllTaskSelectorsBuildAction.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle; -import java.io.File; -import java.io.Serializable; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -import org.gradle.tooling.BuildAction; -import org.gradle.tooling.BuildController; -import org.gradle.tooling.model.Task; -import org.gradle.tooling.model.TaskSelector; -import org.gradle.tooling.model.gradle.BasicGradleProject; -import org.gradle.tooling.model.gradle.BuildInvocations; -import org.grails.cli.gradle.FetchAllTaskSelectorsBuildAction.AllTasksModel; - -/** - * A {@link org.gradle.tooling.BuildAction} that calculates all the tasks from the Gradle build - * - * @author Lari Hotari - * @since 3.0 - * - */ -public class FetchAllTaskSelectorsBuildAction implements BuildAction { - private static final long serialVersionUID = 1L; - private final String currentProjectPath; - - public FetchAllTaskSelectorsBuildAction(File currentProjectDir) { - this.currentProjectPath = currentProjectDir.getAbsolutePath(); - } - - public AllTasksModel execute(BuildController controller) { - AllTasksModel model = new AllTasksModel(); - Map> allTaskSelectors = new LinkedHashMap>(); - model.allTaskSelectors = allTaskSelectors; - Map> allTasks = new LinkedHashMap>(); - model.allTasks = allTasks; - Map projectPaths = new HashMap(); - model.projectPaths = projectPaths; - for (BasicGradleProject project: controller.getBuildModel().getProjects()) { - BuildInvocations entryPointsForProject = controller.getModel(project, BuildInvocations.class); - Set selectorNames = new LinkedHashSet(); - for (TaskSelector selector : entryPointsForProject.getTaskSelectors()) { - selectorNames.add(selector.getName()); - } - allTaskSelectors.put(project.getName(), selectorNames); - - Set taskNames = new LinkedHashSet(); - for (Task task : entryPointsForProject.getTasks()) { - taskNames.add(task.getName()); - } - allTasks.put(project.getName(), taskNames); - - projectPaths.put(project.getName(), project.getPath()); - if(project.getProjectDirectory().getAbsolutePath().equals(currentProjectPath)) { - model.currentProject = project.getName(); - } - } - return model; - } - - public static class AllTasksModel implements Serializable { - private static final long serialVersionUID = 1L; - public Map> allTasks; - public Map> allTaskSelectors; - public Map projectPaths; - public String currentProject; - } -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleAsyncInvoker.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleAsyncInvoker.groovy deleted file mode 100644 index 45b05bd39a1..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleAsyncInvoker.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle - -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic - -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors - - - -/** - * @author Graeme Rocher - */ -@CompileStatic -class GradleAsyncInvoker { - GradleInvoker invoker - - public static final ExecutorService POOL = Executors.newFixedThreadPool(4); - - static { - Runtime.addShutdownHook { - try { - Thread.start { - if(!POOL.isTerminated()) { - POOL.shutdownNow() - } - }.join(1000) - } catch (Throwable e) { - // ignore - } - } - } - - GradleAsyncInvoker(GradleInvoker invoker) { - this.invoker = invoker - } - - @Override - @CompileDynamic - Object invokeMethod(String name, Object args) { - POOL.submit { - invoker."$name"(*args) - } - } - - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleInvoker.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleInvoker.groovy deleted file mode 100644 index b5f707819f8..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleInvoker.groovy +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle - -import grails.util.Environment -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import org.gradle.tooling.BuildLauncher -import org.grails.build.parsing.CommandLine -import org.grails.cli.profile.ExecutionContext - -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import java.util.concurrent.FutureTask - - -/** - * Allow dynamic invocation of Gradle tasks - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class GradleInvoker { - - ExecutionContext executionContext - - GradleInvoker(ExecutionContext executionContext) { - this.executionContext = executionContext - } - - @Override - Object invokeMethod(String name, Object args) { - Object[] argArray = (Object[]) args - - - GradleUtil.runBuildWithConsoleOutput(executionContext) { BuildLauncher buildLauncher -> - buildLauncher.forTasks(name.split(' ')) - List arguments = [] - arguments << "-Dgrails.env=${Environment.current.name}".toString() - - - def commandLine = executionContext.commandLine - if(commandLine.hasOption(CommandLine.STACKTRACE_ARGUMENT)) { - arguments << '--stacktrace' - arguments << '-Dgrails.full.stacktrace=true' - } - - arguments.addAll argArray.collect() { it.toString() } - buildLauncher.withArguments( arguments as String[]) - } - } - - GradleAsyncInvoker getAsync() { - return new GradleAsyncInvoker(this) - } - - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleUtil.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleUtil.groovy deleted file mode 100644 index ba4b672bbcc..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/GradleUtil.groovy +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle - -import grails.build.logging.GrailsConsole -import grails.io.support.SystemOutErrCapturer -import grails.io.support.SystemStreamsRedirector -import groovy.transform.CompileStatic -import groovy.transform.stc.ClosureParams -import groovy.transform.stc.FromString -import groovy.transform.stc.SimpleType -import org.gradle.tooling.BuildAction -import org.gradle.tooling.BuildActionExecuter -import org.gradle.tooling.BuildLauncher -import org.gradle.tooling.GradleConnector -import org.gradle.tooling.LongRunningOperation -import org.gradle.tooling.ProjectConnection -import org.gradle.tooling.internal.consumer.DefaultCancellationTokenSource -import org.grails.build.logging.GrailsConsoleErrorPrintStream -import org.grails.build.logging.GrailsConsolePrintStream -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.ProjectContext - -/** - * Utility methods for interacting with Gradle - * - * @since 3.0 - * @author Graeme Rocher - * @author Lari Hotari - */ -@CompileStatic -class GradleUtil { - private static final boolean DEFAULT_SUPPRESS_OUTPUT = true - - public static ProjectConnection openGradleConnection(File baseDir) { - GradleConnector gradleConnector = GradleConnector.newConnector().forProjectDirectory(baseDir) - if (System.getenv("GRAILS_GRADLE_HOME")) { - gradleConnector.useInstallation(new File(System.getenv("GRAILS_GRADLE_HOME"))) - } else { - def userHome = System.getProperty("user.home") - if (userHome) { - File gradleFile = new File(baseDir, "gradle.properties") - if (gradleFile.exists() && gradleFile.canRead()) { - Properties gradleProperties = new Properties() - gradleProperties.load(gradleFile.newInputStream()) - String gradleWrapperVersion = gradleProperties.getProperty("gradleWrapperVersion") - - File sdkManGradle = new File("$userHome/.sdkman/candidates/gradle/$gradleWrapperVersion") - if (sdkManGradle.exists() && sdkManGradle.isDirectory()) { - gradleConnector.useInstallation(sdkManGradle) - } - } - } - } - - gradleConnector.connect() - } - - public static T withProjectConnection(File baseDir, boolean suppressOutput = DEFAULT_SUPPRESS_OUTPUT, - @ClosureParams(value = SimpleType.class, options = "org.gradle.tooling.ProjectConnection") Closure closure) { - ProjectConnection projectConnection = openGradleConnection(baseDir) - try { - if (suppressOutput) { - SystemOutErrCapturer.withNullOutput { - closure(projectConnection) - } - } else { - SystemStreamsRedirector.withOriginalIO { - closure(projectConnection) - } - } - } finally { - projectConnection.close(); - } - } - - public static void runBuildWithConsoleOutput(ExecutionContext context, - @ClosureParams(value = SimpleType.class, options = "org.gradle.tooling.BuildLauncher") Closure buildLauncherCustomizationClosure) { - withProjectConnection(context.getBaseDir(), DEFAULT_SUPPRESS_OUTPUT) { ProjectConnection projectConnection -> - BuildLauncher launcher = projectConnection.newBuild() - setupConsoleOutput(context, launcher) - wireCancellationSupport(context, launcher) - buildLauncherCustomizationClosure.call(launcher) - launcher.run() - } - } - - public static LongRunningOperation setupConsoleOutput(ProjectContext context, LongRunningOperation operation) { - GrailsConsole grailsConsole = context.console - operation.colorOutput = grailsConsole.ansiEnabled - operation.standardOutput = new GrailsConsolePrintStream( grailsConsole.out ) - operation.standardError = new GrailsConsoleErrorPrintStream( grailsConsole.err ) - operation - } - - public static T runBuildActionWithConsoleOutput(ProjectContext context, BuildAction buildAction) { - // workaround for GROOVY-7211, static type checking problem when default parameters are used - runBuildActionWithConsoleOutput(context, buildAction, null) - } - - public static T runBuildActionWithConsoleOutput(ProjectContext context, BuildAction buildAction, - @ClosureParams(value = FromString.class, options = "org.gradle.tooling.BuildActionExecuter") Closure buildActionExecuterCustomizationClosure) { - withProjectConnection(context.getBaseDir(), DEFAULT_SUPPRESS_OUTPUT) { ProjectConnection projectConnection -> - runBuildActionWithConsoleOutput(projectConnection, context, buildAction, buildActionExecuterCustomizationClosure) - } - } - - public static T runBuildActionWithConsoleOutput(ProjectConnection connection, ProjectContext context, BuildAction buildAction) { - // workaround for GROOVY-7211, static type checking problem when default parameters are used - runBuildActionWithConsoleOutput(connection, context, buildAction, null) - } - - public static T runBuildActionWithConsoleOutput(ProjectConnection connection, ProjectContext context, BuildAction buildAction, @ClosureParams(value=FromString.class, options="org.gradle.tooling.BuildActionExecuter") Closure buildActionExecuterCustomizationClosure) { - BuildActionExecuter buildActionExecuter = connection.action(buildAction) - setupConsoleOutput(context, buildActionExecuter) - buildActionExecuterCustomizationClosure?.call(buildActionExecuter) - return buildActionExecuter.run() - } - - public static wireCancellationSupport(ExecutionContext context, BuildLauncher buildLauncher) { - DefaultCancellationTokenSource cancellationTokenSource = new DefaultCancellationTokenSource() - buildLauncher.withCancellationToken(cancellationTokenSource.token()) - context.addCancelledListener({ - cancellationTokenSource.cancel() - }) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/CachedGradleOperation.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/CachedGradleOperation.groovy deleted file mode 100644 index e38f6249a38..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/CachedGradleOperation.groovy +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle.cache - -import grails.util.BuildSettings -import groovy.transform.CompileStatic -import org.gradle.tooling.GradleConnector -import org.gradle.tooling.ProjectConnection -import org.gradle.tooling.internal.consumer.ConnectorServices -import org.gradle.tooling.internal.consumer.DefaultGradleConnector -import org.grails.cli.gradle.GradleUtil -import org.grails.cli.profile.ProjectContext - -import java.util.concurrent.Callable - -/** - * Utility class for performing cached operations that retrieve data from Gradle. Since these operations are expensive we want to cache the data to avoid unnecessarily calling Gradle - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -abstract class CachedGradleOperation implements Callable { - - protected String fileName - protected ProjectContext projectContext - - CachedGradleOperation(ProjectContext projectContext, String fileName) { - this.fileName = fileName - this.projectContext = projectContext - } - - abstract T readFromCached(File f) - - abstract void writeToCache(PrintWriter writer, T data) - - abstract T readFromGradle(ProjectConnection connection) - - @Override - T call() throws Exception { - def depsFile = new File(BuildSettings.TARGET_DIR, fileName) - try { - if(depsFile.exists() && depsFile.lastModified() > new File(projectContext.baseDir, "build.gradle").lastModified()) { - T cached = readFromCached(depsFile) - if(cached) { - return cached - } - - } - } catch (Throwable e) { - throw e - } - - try { - ProjectConnection projectConnection = GradleUtil.openGradleConnection(projectContext.baseDir) - try { - updateStatusMessage() - def data = readFromGradle(projectConnection) - storeData(data) - return data - } finally { - projectConnection.close() - } - } finally { - DefaultGradleConnector.close() - ConnectorServices.reset() - } - } - - void updateStatusMessage() { - // no-op - } - - protected void storeData(T data) { - try { - def depsFile = new File(BuildSettings.TARGET_DIR, fileName) - depsFile.withPrintWriter { PrintWriter writer -> - writeToCache(writer, data) - } - } catch (Throwable e) { - // ignore - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/ListReadingCachedGradleOperation.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/ListReadingCachedGradleOperation.groovy deleted file mode 100644 index dbaf84b2bad..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/ListReadingCachedGradleOperation.groovy +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle.cache - -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.cli.profile.ProjectContext - - -/** - * A {@link CachedGradleOperation} that reads and writes a list of values - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -@InheritConstructors -abstract class ListReadingCachedGradleOperation extends CachedGradleOperation>{ - - @Override - List readFromCached(File f) { - return f.text.split('\n').collect() { String str -> createListEntry(str) } - } - - protected abstract T createListEntry(String str) - - @Override - void writeToCache(PrintWriter writer, List data) { - for (url in data) writer.println(url.toString()) - } - - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/MapReadingCachedGradleOperation.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/MapReadingCachedGradleOperation.groovy deleted file mode 100644 index fa0adaef5cc..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/cache/MapReadingCachedGradleOperation.groovy +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.gradle.cache - -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.gradle.tooling.ProjectConnection -import org.yaml.snakeyaml.DumperOptions -import org.yaml.snakeyaml.LoaderOptions -import org.yaml.snakeyaml.Yaml -import org.yaml.snakeyaml.constructor.SafeConstructor -import org.yaml.snakeyaml.representer.Representer - - -/** - * Cached Gradle operation that reads a Map - * - * @author Graeme Rocher - * @since 3.1 - */ -@InheritConstructors -@CompileStatic -abstract class MapReadingCachedGradleOperation extends CachedGradleOperation> { - @Override - Map readFromCached(File f) { - def map = (Map) f.withReader { BufferedReader r -> - new Yaml(new SafeConstructor(new LoaderOptions())).load(r) - } - Map newMap = [:] - - for(entry in map.entrySet()) { - newMap.put(entry.key, createMapValue(entry.value)) - } - return newMap - } - - abstract V createMapValue(Object value) - - @Override - void writeToCache(PrintWriter writer, Map data) { - def options = new DumperOptions() - options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK) - Map toWrite = data.collectEntries { String key, V val -> - if(val instanceof Iterable) { - return [(key):val.collect() { it.toString() }] - } - else { - return [(key):val.toString()] - } - } - new Yaml(new SafeConstructor(new LoaderOptions()), new Representer(options), options).dump(toWrite, writer) - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/GradleCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/GradleCommand.groovy deleted file mode 100644 index 04a2c0169ab..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/GradleCommand.groovy +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle.commands -import groovy.transform.CompileStatic -import jline.console.completer.Completer -import org.gradle.tooling.BuildLauncher -import org.grails.cli.gradle.GradleUtil -import org.grails.cli.interactive.completers.ClosureCompleter -import org.grails.cli.profile.* -/** - * A command for invoking Gradle commands - * - * @author Graeme Rocher - */ -@CompileStatic -class GradleCommand implements ProjectCommand, Completer, ProjectContextAware { - public static final String GRADLE = "gradle" - - final String name = GRADLE - final CommandDescription description = new CommandDescription(name, "Allows running of Gradle tasks", "gradle [task name]") - ProjectContext projectContext - - private ReadGradleTasks readTasks - private Completer completer - - void setProjectContext(ProjectContext projectContext) { - this.projectContext = projectContext - initializeCompleter() - } - - @Override - boolean handle(ExecutionContext context) { - GradleUtil.runBuildWithConsoleOutput(context) { BuildLauncher buildLauncher -> - def args = context.commandLine.remainingArgsString?.trim() - if(args) { - buildLauncher.withArguments(args) - } - } - return true - } - - @Override - int complete(String buffer, int cursor, List candidates) { - initializeCompleter() - - if(completer) - return completer.complete(buffer, cursor, candidates) - else - return cursor - } - - private void initializeCompleter() { - if (completer == null && projectContext) { - readTasks = new ReadGradleTasks(projectContext) - completer = new ClosureCompleter((Closure>) { readTasks.call() }) - } - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/GradleTaskCommandAdapter.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/GradleTaskCommandAdapter.groovy deleted file mode 100644 index c50ff2a2e1a..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/GradleTaskCommandAdapter.groovy +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle.commands - -import grails.util.Described -import grails.util.GrailsNameUtils -import grails.util.Named -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import org.grails.cli.gradle.GradleInvoker -import org.grails.cli.profile.CommandDescription -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileCommand - -/** - * Adapts a {@link Named} command into a Gradle task execution - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class GradleTaskCommandAdapter implements ProfileCommand { - - Profile profile - final Named adapted - - GradleTaskCommandAdapter(Profile profile, Named adapted) { - this.profile = profile - this.adapted = adapted - } - - @Override - CommandDescription getDescription() { - String description - if(adapted instanceof Described) { - description = ((Described)adapted).description - } - else { - description = "" - } - return new CommandDescription(adapted.name, description) - } - - @Override - @CompileDynamic - boolean handle(ExecutionContext executionContext) { - GradleInvoker invoker = new GradleInvoker(executionContext) - - def commandLine = executionContext.commandLine - if (commandLine.remainingArgs || commandLine.undeclaredOptions) { - invoker."${GrailsNameUtils.getPropertyNameForLowerCaseHyphenSeparatedName(adapted.name)}"("-Pargs=${commandLine.remainingArgsWithOptionsString}") - } else { - invoker."${GrailsNameUtils.getPropertyNameForLowerCaseHyphenSeparatedName(adapted.name)}"() - } - - return true - } - - @Override - String getName() { - return adapted.name - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/ReadGradleTasks.groovy b/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/ReadGradleTasks.groovy deleted file mode 100644 index c9d2778e6bf..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/gradle/commands/ReadGradleTasks.groovy +++ /dev/null @@ -1,68 +0,0 @@ - -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.gradle.commands - -import grails.io.support.SystemOutErrCapturer -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.gradle.tooling.ProjectConnection -import org.grails.cli.gradle.FetchAllTaskSelectorsBuildAction -import org.grails.cli.gradle.cache.ListReadingCachedGradleOperation -import org.grails.cli.profile.ProjectContext - -/** - * @author Graeme Rocher - */ -@CompileStatic -class ReadGradleTasks extends ListReadingCachedGradleOperation { - - private static final Closure taskNameFormatter = { String projectPath, String taskName -> - if(projectPath == ':') { - ":$taskName".toString() - } else { - "$projectPath:$taskName".toString() - } - } - - ReadGradleTasks(ProjectContext projectContext) { - super(projectContext, ".gradle-tasks") - } - - @Override - protected String createListEntry(String str) { str } - - @Override - List readFromGradle(ProjectConnection connection) { - SystemOutErrCapturer.withNullOutput { - FetchAllTaskSelectorsBuildAction.AllTasksModel allTasksModel = (FetchAllTaskSelectorsBuildAction.AllTasksModel)connection.action(new FetchAllTaskSelectorsBuildAction(projectContext.getBaseDir())).run() - Collection allTaskSelectors=[] - - if (allTasksModel.currentProject) { - allTaskSelectors.addAll(allTasksModel.allTaskSelectors.get(allTasksModel.currentProject)) - } - - allTasksModel.projectPaths.each { String projectName, String projectPath -> - allTasksModel.allTasks.get(projectName).each { String taskName -> - allTaskSelectors.add(taskNameFormatter(projectPath, taskName)) - } - } - - allTaskSelectors.unique().toList() - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/AllClassCompleter.groovy b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/AllClassCompleter.groovy deleted file mode 100644 index e4d19394245..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/AllClassCompleter.groovy +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.interactive.completers - -import grails.util.BuildSettings - - - -/** - * A completer that completes all classes in the project - * - * @author Graeme Rocher - * @since 3.0 - */ -class AllClassCompleter extends ClassNameCompleter { - AllClassCompleter() { - super(new File(BuildSettings.BASE_DIR, "grails-app") - ?.listFiles() - ?.findAll() { File f -> f.isDirectory() && !f.isHidden() && !f.name.startsWith('.') } as File[]) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/ClassNameCompleter.groovy b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/ClassNameCompleter.groovy deleted file mode 100644 index e599e44cde2..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/ClassNameCompleter.groovy +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.interactive.completers - -import groovy.transform.CompileStatic -import org.grails.io.support.PathMatchingResourcePatternResolver -import org.grails.io.support.Resource - -import java.util.concurrent.ConcurrentLinkedQueue -import java.util.concurrent.ConcurrentSkipListSet - - -/** - * A completer that completes class names - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class ClassNameCompleter extends StringsCompleter { - - private static Map> RESOURCE_SCAN_CACHE = [:] - private static Collection allCompeters = new ConcurrentLinkedQueue<>() - PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver() - - private File[] baseDirs - - ClassNameCompleter(File baseDir) { - initialize(baseDir) - } - - ClassNameCompleter(File... baseDirs) { - initialize(baseDirs) - } - - static void refreshAll() { - Thread.start { - RESOURCE_SCAN_CACHE.clear() - Collection competers = new ArrayList<>(allCompeters) - for (ClassNameCompleter completer : competers) { - completer.refresh() - } - } - } - - private void refresh() { - if(!baseDirs) return - initialize(baseDirs) - } - - private void initialize(File... baseDirs) { - try { - if(!baseDirs) return - this.baseDirs = baseDirs - if(!allCompeters.contains(this)) - allCompeters << this - SortedSet allStrings = new ConcurrentSkipListSet<>() - for(File baseDir in baseDirs) { - def pattern = "file:${baseDir}/**/*.groovy".toString() - SortedSet strings = RESOURCE_SCAN_CACHE[pattern] - if(strings == null) { - strings = new TreeSet<>() - RESOURCE_SCAN_CACHE[pattern] = strings - def resources = resourcePatternResolver.getResources(pattern) - for (res in resources) { - if(isValidResource(res)) { - def path = res.file.canonicalPath - def basePath = baseDir.canonicalPath - path = (path - basePath)[1..-8] - path = path.replace(File.separatorChar, '.' as char) - strings << path - } - } - } - allStrings.addAll(strings) - } - setStrings(allStrings) - } catch (Throwable e) { - // ignore - } - } - - boolean isValidResource(Resource resource) { - true - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/ClosureCompleter.groovy b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/ClosureCompleter.groovy deleted file mode 100644 index f2e8dfcad26..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/ClosureCompleter.groovy +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.interactive.completers - -import groovy.transform.CompileStatic -import jline.console.completer.Completer - - - -/** - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class ClosureCompleter implements Completer { - private Closure> closure - private Completer completer - - public ClosureCompleter(Closure> closure) { - this.closure = closure - } - - Completer getCompleter() { - if(completer == null) { - completer = new jline.console.completer.StringsCompleter(closure.call()) - } - completer - } - - @Override - public int complete(String buffer, int cursor, List candidates) { - getCompleter().complete(buffer, cursor, candidates) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/DomainClassCompleter.groovy b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/DomainClassCompleter.groovy deleted file mode 100644 index 2588bcacc12..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/DomainClassCompleter.groovy +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.interactive.completers - -import grails.util.BuildSettings -import groovy.transform.CompileStatic -import org.grails.io.support.GrailsResourceUtils -import org.grails.io.support.Resource - -/** - * A completer for domain classes - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class DomainClassCompleter extends ClassNameCompleter { - DomainClassCompleter() { - super(new File(BuildSettings.BASE_DIR, "grails-app/domain")) - } - - @Override - boolean isValidResource(Resource resource) { - GrailsResourceUtils.isDomainClass(resource.getURL()) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/EscapingFileNameCompletor.groovy b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/EscapingFileNameCompletor.groovy deleted file mode 100644 index 398be115569..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/EscapingFileNameCompletor.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2011 SpringSource. - * - * 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.grails.cli.interactive.completers - -import jline.console.completer.FileNameCompleter - - -/** - * JLine Completor that does file path matching like FileNameCompletor, - * but in addition it escapes whitespace in completions with the '\' - * character. - * - * @author Peter Ledbrook - * @since 2.0 - */ -class EscapingFileNameCompletor extends FileNameCompleter { - /** - *

Gets FileNameCompletor to create a list of candidates and then - * inserts '\' before any whitespace characters in each of the candidates. - * If a candidate ends in a whitespace character, then that is not - * escaped.

- */ - int complete(String buffer, int cursor, List candidates) { - int retval = super.complete(buffer, cursor, candidates) - - int count = candidates.size() - for (int i = 0; i < count; i++) { - candidates[i] = candidates[i].replaceAll(/(\s)(?!$)/, '\\\\$1') - } - - return retval - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/RegexCompletor.groovy b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/RegexCompletor.groovy deleted file mode 100644 index 1dc06e3f8cf..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/RegexCompletor.groovy +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011 SpringSource - * - * 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.grails.cli.interactive.completers - -import jline.console.completer.Completer - -import java.util.regex.Pattern - -/** - * JLine Completor that accepts a string if it matches a given regular - * expression pattern. - * - * @author Peter Ledbrook - * @since 2.0 - */ -class RegexCompletor implements Completer { - Pattern pattern - - RegexCompletor(String pattern) { - this(Pattern.compile(pattern)) - } - - RegexCompletor(Pattern pattern) { - this.pattern = pattern - } - - /** - *

Check whether the whole buffer matches the configured pattern. - * If it does, the buffer is added to the candidates list - * (which indicates acceptance of the buffer string) and returns 0, - * i.e. the start of the buffer. This mimics the behaviour of SimpleCompletor. - *

- *

If the buffer doesn't match the configured pattern, this returns - * -1 and the candidates list is left empty.

- */ - int complete(String buffer, int cursor, List candidates) { - if (buffer ==~ pattern) { - candidates << buffer - return 0 - } - else return -1 - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/SimpleOrFileNameCompletor.groovy b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/SimpleOrFileNameCompletor.groovy deleted file mode 100644 index 252ccdb7840..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/SimpleOrFileNameCompletor.groovy +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011 SpringSource - * - * 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.grails.cli.interactive.completers - -import jline.console.completer.Completer -import jline.console.completer.StringsCompleter - - -/** - * JLine Completor that mixes a fixed set of options with file path matches. - * Fixed options that match will appear first, followed by file path matches. - * - * @author Peter Ledbrook - * @since 2.0 - */ -class SimpleOrFileNameCompletor implements Completer { - private simpleCompletor - private fileNameCompletor - - SimpleOrFileNameCompletor(List fixedOptions) { - this(fixedOptions as String[]) - } - - SimpleOrFileNameCompletor(String[] fixedOptions) { - simpleCompletor = new StringsCompleter(fixedOptions) - fileNameCompletor = new EscapingFileNameCompletor() - } - - int complete(String buffer, int cursor, List candidates) { - // Try the simple completor first... - def retval = simpleCompletor.complete(buffer, cursor, candidates) - - // ...and then the file path completor. By using the given candidate - // list with both completors we aggregate the results automatically. - def fileRetval = fileNameCompletor.complete(buffer, cursor, candidates) - - // If the simple completor has matched, we return its value, otherwise - // we return whatever the file path matcher returned. This ensures that - // both simple completor and file path completor candidates appear - // correctly in the command prompt. If neither competors have matches, - // we of course return -1. - if (retval == -1) retval = fileRetval - return candidates ? retval : -1 - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/SortedAggregateCompleter.java b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/SortedAggregateCompleter.java deleted file mode 100644 index 8d8018bd5d9..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/SortedAggregateCompleter.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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 - * - * 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.grails.cli.interactive.completers; - -import jline.console.completer.Completer; - -import java.util.*; - -import static jline.internal.Preconditions.checkNotNull; - -/** - * Copied from jline AggregateCompleter - * - * sorts aggregated completions - * - */ -public class SortedAggregateCompleter - implements Completer -{ - private final List completers = new ArrayList(); - - public SortedAggregateCompleter() { - // empty - } - - /** - * Construct an AggregateCompleter with the given collection of completers. - * The completers will be used in the iteration order of the collection. - * - * @param completers the collection of completers - */ - public SortedAggregateCompleter(final Collection completers) { - checkNotNull(completers); - this.completers.addAll(completers); - } - - /** - * Construct an AggregateCompleter with the given completers. - * The completers will be used in the order given. - * - * @param completers the completers - */ - public SortedAggregateCompleter(final Completer... completers) { - this(Arrays.asList(completers)); - } - - /** - * Retrieve the collection of completers currently being aggregated. - * - * @return the aggregated completers - */ - public Collection getCompleters() { - return completers; - } - - /** - * Perform a completion operation across all aggregated completers. - * - * @see Completer#complete(String, int, java.util.List) - * @return the highest completion return value from all completers - */ - public int complete(final String buffer, final int cursor, final List candidates) { - // buffer could be null - checkNotNull(candidates); - - List completions = new ArrayList(completers.size()); - - // Run each completer, saving its completion results - int max = -1; - for (Completer completer : completers) { - Completion completion = new Completion(candidates); - completion.complete(completer, buffer, cursor); - - // Compute the max cursor position - max = Math.max(max, completion.cursor); - - completions.add(completion); - } - - SortedSet allCandidates = new TreeSet<>(); - - // Append candidates from completions which have the same cursor position as max - for (Completion completion : completions) { - if (completion.cursor == max) { - allCandidates.addAll(completion.candidates); - } - } - - candidates.addAll(allCandidates); - - return max; - } - - /** - * @return a string representing the aggregated completers - */ - @Override - public String toString() { - return getClass().getSimpleName() + "{" + - "completers=" + completers + - '}'; - } - - private class Completion - { - public final List candidates; - - public int cursor; - - public Completion(final List candidates) { - checkNotNull(candidates); - this.candidates = new LinkedList(candidates); - } - - public void complete(final Completer completer, final String buffer, final int cursor) { - checkNotNull(completer); - this.cursor = completer.complete(buffer, cursor, candidates); - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/StringsCompleter.java b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/StringsCompleter.java deleted file mode 100644 index 16d00d811e9..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/StringsCompleter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2012 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 - * - * 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.grails.cli.interactive.completers; - -import jline.console.completer.Completer; - -import java.util.*; - -import static jline.internal.Preconditions.checkNotNull; - -/** - * A completer that completes based on a collection of Strings - * - * @author Graeme Rocher - * @since 3.0 - */ -public class StringsCompleter - implements Completer -{ - private SortedSet strings = new TreeSet(); - - public StringsCompleter() { - // empty - } - - public StringsCompleter(final Collection strings) { - checkNotNull(strings); - getStrings().addAll(strings); - } - - public StringsCompleter(final String... strings) { - this(Arrays.asList(strings)); - } - - public SortedSet getStrings() { - return strings; - } - - - public void setStrings(SortedSet strings) { - this.strings = strings; - } - - public int complete(final String buffer, final int cursor, final List candidates) { - // buffer could be null - checkNotNull(candidates); - - if (buffer == null) { - candidates.addAll(getStrings()); - } - else { - for (String match : getStrings().tailSet(buffer)) { - if (!match.startsWith(buffer)) { - break; - } - - candidates.add(match); - } - } - - return candidates.isEmpty() ? -1 : 0; - } -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/TestsCompleter.groovy b/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/TestsCompleter.groovy deleted file mode 100644 index 4c3b3a9c229..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/interactive/completers/TestsCompleter.groovy +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.interactive.completers - -import grails.util.BuildSettings -import groovy.transform.CompileStatic -import org.grails.io.support.Resource - - - -/** - * A completer that completes the names of the tests in the project - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class TestsCompleter extends ClassNameCompleter { - TestsCompleter() { - super(new File(BuildSettings.BASE_DIR, "src/test/groovy"), new File(BuildSettings.BASE_DIR, "src/integration-test/groovy")) - } - - @Override - boolean isValidResource(Resource resource) { - def fn = resource.filename - fn.endsWith('Spec.groovy') || fn.endsWith('Tests.groovy') - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/AbstractProfile.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/AbstractProfile.groovy deleted file mode 100644 index 9b87bdc4dce..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/AbstractProfile.groovy +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile - -import grails.io.IOUtils -import grails.util.BuildSettings -import grails.util.CosineSimilarity -import groovy.transform.CompileStatic -import groovy.transform.ToString -import jline.console.completer.ArgumentCompleter -import jline.console.completer.Completer -import org.eclipse.aether.artifact.DefaultArtifact -import org.eclipse.aether.graph.Dependency -import org.eclipse.aether.graph.Exclusion -import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector -import org.grails.build.parsing.ScriptNameResolver -import org.grails.cli.interactive.completers.StringsCompleter -import org.grails.cli.profile.commands.CommandRegistry -import org.grails.cli.profile.commands.DefaultMultiStepCommand -import org.grails.cli.profile.commands.script.GroovyScriptCommand -import org.grails.config.NavigableMap -import org.grails.io.support.Resource -import org.yaml.snakeyaml.LoaderOptions -import org.yaml.snakeyaml.Yaml -import org.yaml.snakeyaml.constructor.SafeConstructor - -import static org.grails.cli.profile.ProfileUtil.createDependency - -/** - * Abstract implementation of the profile class - * - * @author Graeme Rocher - * @since 3.1 - */ -@CompileStatic -@ToString(includes = ['name']) -abstract class AbstractProfile implements Profile { - protected final Resource profileDir - protected String name - protected List parentProfiles - protected Map commandsByName - protected NavigableMap navigableConfig - protected ProfileRepository profileRepository - protected List dependencies = [] - protected List repositories = [] - protected List parentNames = [] - protected List buildRepositories = [] - protected List buildPlugins = [] - protected List buildExcludes = [] - protected List skeletonExcludes = [] - protected List binaryExtensions = [] - protected List executablePatterns = [] - protected final List internalCommands = [] - protected List buildMerge = null - protected List features = [] - protected Set defaultFeaturesNames = [] - protected Set requiredFeatureNames = [] - protected String parentTargetFolder - protected final ClassLoader classLoader - protected ExclusionDependencySelector exclusionDependencySelector = new ExclusionDependencySelector() - protected String description = ""; - protected String instructions = ""; - protected String version = BuildSettings.package.implementationVersion - - AbstractProfile(Resource profileDir) { - this(profileDir, AbstractProfile.getClassLoader()) - } - - AbstractProfile(Resource profileDir, ClassLoader classLoader) { - this.classLoader = classLoader - this.profileDir = profileDir - - - def url = profileDir.getURL() - def jarFile = IOUtils.findJarFile(url) - def pattern = ~/.+-(\d.+)\.jar/ - - - def path - if(jarFile != null) { - path = jarFile.name - } - else if(url != null){ - def p = url.path - path = p.substring(0, p.indexOf('.jar') + 4) - } - if(path) { - def matcher = pattern.matcher(path) - if(matcher.matches()) { - this.version = matcher.group(1) - } - } - } - - String getVersion() { - return version - } - - protected void initialize() { - def profileYml = profileDir.createRelative("profile.yml") - Map profileConfig = new Yaml(new SafeConstructor(new LoaderOptions())).> load(profileYml.getInputStream()) - - name = profileConfig.get("name")?.toString() - description = profileConfig.get("description")?.toString() ?: '' - instructions = profileConfig.get("instructions")?.toString() ?: '' - - def parents = profileConfig.get("extends") - if(parents) { - parentNames = parents.toString().split(',').collect() { String name -> name.trim() } - } - if(this.name == null) { - throw new IllegalStateException("Profile name not set. Profile for path ${profileDir.URL} is invalid") - } - def map = new NavigableMap() - map.merge(profileConfig) - navigableConfig = map - def commandsByName = profileConfig.get("commands") - if(commandsByName instanceof Map) { - def commandsMap = (Map) commandsByName - for(clsName in commandsMap.keySet()) { - def fileName = commandsMap[clsName].toString() - if(fileName.endsWith(".groovy")) { - GroovyScriptCommand cmd = (GroovyScriptCommand)classLoader.loadClass(clsName.toString()).newInstance() - cmd.profile = this - cmd.profileRepository = profileRepository - internalCommands.add cmd - } - else if(fileName.endsWith('.yml')) { - def yamlCommand = profileDir.createRelative("commands/$fileName") - if(yamlCommand.exists()) { - Map data = new Yaml(new SafeConstructor(new LoaderOptions())).load(yamlCommand.getInputStream()) - Command cmd = new DefaultMultiStepCommand(clsName.toString(), this, data) - Object minArguments = data?.minArguments - cmd.minArguments = minArguments instanceof Integer ? (Integer)minArguments : 1 - internalCommands.add cmd - } - - } - } - } - - def featuresConfig = profileConfig.get("features") - if(featuresConfig instanceof Map) { - Map featureMap = (Map) featuresConfig - def featureList = (List) featureMap.get("provided") ?: Collections.emptyList() - def defaultFeatures = (List) featureMap.get("defaults") ?: Collections.emptyList() - def requiredFeatures = (List) featureMap.get("required") ?: Collections.emptyList() - for (fn in featureList) { - def featureData = profileDir.createRelative("features/${fn}/feature.yml") - if(featureData.exists()) { - def f = new DefaultFeature(this, fn.toString(), profileDir.createRelative("features/$fn/")) - features.add f - } - } - - defaultFeaturesNames.addAll((List) defaultFeatures) - requiredFeatureNames.addAll((List) requiredFeatures) - } - - - - def dependenciesConfig = profileConfig.get("dependencies") - - if (dependenciesConfig instanceof List) { - List exclusions =[] - for (entry in dependenciesConfig) { - if (entry instanceof Map) { - def scope = (String) entry.scope - String coords = (String) entry.coords - if (scope == 'excludes') { - def artifact = new DefaultArtifact(coords) - exclusions.add new Exclusion(artifact.groupId ?: null, artifact.artifactId ?: null, artifact.classifier ?: null, artifact.extension ?: null) - } else { - Dependency dependency = createDependency(coords, scope, entry) - dependencies.add(dependency) - } - } - exclusionDependencySelector = new ExclusionDependencySelector(exclusions) - } - } - - this.repositories = (List)navigableConfig.get("repositories", []) - - this.buildRepositories = (List)navigableConfig.get("build.repositories", []) - this.buildPlugins = (List)navigableConfig.get("build.plugins", []) - this.buildExcludes = (List)navigableConfig.get("build.excludes", []) - this.buildMerge = (List)navigableConfig.get("build.merge", null) - this.parentTargetFolder = (String)navigableConfig.get("skeleton.parent.target", null) - this.skeletonExcludes = (List)navigableConfig.get("skeleton.excludes", []) - this.binaryExtensions = (List)navigableConfig.get("skeleton.binaryExtensions", []) - this.executablePatterns = (List)navigableConfig.get("skeleton.executable", []) - } - - String getDescription() { - description - } - - String getInstructions() { - instructions - } - - Set getBinaryExtensions() { - Set calculatedBinaryExtensions = [] - def parents = getExtends() - for(profile in parents) { - calculatedBinaryExtensions.addAll(profile.binaryExtensions) - } - calculatedBinaryExtensions.addAll(binaryExtensions) - return calculatedBinaryExtensions - } - - Set getExecutablePatterns() { - Set calculatedExecutablePatterns = [] - def parents = getExtends() - for(profile in parents) { - calculatedExecutablePatterns.addAll(profile.executablePatterns) - } - calculatedExecutablePatterns.addAll(executablePatterns) - return calculatedExecutablePatterns - } - - @Override - Iterable getDefaultFeatures() { - getFeatures().findAll() { Feature f -> defaultFeaturesNames.contains(f.name) } - } - - @Override - Iterable getRequiredFeatures() { - def requiredFeatureInstances = getFeatures().findAll() { Feature f -> requiredFeatureNames.contains(f.name) } - if(requiredFeatureInstances.size() != requiredFeatureNames.size()) { - throw new IllegalStateException("One or more required features were not found on the classpath. Required features: $requiredFeatureNames") - } - return requiredFeatureInstances - } - - @Override - Iterable getFeatures() { - Set calculatedFeatures = [] - calculatedFeatures.addAll(features) - def parents = getExtends() - for(profile in parents) { - calculatedFeatures.addAll profile.features - } - return calculatedFeatures - } - - @Override - List getBuildMergeProfileNames() { - if(buildMerge != null) { - return this.buildMerge - } - else { - List mergeNames = [] - for(parent in getExtends()) { - mergeNames.add(parent.name) - } - mergeNames.add(name) - return mergeNames - } - } - - @Override - List getBuildRepositories() { - List calculatedRepositories = [] - def parents = getExtends() - for(profile in parents) { - calculatedRepositories.addAll(profile.buildRepositories) - } - calculatedRepositories.addAll(buildRepositories) - return calculatedRepositories - } - - @Override - List getBuildPlugins() { - List calculatedPlugins = [] - def parents = getExtends() - for(profile in parents) { - def dependencies = profile.buildPlugins - for(dep in dependencies) { - if(!buildExcludes.contains(dep)) - calculatedPlugins.add(dep) - } - } - calculatedPlugins.addAll(buildPlugins) - return calculatedPlugins - } - - @Override - List getRepositories() { - List calculatedRepositories = [] - def parents = getExtends() - for(profile in parents) { - calculatedRepositories.addAll(profile.repositories) - } - calculatedRepositories.addAll(repositories) - return calculatedRepositories - } - - List getDependencies() { - List calculatedDependencies = [] - def parents = getExtends() - for(profile in parents) { - def dependencies = profile.dependencies - for(dep in dependencies) { - if(exclusionDependencySelector.selectDependency(dep)) { - calculatedDependencies.add(dep) - } - } - } - calculatedDependencies.addAll(dependencies) - return calculatedDependencies - } - - ProfileRepository getProfileRepository() { - return profileRepository - } - - void setProfileRepository(ProfileRepository profileRepository) { - this.profileRepository = profileRepository - } - - Resource getProfileDir() { - return profileDir - } - - - @Override - NavigableMap getConfiguration() { - navigableConfig - } - - @Override - Resource getTemplate(String path) { - return profileDir.createRelative("templates/$path") - } - - @Override - public Iterable getExtends() { - return parentNames.collect() { String name -> - def parent = profileRepository.getProfile(name, true) - if(parent == null) { - throw new IllegalStateException("Profile [$name] declares an invalid dependency on parent profile [$name]") - } - return parent - } - } - - @Override - public Iterable getCompleters(ProjectContext context) { - def commands = getCommands(context) - - Collection completers = [] - - for(Command cmd in commands) { - def description = cmd.description - - def commandNameCompleter = new StringsCompleter(cmd.name) - if(cmd instanceof Completer) { - completers << new ArgumentCompleter(commandNameCompleter, (Completer)cmd) - }else { - if(description.completer) { - if(description.flags) { - completers << new ArgumentCompleter(commandNameCompleter, - description.completer, - new StringsCompleter(description.flags.collect() { CommandArgument arg -> "-$arg.name".toString() })) - } - else { - completers << new ArgumentCompleter(commandNameCompleter, description.completer) - } - - } - else { - if(description.flags) { - completers << new ArgumentCompleter(commandNameCompleter, new StringsCompleter(description.flags.collect() { CommandArgument arg -> "-$arg.name".toString() })) - } - else { - completers << commandNameCompleter - } - } - } - } - - return completers - } - - @Override - Command getCommand(ProjectContext context, String name) { - getCommands(context) - return commandsByName[name] - } - - @Override - Iterable getCommands(ProjectContext context) { - if(commandsByName == null) { - commandsByName = new LinkedHashMap() - List excludes = [] - def registerCommand = { Command command -> - def name = command.name - if(!commandsByName.containsKey(name) && !excludes.contains(name)) { - if(command instanceof ProfileRepositoryAware) { - ((ProfileRepositoryAware)command).setProfileRepository(profileRepository) - } - commandsByName.put(name, command) - def desc = command.description - def synonyms = desc.synonyms - if(synonyms) { - for(String syn in synonyms) { - commandsByName.put(syn, command) - } - } - if(command instanceof ProjectContextAware) { - ((ProjectContextAware)command).projectContext = context - } - if(command instanceof ProfileCommand) { - ((ProfileCommand)command).profile = this - } - } - } - - CommandRegistry.findCommands(this).each(registerCommand) - - def parents = getExtends() - if(parents) { - excludes = (List)configuration.navigate("command", "excludes") ?: [] - registerParentCommands(context, parents, registerCommand) - } - } - return commandsByName.values() - } - - protected void registerParentCommands(ProjectContext context, Iterable parents, Closure registerCommand) { - for (parent in parents) { - parent.getCommands(context).each registerCommand - - def extended = parent.extends - if(extended) { - registerParentCommands context, extended, registerCommand - } - } - } - - @Override - boolean hasCommand(ProjectContext context, String name) { - getCommands(context) // ensure initialization - return commandsByName.containsKey(name) - } - - @Override - boolean handleCommand(ExecutionContext context) { - getCommands(context) // ensure initialization - - def commandLine = context.commandLine - def commandName = commandLine.commandName - def cmd = commandsByName[commandName] - if(cmd) { - def requiredArguments = cmd?.description?.arguments - int requiredArgumentCount = requiredArguments?.findAll() { CommandArgument ca -> ca.required }?.size() ?: 0 - if(commandLine.remainingArgs.size() < requiredArgumentCount) { - context.console.error "Command [$commandName] missing required arguments: ${requiredArguments*.name}. Type 'grails help $commandName' for more info." - return false - } - else { - return cmd.handle(context) - } - } - else { - // Apply command name expansion (rA for run-app, tA for test-app etc.) - cmd = commandsByName.values().find() { Command c -> - ScriptNameResolver.resolvesTo(commandName, c.name) - } - if(cmd) { - return cmd.handle(context) - } - else { - context.console.error("Command not found ${context.commandLine.commandName}") - def mostSimilar = CosineSimilarity.mostSimilar(commandName, commandsByName.keySet()) - List topMatches = mostSimilar.subList(0, Math.min(3, mostSimilar.size())); - if(topMatches) { - context.console.log("Did you mean: ${topMatches.join(' or ')}?") - } - return false - } - - } - } - - @Override - String getParentSkeletonDir() { - this.parentTargetFolder - } - - @Override - File getParentSkeletonDir(File parent) { - if (parentSkeletonDir) { - new File(parent, parentSkeletonDir) - } else { - parent - } - } - - List getSkeletonExcludes() { - this.skeletonExcludes - } - - @Override - String getName() { - name - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/AbstractStep.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/AbstractStep.groovy deleted file mode 100644 index f85da99b0b9..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/AbstractStep.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -import org.grails.build.parsing.CommandLine - -/** - * Abstract implementation of the {@link Step} interface - * - * @author Graeme Rocher - */ -abstract class AbstractStep implements Step { - ProfileCommand command - Map parameters - - AbstractStep(ProfileCommand command, Map parameters) { - this.command = command - this.parameters = parameters - } - - /** - * Obtains details of the given flag if it has been set by the user - * - * @param name The name of the flag - * @return The flag information, or null if it isn't set by the user - */ - def flag(CommandLine commandLine, String name) { - def value = commandLine?.undeclaredOptions?.get(name) - return value ?: null - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/Command.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/Command.groovy deleted file mode 100644 index 60f8b52663d..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/Command.groovy +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -import grails.util.Named - -/** - * An interface that represents a command to be executed by the Grails command line. Commands are by default global, - * however a command can be made specific to a particular {@link Profile} by implementation the {@link ProfileCommand} interface. - * - * @author Graeme Rocher - * @since 3.0 - */ -interface Command extends Named { - - /** - * @return The description of the command - */ - CommandDescription getDescription() - - /** - * run the command - * - * @param executionContext The {@link ExecutionContext} - * - * @return Whether the command should continue - */ - boolean handle(ExecutionContext executionContext) -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/CommandArgument.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/CommandArgument.groovy deleted file mode 100644 index b8dbe7fb056..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/CommandArgument.groovy +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -import groovy.transform.CompileStatic - - - -/** - * Represents argument to a command - * - * @author Graeme Rocher - * @since - */ -@CompileStatic -class CommandArgument { - /** - * The name of the argument - */ - String name - /** - * The description of the argument - */ - String description - - /** - * Whether the argument is required or not - */ - boolean required = true - - /** - * The string argument this argument translates into - */ - String target - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/CommandCancellationListener.java b/grails-shell/src/main/groovy/org/grails/cli/profile/CommandCancellationListener.java deleted file mode 100644 index eeebc4c0ecc..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/CommandCancellationListener.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile; - -/** - * A listener for listening for cancellation of {@link org.grails.cli.profile.Command} executions - * - * @author Lari Hotari - * @author Graeme Rocher - */ -public interface CommandCancellationListener { - /** - * Fired when a {@link org.grails.cli.profile.Command} is cancelled - */ - public void commandCancelled(); -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/CommandDescription.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/CommandDescription.groovy deleted file mode 100644 index 2f3b2edea9d..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/CommandDescription.groovy +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -import groovy.transform.Canonical -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import jline.console.completer.Completer - -/** - * Describes a {@link Command} - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -@Canonical -class CommandDescription { - /** - * The name of the command - */ - String name - /** - * The description of the command - */ - String description - /** - * The usage instructions for the command - */ - String usage - - /** - * Any names that should also map to this command - */ - Collection synonyms = [] - - /** - * A completer for the command - */ - Completer completer = null - - private Map arguments = new LinkedHashMap<>() - private Map flags = new LinkedHashMap<>() - - /** - * Returns an argument for the given name or null if it doesn't exist - * @param name The name - * @return The argument or null - */ - CommandArgument getArgument(String name) { - arguments[name] - } - - /** - * Returns a flag for the given name or null if it doesn't exist - * @param name The name - * @return The argument or null - */ - CommandArgument getFlag(String name) { - flags[name] - } - - /** - * Arguments to the command - */ - Collection getArguments() { - arguments.values() - } - - /** - * Flags to the command. These differ as they are optional and are prefixed with a hyphen (Example -debug) - */ - Collection getFlags() { - flags.values() - } - - /** - * Adds a synonyms for this command - * - * @param synonyms The synonyms - * @return This command description - */ - CommandDescription synonyms(String...synonyms) { - this.synonyms.addAll(synonyms) - return this - } - /** - * Sets the completer - * - * @param completer The class of the completer to set - * @return The description instance - */ - CommandDescription completer(Class completer) { - this.completer = completer.newInstance() - return this - } - - /** - * Sets the completer - * - * @param completer The completer to set - * @return The description instance - */ - CommandDescription completer(Completer completer) { - this.completer = completer - return this - } - - /** - * Adds an argument for the given named arguments - * - * @param args The named arguments - */ - @CompileDynamic - CommandDescription argument(Map args) { - def arg = new CommandArgument(args) - def name = arg.name - if(name) { - arguments[name] = arg - } - return this - } - - /** - * Adds a flag for the given named arguments - * - * @param args The named arguments - */ - @CompileDynamic - CommandDescription flag(Map args) { - def arg = new CommandArgument(args) - def name = arg.name - if(name) { - arg.required = false - flags[name] = arg - } - return this - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/CommandException.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/CommandException.groovy deleted file mode 100644 index 7137f7dc378..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/CommandException.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package org.grails.cli.profile - -import groovy.transform.InheritConstructors - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * @author Graeme Rocher - * @since 3.0 - */ -@InheritConstructors -class CommandException extends RuntimeException{ -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/DefaultFeature.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/DefaultFeature.groovy deleted file mode 100644 index b5e14277d84..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/DefaultFeature.groovy +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile - -import groovy.transform.CompileStatic -import groovy.transform.EqualsAndHashCode -import groovy.transform.ToString -import org.eclipse.aether.graph.Dependency -import org.grails.config.NavigableMap -import org.grails.io.support.Resource -import org.yaml.snakeyaml.LoaderOptions -import org.yaml.snakeyaml.Yaml -import org.yaml.snakeyaml.constructor.SafeConstructor - -import static org.grails.cli.profile.ProfileUtil.createDependency - -/** - * Default implementation of the {@link Feature} interface - * - * @author Graeme Rocher - * @since 3.1 - */ -@EqualsAndHashCode(includes = ['name']) -@ToString(includes = ['profile', 'name']) -@CompileStatic -class DefaultFeature implements Feature { - final Profile profile - final String name - final Resource location - final NavigableMap configuration = new NavigableMap() - final List dependencies = [] - final List buildPlugins - final List buildRepositories - - DefaultFeature(Profile profile, String name, Resource location) { - this.profile = profile - this.name = name - this.location = location - def featureYml = location.createRelative("feature.yml") - Map featureConfig = new Yaml(new SafeConstructor(new LoaderOptions())).>load(featureYml.getInputStream()) - configuration.merge(featureConfig) - def dependenciesConfig = configuration.get("dependencies") - - if(dependenciesConfig instanceof List) { - for(entry in ((List) dependenciesConfig)) { - if (entry instanceof Map) { - def scope = (String) entry.scope - def os = entry.os - if (os && !isSupportedOs(os.toString())) { - continue - } - String coords = (String) entry.coords - Dependency dependency = createDependency(coords, scope, entry) - dependencies.add(dependency) - } - } - } - this.buildPlugins = (List)configuration.get("build.plugins", []) - this.buildRepositories = (List) configuration.get("build.repositories", []) - } - - @Override - String getDescription() { - configuration.get("description", '').toString() - } - - static boolean isSupportedOs(String os) { - os = os.toLowerCase(Locale.ENGLISH).trim() - String osName = System.getProperty("os.name")?.toLowerCase(Locale.ENGLISH) ?: "unix" - switch (os) { - case "windows": - return osName.contains("windows") - case "osx": - return osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx") - case "unix": - return osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx") || - osName.contains("sunos") || osName.contains("solaris") || osName.contains("linux") || - osName.contains("freebsd") - default: - return false - } - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ExecutionContext.java b/grails-shell/src/main/groovy/org/grails/cli/profile/ExecutionContext.java deleted file mode 100644 index 05c1edc053b..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ExecutionContext.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile; - -import org.grails.build.parsing.CommandLine; - - -/** - * Context for the execution of {@link org.grails.cli.profile.Command} instances within a {@link org.grails.cli.profile.Profile} - * - * @author Lari Hotari - * @author Graeme Rocher - */ -public interface ExecutionContext extends ProjectContext { - - /** - * @return The parsed command line arguments as an instance of {@link org.grails.build.parsing.CommandLine} - */ - CommandLine getCommandLine(); - - /** - * Allows cancelling of the running command - */ - void cancel(); - - /** - * Attaches a listener for cancellation events - * - * @param listener The {@link CommandCancellationListener} - */ - void addCancelledListener(CommandCancellationListener listener); -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/Feature.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/Feature.groovy deleted file mode 100644 index e393a616d26..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/Feature.groovy +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile - -import org.eclipse.aether.graph.Dependency -import org.grails.config.NavigableMap -import org.grails.io.support.Resource - - -/** - * An interface that describes a feature of a profile. Different profiles may share many common features even if the profile itself is different. - * - * @author Graeme Rocher - * @since 3.1 - */ -interface Feature { - - /** - * @return The profile this feature belongs to - */ - Profile getProfile() - - /** - * @return The name of the feature - */ - String getName() - - /** - * @return The description of the profile - */ - String getDescription() - - /** - * @return The location of the feature - */ - Resource getLocation() - - /** - * @return The dependency definitions for this feature - */ - List getDependencies() - - /** - * @return The build plugin names - */ - List getBuildPlugins() - - /** - * @return The build repositories url - */ - List getBuildRepositories() - - /** - * @return The configuration for the feature - */ - NavigableMap getConfiguration() -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/FileSystemProfile.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/FileSystemProfile.groovy deleted file mode 100644 index f926df0ba1a..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/FileSystemProfile.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile - -import grails.util.BuildSettings -import groovy.transform.CompileStatic -import org.grails.io.support.FileSystemResource -import org.grails.io.support.Resource - - - -/** - * Simple disk based implementation of the {@link Profile} interface - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class FileSystemProfile extends ResourceProfile { - - FileSystemProfile(ProfileRepository repository, File profileDir) { - super(repository, profileDir.name, new FileSystemResource(profileDir)) - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/MultiStepCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/MultiStepCommand.groovy deleted file mode 100644 index 0813457854a..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/MultiStepCommand.groovy +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -import org.grails.cli.profile.commands.events.CommandEvents - -/** - * A command that executes multiple steps - * - * @author Graeme Rocher - * @since 3.0 - */ -abstract class MultiStepCommand implements ProfileCommand, CommandEvents { - - String name - Profile profile - int minArguments = 1 - - MultiStepCommand(String name, Profile profile) { - this.name = name - this.profile = profile - } - /** - * @return The steps that make up the command - */ - abstract List getSteps() - - @Override - boolean handle(ExecutionContext context) { - if(minArguments > 0 && (!context.commandLine.getRemainingArgs() || context.commandLine.getRemainingArgs().size() < minArguments)) { - context.console.error("Expecting ${minArguments ? 'an argument' : minArguments + ' arguments'} to $name.") - context.console.info("${description.usage}") - return true - } - notify("${name}Start", context) - for(AbstractStep step : getSteps()) { - if(!step.handle(context)) { - break - } - } - notify("${name}End", context) - true - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/Profile.java b/grails-shell/src/main/groovy/org/grails/cli/profile/Profile.java deleted file mode 100644 index b373b3eb802..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/Profile.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2014 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 - * - * 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.grails.cli.profile; - -import jline.console.completer.Completer; -import org.eclipse.aether.graph.Dependency; -import org.grails.config.NavigableMap; -import org.grails.io.support.Resource; - -import java.io.File; -import java.util.List; -import java.util.Set; - -/** - * A Profile defines an active code generation and command execution policy. For example the "web" profile allows - * the execution of code gen and build commands that relate to web applications - * - * @author Graeme Rocher - * @author Lari Hotari - * - * @since 3.0 - */ -public interface Profile { - - /** - * @return The name of the profile - */ - String getName(); - - /** - * @return The version of the profile - */ - String getVersion(); - - /** - * @return The description of the profile - */ - String getDescription(); - - /** - * @return The list of file extensions which should be treated as binary - */ - Set getBinaryExtensions(); - - /** - * @return The list of file patterns which should be executable in the resulting application - */ - Set getExecutablePatterns(); - - /** - * @return Text to display after an application has been created with the profile - */ - String getInstructions(); - - /** - * @return The features for this profile - */ - Iterable getFeatures(); - - /** - * @return The default features for this profile - */ - Iterable getDefaultFeatures(); - - /** - * @return The required features for this profile - */ - Iterable getRequiredFeatures(); - - /** - * The other {@link org.grails.cli.profile.Profile} instances that this {@link org.grails.cli.profile.Profile} extends - * @return zero or many {@link org.grails.cli.profile.Profile} instance that this profile extends from - */ - Iterable getExtends(); - - /** - * @return The maven repository definitions for this profile - */ - List getRepositories(); - - /** - * @return The dependency definitions for this profile - */ - List getDependencies(); - - /** - * @return The profiles configuration - */ - NavigableMap getConfiguration(); - - /** - * @return The directory where the profile is located locally - */ - Resource getProfileDir(); - - /** - * Obtain a template by path - * - * @param path The path to template - * @return The resource or null if it doesn't exist - */ - Resource getTemplate(String path); - - /** - * Obtain a command by name - * - * @param name Obtain a command by name - * @return The command - */ - Command getCommand(ProjectContext context, String name); - - /** - * The profile completers - * @param context The {@link org.grails.cli.profile.ProjectContext} instance - * @return An {@link java.lang.Iterable} of {@link jline.console.completer.Completer} instances - */ - Iterable getCompleters(ProjectContext context); - - /** - * The profile {@link org.grails.cli.profile.Command} instances - * - * @param context The {@link ProjectContext} instance - * @return An {@link java.lang.Iterable} of {@link org.grails.cli.profile.Command} instances - */ - Iterable getCommands(ProjectContext context); - - /** - * Whether a command executes for the given context and name - * @param context The {@link org.grails.cli.profile.ProjectContext} - * @param name The command name - * @return True if the command does exist - */ - boolean hasCommand(ProjectContext context, String name); - /** - * Obtains a {@link Command} - * - * @return True if the command was handled - */ - boolean handleCommand(ExecutionContext context); - - /** - * @return The buildscript maven repository definitions for this profile - */ - List getBuildRepositories(); - - /** - * @return The profile names to participate in build merge - */ - List getBuildMergeProfileNames(); - - /** - * @return The list of build plugins for this profile - */ - List getBuildPlugins(); - - /** - * @return The subfolder the parent profile(s) skeleton should be copied into - */ - String getParentSkeletonDir(); - - /** - * @return The directory the parent profile(s) skeleton should be copied into - */ - File getParentSkeletonDir(File parent); - - /** - * @return A list of paths to exclude from the skeleton. Used in ant fileset exclude: - */ - List getSkeletonExcludes(); -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileCommand.groovy deleted file mode 100644 index eacdfef9582..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileCommand.groovy +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -/** - * A {@link Command} applicable only to a certain {@link Profile} - * - * @author Graeme Rocher - * @since 3.0 - */ -interface ProfileCommand extends Command { - /** - * @return The profile of the command - */ - Profile getProfile() - - /** - * Sets the command profile - * - * @param profile The profile - */ - void setProfile(Profile profile) - -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileRepository.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileRepository.groovy deleted file mode 100644 index 3427b97b84d..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileRepository.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package org.grails.cli.profile - -import org.eclipse.aether.artifact.Artifact -import org.grails.io.support.Resource - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * - * A repository of {@link Profile} instances - * - * @author Graeme Rocher - * @since 3.0 - */ -interface ProfileRepository { - - String DEFAULT_PROFILE_NAME = 'web' - - /** - * Obtains a named {@link Profile} - * @param profileName The name of the profile - * @return The {@link Profile} or null - */ - Profile getProfile(String profileName) - - /** - * Obtains a named {@link Profile} - * @param profileName The name of the profile - * @param parentProfile Whether or not the profile is a parent of another profile - * @return The {@link Profile} or null - */ - Profile getProfile(String profileName, Boolean parentProfile) - - /** - * The directory where the profile is located - * - * @param profile The name of the profile - * @return The directory where the profile is located or null if it doesn't exist - */ - Resource getProfileDirectory(String profile) - - /** - * Returns the given profile with all dependencies in topological order where - * given profile is last in the order. - * - * @param profile The {@link Profile} instance - * @return The {@link Profile} and its dependencies - */ - List getProfileAndDependencies(Profile profile) - - /** - * @return All the available profiles in the repository - */ - List getAllProfiles() - - /** - * @return The {@link Artifact} that resolves to the profile - */ - Artifact getProfileArtifact(String profileName) -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileRepositoryAware.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileRepositoryAware.groovy deleted file mode 100644 index 9eb9f88e43e..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileRepositoryAware.groovy +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -/** - * For commands and steps that need to be made aware of the {@link ProfileRepository} to implement - * - * @author Graeme Rocher - * @since 3.0 - */ -interface ProfileRepositoryAware { - void setProfileRepository(ProfileRepository profileRepository) -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileUtil.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileUtil.groovy deleted file mode 100644 index 03a680ed4d7..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ProfileUtil.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package org.grails.cli.profile - -import org.eclipse.aether.artifact.DefaultArtifact -import org.eclipse.aether.graph.Dependency -import org.eclipse.aether.graph.Exclusion - -/** - * The utility class for the Grails profiles. - * - * @author Puneet Behl - * @since 4.1 - */ -class ProfileUtil { - - static Dependency createDependency(String coords, String scope, Map configEntry) { - if (coords.count(':') == 1) { - coords = "$coords:BOM" - } - Dependency dependency = new Dependency(new DefaultArtifact(coords), scope.toString()) - if (configEntry.containsKey('excludes')) { - List dependencyExclusions = new ArrayList<>() - List excludes = (List) configEntry.excludes - for (ex in excludes) { - if (ex instanceof Map) { - dependencyExclusions.add(new Exclusion((String) ex.group, (String) ex.module, (String) ex.classifier, (String) ex.extension)) - } - } - dependency = dependency.setExclusions(dependencyExclusions) - } - dependency - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectCommand.groovy deleted file mode 100644 index 06d43e2b17c..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectCommand.groovy +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -/** - * A marker interface for commands that are global, but apply only within the context of a project - * - * @author Graeme Rocher - * @since 3.0 - */ -interface ProjectCommand extends Command { -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectContext.java b/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectContext.java deleted file mode 100644 index a753c266335..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectContext.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile; - -import grails.build.logging.GrailsConsole; -import grails.config.ConfigMap; - -import java.io.File; - -/** - * The project context used by a {@link org.grails.cli.profile.Profile} - * - * @author Lari Hotari - * @author Graeme Rocher - */ -public interface ProjectContext { - /** - * @return The {@link grails.build.logging.GrailsConsole} instance - */ - GrailsConsole getConsole(); - - /** - * - * @return The base directory of the project - */ - File getBaseDir(); - - /** - * @return The codegen config - */ - ConfigMap getConfig(); - - /** - * Obtains a value from the codegen configuration - * - * @param path The path to value - * @return The value or null if not set - */ - String navigateConfig(String... path); - - /** - * Obtains a value of the given type from the codegen configuration - * - * @param requiredType The required return type - * @param path The path to value - * @return The value or null if not set - */ - T navigateConfigForType(Class requiredType, String... path); -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectContextAware.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectContextAware.groovy deleted file mode 100644 index 45f80580366..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ProjectContextAware.groovy +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - -/** - * Interface for components that want to be made aware of the proxy context - * - * @author Graeme Rocher - * @since 3.0 - */ -interface ProjectContextAware { - - void setProjectContext(ProjectContext projectContext) -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/ResourceProfile.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/ResourceProfile.groovy deleted file mode 100644 index b5007e5e232..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/ResourceProfile.groovy +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2014 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 - * - * 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.grails.cli.profile - -import groovy.transform.CompileStatic -import org.grails.config.NavigableMap -import org.grails.io.support.Resource -import org.yaml.snakeyaml.Yaml -/** - * A profile that operates against abstract {@link Resource} references - * - * - * @since 3.0 - * @author Lari Hotari - * @author Graeme Rocher - */ -@CompileStatic -class ResourceProfile extends AbstractProfile implements Profile { - - - ResourceProfile(ProfileRepository repository, String name, Resource profileDir) { - super(profileDir) - super.name = name - this.profileRepository = repository - initialize() - } - - @Override - String getName() { - super.name - } - - public static Profile create(ProfileRepository repository, String name, Resource profileDir) { - Profile profile = new ResourceProfile(repository, name, profileDir) - return profile - } - - - boolean equals(o) { - if (this.is(o)) return true - if (getClass() != o.class) return false - - ResourceProfile that = (ResourceProfile) o - - if (name != that.name) return false - - return true - } - - int hashCode() { - return (name != null ? name.hashCode() : 0) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/Step.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/Step.groovy deleted file mode 100644 index 0e0fb5827a5..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/Step.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile - - -/** - * Represents a step within a {@link Command}. Commands are made up of 1 or many steps. - * - * @author Graeme Rocher - * @since 3.0 - */ -interface Step { - - /** - * @return The name of the step - */ - String getName() - /** - * @return The parameters to the step - */ - Map getParameters() - - /** - * @return The command that this step is part of - */ - Command getCommand() - - /** - * Handles the command logic - * - * @param context The {@link ExecutionContext} instead - * - * @return True if the command should proceed to the next step, false otherwise - */ - boolean handle(ExecutionContext context) - -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ArgumentCompletingCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ArgumentCompletingCommand.groovy deleted file mode 100644 index b6d6b5710d7..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ArgumentCompletingCommand.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package org.grails.cli.profile.commands - -import jline.console.completer.ArgumentCompleter -import jline.console.completer.Completer -import org.grails.build.parsing.CommandLine -import org.grails.build.parsing.CommandLineParser -import org.grails.cli.profile.Command -import org.grails.cli.profile.CommandDescription - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * @author graemerocher - */ -abstract class ArgumentCompletingCommand implements Command, Completer { - - CommandLineParser cliParser = new CommandLineParser() - - @Override - final int complete(String buffer, int cursor, List candidates) { - def desc = getDescription() - def commandLine = cliParser.parseString(buffer) - return complete(commandLine, desc, candidates, cursor) - } - - protected int complete(CommandLine commandLine, CommandDescription desc, List candidates, int cursor) { - def invalidOptions = commandLine.undeclaredOptions.keySet().findAll { String str -> - desc.getFlag(str.trim()) == null - } - - def lastOption = commandLine.lastOption() - - - for (arg in desc.flags) { - def argName = arg.name - def flag = "-$argName".toString() - if (!commandLine.hasOption(arg.name)) { - if (lastOption) { - def lastArg = lastOption.key - if (arg.name.startsWith(lastArg)) { - candidates.add("${argName.substring(lastArg.length())} ".toString()) - } else if (!invalidOptions) { - candidates.add "$flag ".toString() - } - } else { - candidates.add "$flag ".toString() - } - } - } - return cursor - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ClosureExecutingCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ClosureExecutingCommand.groovy deleted file mode 100644 index ef5155a3f0e..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ClosureExecutingCommand.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.cli.profile.commands - -import org.grails.cli.profile.Command -import org.grails.cli.profile.CommandDescription -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileCommand - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * A command that executes a closure - * - * @author Graeme Rocher - * @since 3.0 - */ -class ClosureExecutingCommand implements ProfileCommand { - String name - Closure callable - Profile profile - - ClosureExecutingCommand(String name, Closure callable) { - this.name = name - this.callable = callable - } - - @Override - CommandDescription getDescription() { - new CommandDescription(name) - } - - @Override - boolean handle(ExecutionContext executionContext) { - callable.call(executionContext) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CommandCompleter.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CommandCompleter.groovy deleted file mode 100644 index 34ab7dcfa7c..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CommandCompleter.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile.commands - -import jline.console.completer.Completer -import org.grails.cli.profile.Command - -/** - * A completer for commands - * - * @author Graeme Rocher - * @since 3.1 - */ -class CommandCompleter implements Completer { - - Collection commands - - CommandCompleter(Collection commands) { - this.commands = commands - } - - @Override - int complete(String buffer, int cursor, List candidates) { - def cmd = commands.find() { - def trimmed = buffer.trim() - if(trimmed.split(/\s/).size() > 1) { - return trimmed.startsWith( it.name ) - } - else { - return trimmed == it.name - } - } - if(cmd instanceof Completer) { - return ((Completer)cmd).complete(buffer, cursor, candidates) - } - return cursor - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CommandRegistry.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CommandRegistry.groovy deleted file mode 100644 index c8bd4f32432..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CommandRegistry.groovy +++ /dev/null @@ -1,101 +0,0 @@ -package org.grails.cli.profile.commands - -import groovy.transform.CompileStatic -import org.grails.cli.GrailsCli -import org.grails.cli.profile.Command -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileCommand -import org.grails.cli.profile.ProfileRepository -import org.grails.cli.profile.ProfileRepositoryAware -import org.grails.cli.profile.ProjectCommand -import org.grails.cli.profile.commands.factory.CommandFactory -import org.grails.config.CodeGenConfig - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * Registry of available commands - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class CommandRegistry { - - private static Map registeredCommands = [:] - private static List registeredCommandFactories = [] - - static { - def commands = ServiceLoader.load(Command).iterator() - - while(commands.hasNext()) { - Command command = commands.next() - registeredCommands[command.name] = command - } - - def commandFactories = ServiceLoader.load(CommandFactory).iterator() - while(commandFactories.hasNext()) { - CommandFactory commandFactory = commandFactories.next() - - registeredCommandFactories << commandFactory - } - } - - /** - * Returns a command for the given name and repository - * - * @param name The command name - * @param repository The {@link ProfileRepository} instance - * @return A command or null of non exists - */ - static Command getCommand(String name, ProfileRepository repository) { - def command = registeredCommands[name] - if(command instanceof ProfileRepositoryAware) { - command.profileRepository = repository - } - return command - } - - static Collection findCommands( ProfileRepository repository ) { - registeredCommands.values().collect() { Command cmd -> - if(cmd instanceof ProfileRepositoryAware) { - ((ProfileRepositoryAware)cmd).profileRepository = repository - } - return cmd - } - } - - static Collection findCommands( Profile profile, boolean inherited = false ) { - Collection commands = [] - - for(CommandFactory cf in registeredCommandFactories) { - def factoryCommands = cf.findCommands(profile, inherited) - def condition = { Command c -> c.name == 'events' } - def eventCommands = factoryCommands.findAll(condition) - for(ec in eventCommands) { - ec.handle(new GrailsCli.ExecutionContextImpl(new CodeGenConfig(profile.configuration))) - } - factoryCommands.removeAll(condition) - commands.addAll factoryCommands - } - - commands.addAll( registeredCommands.values() - .findAll { Command c -> (c instanceof ProjectCommand) || (c instanceof ProfileCommand) && ((ProfileCommand)c).profile == profile } - ) - return commands - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateAppCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateAppCommand.groovy deleted file mode 100644 index b2884de7eea..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateAppCommand.groovy +++ /dev/null @@ -1,778 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands - -import grails.build.logging.GrailsConsole -import grails.io.IOUtils -import grails.util.Environment -import grails.util.GrailsNameUtils -import groovy.ant.AntBuilder -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode -import org.eclipse.aether.graph.Dependency -import org.grails.build.logging.GrailsConsoleAntBuilder -import org.grails.build.parsing.CommandLine -import org.grails.cli.GrailsCli -import org.grails.cli.profile.CommandDescription -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Feature -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileRepository -import org.grails.cli.profile.ProfileRepositoryAware -import org.grails.cli.profile.commands.io.GradleDependency -import org.grails.cli.profile.repository.MavenProfileRepository -import org.grails.io.support.FileSystemResource -import org.grails.io.support.Resource - -import java.nio.file.DirectoryNotEmptyException -import java.nio.file.FileVisitResult -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.stream.Stream - -/** - * Command for creating Grails applications - * - * @author Graeme Rocher - * @author Lari Hotari - * @since 3.0 - */ -@CompileStatic -class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepositoryAware { - private static final String GRAILS_VERSION_FALLBACK_IN_IDE_ENVIRONMENTS_FOR_RUNNING_TESTS ='4.0.0.BUILD-SNAPSHOT' - public static final String NAME = "create-app" - public static final String PROFILE_FLAG = "profile" - public static final String FEATURES_FLAG = "features" - public static final String ENCODING = System.getProperty("file.encoding") ?: "UTF-8" - public static final String INPLACE_FLAG = "inplace" - - protected static final String APPLICATION_YML = "application.yml" - protected static final String BUILD_GRADLE = "build.gradle" - protected static final String GRADLE_PROPERTIES = "gradle.properties" - public static final String UNZIP_PROFILE_TEMP_DIR = "tempgrailsapp" - - ProfileRepository profileRepository - Map variables = [:] - String appname - String groupname - String defaultpackagename - File targetDirectory - - CommandDescription description = new CommandDescription(name, "Creates an application", "create-app [NAME] --profile=web") - - CreateAppCommand() { - populateDescription() - description.flag(name: INPLACE_FLAG, description: "Used to create an application using the current directory") - description.flag(name: PROFILE_FLAG, description: "The profile to use", required:false) - description.flag(name: FEATURES_FLAG, description: "The features to use", required:false) - } - - protected void populateDescription() { - description.argument(name: "Application Name", description: "The name of the application to create.", required: false) - } - - @Override - String getName() { - return NAME - } - - @Override - protected int complete(CommandLine commandLine, CommandDescription desc, List candidates, int cursor) { - def lastOption = commandLine.lastOption() - if(lastOption != null) { - // if value == true it means no profile is specified and only the flag is present - def profileNames = profileRepository.allProfiles.collect() { Profile p -> p.name } - if(lastOption.key == PROFILE_FLAG) { - def val = lastOption.value - if( val == true) { - candidates.addAll(profileNames) - return cursor - } - else if(!profileNames.contains(val)) { - def valStr = val.toString() - - def candidateProfiles = profileNames.findAll { String pn -> - pn.startsWith(valStr) - }.collect() { String pn -> - "${pn.substring(valStr.size())} ".toString() - } - candidates.addAll candidateProfiles - return cursor - } - } - else if(lastOption.key == FEATURES_FLAG) { - def val = lastOption.value - def profile = profileRepository.getProfile(commandLine.hasOption(PROFILE_FLAG) ? commandLine.optionValue(PROFILE_FLAG).toString() : getDefaultProfile()) - def featureNames = profile.features.collect() { Feature f -> f.name } - if( val == true) { - candidates.addAll(featureNames) - return cursor - } - else if(!profileNames.contains(val)) { - def valStr = val.toString() - if(valStr.endsWith(',')) { - def specified = valStr.split(',') - candidates.addAll(featureNames.findAll { String f -> - !specified.contains(f) - }) - return cursor - } - - def candidatesFeatures = featureNames.findAll { String pn -> - pn.startsWith(valStr) - }.collect() { String pn -> - "${pn.substring(valStr.size())} ".toString() - } - candidates.addAll candidatesFeatures - return cursor - } - } - } - return super.complete(commandLine, desc, candidates, cursor) - } - - protected File getDestinationDirectory(File srcFile) { - String searchDir = "skeleton" - File srcDir = srcFile.parentFile - File destDir - if (srcDir.absolutePath.endsWith(searchDir)) { - destDir = targetDirectory - } else { - int index = srcDir.absolutePath.lastIndexOf(searchDir) + searchDir.size() + 1 - String relativePath = (srcDir.absolutePath - srcDir.absolutePath.substring(0,index)) - destDir = new File(targetDirectory, relativePath) - } - destDir - } - - protected void appendFeatureFiles(File skeletonDir) { - def ymlFiles = findAllFilesByName(skeletonDir, APPLICATION_YML) - def buildGradleFiles = findAllFilesByName(skeletonDir, BUILD_GRADLE) - def gradlePropertiesFiles = findAllFilesByName(skeletonDir, GRADLE_PROPERTIES) - - ymlFiles.each { File newYml -> - File oldYml = new File(getDestinationDirectory(newYml), APPLICATION_YML) - String oldText = (oldYml.isFile()) ? oldYml.getText(ENCODING) : null - if (oldText) { - appendToYmlSubDocument(newYml, oldText, oldYml) - } else { - oldYml.text = newYml.getText(ENCODING) - } - - } - buildGradleFiles.each { File srcFile -> - File destFile = new File(getDestinationDirectory(srcFile), BUILD_GRADLE) - destFile.text = destFile.getText(ENCODING) + System.lineSeparator() + srcFile.getText(ENCODING) - } - - gradlePropertiesFiles.each { File srcFile-> - File destFile = new File(getDestinationDirectory(srcFile), GRADLE_PROPERTIES) - if (!destFile.exists()) { - destFile.createNewFile() - } - destFile.append(srcFile.getText(ENCODING)) -// destFile.text = destFile.getText(ENCODING) + srcFile.getText(ENCODING) - } - } - - protected void buildTargetFolders(Profile profile, Map targetDir, File projectDir) { - if (!targetDir.containsKey(profile)) { - targetDir[profile] = projectDir - } - profile.extends.each { Profile p -> - if (profile.parentSkeletonDir) { - targetDir[p] = profile.getParentSkeletonDir(projectDir) - } else { - targetDir[p] = targetDir[profile] - } - buildTargetFolders(p, targetDir, projectDir) - } - } - - - Set findAllFilesByName(File projectDir, String fileName) { - Set files = (Set)[] - if (projectDir.exists()) { - Files.walkFileTree(projectDir.absoluteFile.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes mainAtts) - throws IOException { - if (path.fileName.toString() == fileName) { - files.add(path.toFile()) - } - return FileVisitResult.CONTINUE; - } - }) - } - files - } - - boolean handle(CreateAppCommandObject cmd) { - if (profileRepository == null) throw new IllegalStateException("Property 'profileRepository' must be set") - - String profileName = cmd.profileName - - Profile profileInstance = profileRepository.getProfile(profileName) - if (!validateProfile(profileInstance, profileName)) { - return false - } - - List features = evaluateFeatures(profileInstance, cmd.features).toList() - - if (profileInstance) { - if (!initializeGroupAndName(cmd.appName, cmd.inplace)) { - return false - } - - initializeVariables(profileName, cmd.grailsVersion) - - if(profileRepository instanceof MavenProfileRepository) { - MavenProfileRepository mpr = (MavenProfileRepository)profileRepository - String gormDep = mpr.profileDependencyVersions.versionProperties.get('gorm.version') - if(gormDep != null) { - variables['gorm.version'] = gormDep - } - String groovyDep = mpr.profileDependencyVersions.versionProperties.get('groovy.version') - if(groovyDep != null) { - variables['groovy.version'] = groovyDep - } - String grailsGradlePluginVersion = mpr.profileDependencyVersions.versionProperties.get('grails-gradle-plugin.version') - if (grailsGradlePluginVersion != null) { - variables['grails-gradle-plugin.version'] = grailsGradlePluginVersion - } - } - - Path appFullDirectory = Paths.get(cmd.baseDir.path, appname) - - File projectTargetDirectory = cmd.inplace ? new File(".").canonicalFile : appFullDirectory.toAbsolutePath().normalize().toFile() - - if (projectTargetDirectory.exists() && !isDirectoryEmpty(projectTargetDirectory)) { - GrailsConsole.getInstance().error(new DirectoryNotEmptyException(projectTargetDirectory.absolutePath)) - return false - } - - def profiles = profileRepository.getProfileAndDependencies(profileInstance) - - Map targetDirs = [:] - buildTargetFolders(profileInstance, targetDirs, projectTargetDirectory) - - for(Profile p : profiles) { - Set ymlFiles = findAllFilesByName(projectTargetDirectory, APPLICATION_YML) - Map ymlCache = [:] - - targetDirectory = targetDirs[p] - - ymlFiles.each { File applicationYmlFile -> - String previousApplicationYml = (applicationYmlFile.isFile()) ? applicationYmlFile.getText(ENCODING) : null - if (previousApplicationYml) { - ymlCache[applicationYmlFile] = previousApplicationYml - } - } - - copySkeleton(profileInstance, p) - - ymlCache.each { File applicationYmlFile, String previousApplicationYml -> - if(applicationYmlFile.exists()) { - appendToYmlSubDocument(applicationYmlFile, previousApplicationYml) - } - } - } - def ant = new GrailsConsoleAntBuilder() - - for(Feature f in features) { - def location = f.location - - File skeletonDir - File tmpDir - if(location instanceof FileSystemResource) { - skeletonDir = location.createRelative("skeleton").file - } - else { - tmpDir = unzipProfile(ant, location) - skeletonDir = new File(tmpDir, "META-INF/grails-profile/features/$f.name/skeleton") - } - - targetDirectory = targetDirs[f.profile] - - appendFeatureFiles(skeletonDir) - - if(skeletonDir.exists()) { - copySrcToTarget(ant, skeletonDir, ['**/' + APPLICATION_YML], profileInstance.binaryExtensions) - } - - // Cleanup temporal directories - deleteDirectory(tmpDir) - deleteDirectory(skeletonDir) - } - - replaceBuildTokens(profileName, profileInstance, features, projectTargetDirectory) - cmd.console.addStatus( - "${name == 'create-plugin' ? 'Plugin' : 'Application'} created at ${projectTargetDirectory.absolutePath}" - ) - if (profileInstance.instructions) { - cmd.console.addStatus(profileInstance.instructions) - } - GrailsCli.tiggerAppLoad() - return true - } - else { - System.err.println "Cannot find profile $profileName" - return false - } - } - - private boolean isDirectoryEmpty(File target) { - if (target.isDirectory()) { - try (Stream entries = Files.list(Paths.get(target.toURI()))) { - return !entries.findFirst().isPresent() - } - } - return false - } - - @Override - boolean handle(ExecutionContext executionContext) { - CommandLine commandLine = executionContext.commandLine - - String profileName = evaluateProfileName(commandLine) - - List validFlags = [INPLACE_FLAG, PROFILE_FLAG, FEATURES_FLAG] - commandLine.undeclaredOptions.each { String key, Object value -> - if (!validFlags.contains(key)) { - List possibleSolutions = validFlags.findAll { it.substring(0, 2) == key.substring(0, 2) } - StringBuilder warning = new StringBuilder("Unrecognized flag: ${key}.") - if (possibleSolutions) { - warning.append(" Possible solutions: ") - warning.append(possibleSolutions.join(", ")) - } - executionContext.console.warn(warning.toString()) - } - } - - boolean inPlace = commandLine.hasOption('inplace') || GrailsCli.isInteractiveModeActive() - String appName = commandLine.remainingArgs ? commandLine.remainingArgs[0] : "" - - List features = commandLine.optionValue("features")?.toString()?.split(',')?.toList() - - CreateAppCommandObject cmd = new CreateAppCommandObject( - appName: appName, - baseDir: executionContext.baseDir, - profileName: profileName, - grailsVersion: Environment.getPackage().getImplementationVersion() ?: GRAILS_VERSION_FALLBACK_IN_IDE_ENVIRONMENTS_FOR_RUNNING_TESTS, - features: features, - inplace: inPlace, - console: executionContext.console - ) - - return this.handle(cmd) - } - - protected boolean validateProfile(Profile profileInstance, String profileName) { - if (profileInstance == null) { - GrailsConsole.instance.error("Profile not found for name [$profileName]") - return false - } - return true - } - - private Map unzippedDirectories = new LinkedHashMap() - - @CompileDynamic - protected File unzipProfile(AntBuilder ant, Resource location) { - - def url = location.URL - def tmpDir = unzippedDirectories.get(url) - - if(tmpDir == null) { - def jarFile = IOUtils.findJarFile(url) - tmpDir = Files.createTempDirectory(UNZIP_PROFILE_TEMP_DIR).toFile() - tmpDir.deleteOnExit() - ant.unzip(src: jarFile, dest: tmpDir) - unzippedDirectories.put(url, tmpDir) - } - return tmpDir - } - - @CompileDynamic - protected void replaceBuildTokens(String profileCoords, Profile profile, List features, File targetDirectory) { - AntBuilder ant = new GrailsConsoleAntBuilder() - def ln = System.getProperty("line.separator") - - Closure repositoryUrl = { int spaces, String repo -> - repo.startsWith('http') ? "${' ' * spaces}maven { url \"${repo}\" }" : "${' ' * spaces}${repo}" - } - - def repositories = profile.repositories.collect(repositoryUrl.curry(4)).unique().join(ln) - - List profileDependencies = profile.dependencies - def dependencies = profileDependencies.findAll() { Dependency dep -> - dep.scope != 'build' - } - def buildDependencies = profileDependencies.findAll() { Dependency dep -> - dep.scope == 'build' - } - - for(Feature f in features) { - dependencies.addAll f.dependencies.findAll(){ Dependency dep -> dep.scope != 'build'} - buildDependencies.addAll f.dependencies.findAll(){ Dependency dep -> dep.scope == 'build'} - } - - dependencies.add(new Dependency(profileRepository.getProfileArtifact(profileCoords), "profile")) - - dependencies = dependencies.unique() - - List gradleDependencies = convertToGradleDependencies(dependencies) - - String dependencyString = gradleDependencies - .sort({ GradleDependency dep-> dep.scope}) - .collect( {GradleDependency dep-> dep.toString(4)}) - .unique() - .join(ln) - - def buildRepositories = profile.buildRepositories - for (Feature f in features) { - buildRepositories.addAll(f.getBuildRepositories()) - } - buildRepositories = buildRepositories.collect(repositoryUrl.curry(8)).unique().join(ln) - - buildDependencies = buildDependencies.collect() { Dependency dep -> - String artifactStr = resolveArtifactString(dep) - " classpath \"${artifactStr}\"".toString() - }.unique().join(ln) - - def buildPlugins = profile.buildPlugins.collect() { String name -> - "apply plugin:\"$name\"" - } - - for(Feature f in features) { - buildPlugins.addAll f.buildPlugins.collect() { String name -> - "apply plugin:\"$name\"" - } - } - - buildPlugins = buildPlugins.unique().join(ln) - - ant.replace(dir: targetDirectory) { - replacefilter { - replacetoken("@buildPlugins@") - replacevalue(buildPlugins) - } - replacefilter { - replacetoken("@dependencies@") - replacevalue(dependencyString) - } - replacefilter { - replacetoken("@buildDependencies@") - replacevalue(buildDependencies) - } - replacefilter { - replacetoken("@buildRepositories@") - replacevalue(buildRepositories) - } - replacefilter { - replacetoken("@repositories@") - replacevalue(repositories) - } - variables.each { k, v -> - replacefilter { - replacetoken("@${k}@".toString()) - replacevalue(v) - } - } - } - } - - protected String evaluateProfileName(CommandLine mainCommandLine) { - mainCommandLine.optionValue('profile')?.toString() ?: getDefaultProfile() - } - - protected Iterable evaluateFeatures(Profile profile, List requestedFeatures) { - if (requestedFeatures) { - List allFeatureNames = profile.features*.name - Collection validFeatureNames = requestedFeatures.intersect(allFeatureNames) - requestedFeatures.removeAll(allFeatureNames) - requestedFeatures.each { String invalidFeature -> - List possibleSolutions = allFeatureNames.findAll { - it.substring(0, 2) == invalidFeature.substring(0, 2) - } - StringBuilder warning = new StringBuilder("Feature ${invalidFeature} does not exist in the profile ${profile.name}!") - if (possibleSolutions) { - warning.append(" Possible solutions: ") - warning.append(possibleSolutions.join(", ")) - } - GrailsConsole.getInstance().warn(warning.toString()) - } - return (profile.features.findAll() { Feature f -> validFeatureNames.contains(f.name) } + profile.requiredFeatures).unique() - } - else { - return (profile.defaultFeatures + profile.requiredFeatures).unique() - } - } - - protected String getDefaultProfile() { - ProfileRepository.DEFAULT_PROFILE_NAME - } - - protected String createNewApplicationYml(String previousYml, String newYml) { - def ln = System.getProperty("line.separator") - if (newYml != previousYml) { - StringBuilder appended = new StringBuilder(previousYml.length() + newYml.length() + 30) - if(!previousYml.startsWith("---")) { - appended.append('---' + ln) - } - appended.append(previousYml).append(ln + "---" + ln) - appended.append(newYml) - appended.toString() - } else { - newYml - } - } - - private void appendToYmlSubDocument(File applicationYmlFile, String previousApplicationYml) { - appendToYmlSubDocument(applicationYmlFile, previousApplicationYml, applicationYmlFile) - } - - private void appendToYmlSubDocument(File applicationYmlFile, String previousApplicationYml, File setTo) { - String newApplicationYml = applicationYmlFile.text - if(previousApplicationYml && newApplicationYml != previousApplicationYml) { - setTo.text = createNewApplicationYml(previousApplicationYml, newApplicationYml) - } - } - - protected boolean initializeGroupAndName(String appName, boolean inplace) { - if (!appName && !inplace) { - GrailsConsole.getInstance().error("Specify an application name or use --inplace to create an application in the current directory") - return false - } - String groupAndAppName = appName - if(inplace) { - appname = new File(".").canonicalFile.name - if(!groupAndAppName) { - groupAndAppName = appname - } - } - - if(!groupAndAppName) { - GrailsConsole.getInstance().error("Specify an application name or use --inplace to create an application in the current directory") - return false - } - - try { - defaultpackagename = establishGroupAndAppName(groupAndAppName) - } catch (IllegalArgumentException e ) { - GrailsConsole.instance.error(e.message) - return false - } - } - - private void initializeVariables(String profileName, String grailsVersion) { - variables.APPNAME = appname - - variables['grails.codegen.defaultPackage'] = defaultpackagename - variables['grails.codegen.defaultPackage.path'] = defaultpackagename.replace('.', '/') - - def projectClassName = GrailsNameUtils.getNameFromScript(appname) - - variables['grails.codegen.projectClassName'] = projectClassName - variables['grails.codegen.projectNaturalName'] = GrailsNameUtils.getNaturalName(projectClassName) - variables['grails.codegen.projectName'] = GrailsNameUtils.getScriptName(projectClassName) - variables['grails.profile'] = profileName - variables['grails.version'] = grailsVersion - variables['grails.app.name'] = appname - variables['grails.app.group'] = groupname - } - - private String establishGroupAndAppName(String groupAndAppName) { - String defaultPackage - List parts = groupAndAppName.split(/\./) as List - if (parts.size() == 1) { - appname = parts[0] - defaultPackage = createValidPackageName() - groupname = defaultPackage - } else { - appname = parts[-1] - groupname = parts[0..-2].join('.') - defaultPackage = groupname - } - return defaultPackage - } - - private String createValidPackageName() { - String defaultPackage = appname.split(/[-]+/).collect { String token -> (token.toLowerCase().toCharArray().findAll { char ch -> Character.isJavaIdentifierPart(ch) } as char[]) as String }.join('.') - if(!GrailsNameUtils.isValidJavaPackage(defaultPackage)) { - throw new IllegalArgumentException("Cannot create a valid package name for [$appname]. Please specify a name that is also a valid Java package.") - } - return defaultPackage - } - - @CompileStatic(TypeCheckingMode.SKIP) - private void copySkeleton(Profile profile, Profile participatingProfile) { - def buildMergeProfileNames = profile.buildMergeProfileNames - def excludes = profile.skeletonExcludes - if (profile == participatingProfile) { - excludes = [] - } - - AntBuilder ant = new GrailsConsoleAntBuilder() - - def skeletonResource = participatingProfile.profileDir.createRelative("skeleton") - File skeletonDir - File tmpDir - if(skeletonResource instanceof FileSystemResource) { - skeletonDir = skeletonResource.file - } - else { - // establish the JAR file name and extract - tmpDir = unzipProfile(ant, skeletonResource) - skeletonDir = new File(tmpDir, "META-INF/grails-profile/skeleton") - } - copySrcToTarget(ant, skeletonDir, excludes, profile.binaryExtensions) - - Set sourceBuildGradles = findAllFilesByName(skeletonDir, BUILD_GRADLE) - - sourceBuildGradles.each { File srcFile -> - final File srcDir = srcFile.parentFile - final File destDir = getDestinationDirectory(srcFile) - final File destFile = new File(destDir, BUILD_GRADLE) - - ant.copy(file:"${srcDir}/.gitignore", todir: destDir, failonerror:false) - - if (!destFile.exists()) { - ant.copy file:srcFile, tofile:destFile - } else if (buildMergeProfileNames.contains(participatingProfile.name)) { - def concatFile = "${destDir}/concat-build.gradle" - ant.move(file:destFile, tofile: concatFile) - ant.concat([destfile: destFile, fixlastline: true], { - path { - pathelement location: concatFile - pathelement location: srcFile - } - }) - ant.delete(file: concatFile, failonerror: false) - } - } - - Set sourceGradleProperties = findAllFilesByName(skeletonDir, GRADLE_PROPERTIES) - - sourceGradleProperties.each { File srcFile -> - File destDir = getDestinationDirectory(srcFile) - File destFile = new File(destDir, GRADLE_PROPERTIES) - - if (!destFile.exists()) { - ant.copy file: srcFile, tofile: destFile - } else { - def concatGradlePropertiesFile = "${destDir}/concat-gradle.properties" - ant.move(file: destFile, tofile: concatGradlePropertiesFile) - ant.concat([destfile: destFile, fixlastline: true], { - path { - pathelement location: concatGradlePropertiesFile - pathelement location: srcFile - } - }) - ant.delete(file: concatGradlePropertiesFile, failonerror: false) - } - } - - ant.chmod(dir: targetDirectory, includes: profile.executablePatterns.join(' '), perm: 'u+x') - - // Cleanup temporal directories - deleteDirectory(tmpDir) - deleteDirectory(skeletonDir) - } - - @CompileDynamic - protected void copySrcToTarget(GrailsConsoleAntBuilder ant, File srcDir, List excludes, Set binaryFileExtensions) { - ant.copy(todir: targetDirectory, overwrite: true, encoding: 'UTF-8') { - fileSet(dir: srcDir, casesensitive: false) { - exclude(name: '**/.gitkeep') - for (exc in excludes) { - exclude name: exc - } - exclude name: "**/"+BUILD_GRADLE - exclude name: "**/"+GRADLE_PROPERTIES - binaryFileExtensions.each { ext -> - exclude(name: "**/*.${ext}") - } - } - filterset { - variables.each { k, v -> - filter(token: k, value: v) - } - } - mapper { - filtermapper { - variables.each { k, v -> - replacestring(from: "@${k}@".toString(), to: v) - } - } - } - } - ant.copy(todir: targetDirectory, overwrite: true) { - fileSet(dir: srcDir, casesensitive: false) { - binaryFileExtensions.each { ext -> - include(name: "**/*.${ext}") - } - for (exc in excludes) { - exclude name: exc - } - exclude name: "**/"+BUILD_GRADLE - } - mapper { - filtermapper { - variables.each { k, v -> - replacestring(from: "@${k}@".toString(), to: v) - } - } - } - } - } - - protected String resolveArtifactString(Dependency dep) { - def artifact = dep.artifact - def v = artifact.version.replace('BOM', '') - - return v ? "${artifact.groupId}:${artifact.artifactId}:${v}" : "${artifact.groupId}:${artifact.artifactId}" - } - - private void deleteDirectory(File directory) { - try { - directory?.deleteDir() - } catch (Throwable t) { - // Ignore error deleting temporal directory - } - } - - protected List convertToGradleDependencies(List dependencies) { - List gradleDependencies = [] - gradleDependencies.addAll(dependencies.collect { new GradleDependency(it) }) - gradleDependencies - } - - static class CreateAppCommandObject { - String appName - File baseDir - String profileName - String grailsVersion - List features - boolean inplace = false - GrailsConsole console - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreatePluginCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreatePluginCommand.groovy deleted file mode 100644 index 9ea662a99df..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreatePluginCommand.groovy +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands - -import groovy.transform.CompileStatic -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Profile -/** - * A command for creating a plugin - * - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class CreatePluginCommand extends CreateAppCommand { - - public static final String NAME = "create-plugin" - - CreatePluginCommand() { - description.description = "Creates a plugin" - description.usage = "create-plugin [NAME]" - } - - @Override - protected void populateDescription() { - description.argument(name: "Plugin Name", description: "The name of the plugin to create.", required: false) - } - - @Override - String getName() { NAME } - - @Override - protected String getDefaultProfile() { "web-plugin" } - - protected boolean validateProfile(Profile profileInstance, String profileName, ExecutionContext executionContext) { - def pluginProfile = profileInstance.extends.find() { Profile parent -> parent.name == 'plugin' } - if(profileName != 'plugin' && pluginProfile == null) { - executionContext.console.error("No valid plugin profile found for name [$profileName]") - return false - } - else { - return super.validateProfile(profileInstance, profileName) - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateProfileCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateProfileCommand.groovy deleted file mode 100644 index a2d72abdc92..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateProfileCommand.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile.commands - - - -/** - * Creates a profile - * - * @author Graeme Rocher - * @since 3.1 - */ -class CreateProfileCommand extends CreateAppCommand { - public static final String NAME = "create-profile" - - CreateProfileCommand() { - description.description = "Creates a profile" - description.usage = "create-profile [NAME]" - } - - @Override - protected void populateDescription() { - description.argument(name: "Profile Name", description: "The name of the plugin to create.", required: false) - } - - @Override - String getName() { NAME } - - @Override - protected String getDefaultProfile() { "profile" } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/DefaultMultiStepCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/DefaultMultiStepCommand.groovy deleted file mode 100644 index bea967a0343..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/DefaultMultiStepCommand.groovy +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands - -import grails.build.logging.GrailsConsole -import groovy.transform.CompileDynamic -import jline.console.completer.Completer -import org.grails.cli.profile.* -import org.grails.cli.profile.steps.StepRegistry -/** - * Simple implementation of the {@link MultiStepCommand} abstract class that parses commands defined in YAML or JSON - * - * @author Lari Hotari - * @author Graeme Rocher - * @since 3.0 - */ -class DefaultMultiStepCommand extends MultiStepCommand { - private Map data - private List steps - - final CommandDescription description - - DefaultMultiStepCommand(String name, Profile profile, Map data) { - super(name, profile) - this.data = data - - def description = data?.description - if(description instanceof List) { - List descList = (List)description - if(descList) { - - this.description = new CommandDescription(name: name, description: descList.get(0).toString(), usage: data?.usage) - - if(descList.size()>1) { - for(arg in descList[1..-1]) { - if(arg instanceof Map) { - Map map = (Map)arg - if(map.containsKey('usage')) { - this.description.usage = map.get('usage')?.toString() - } - else if(map.containsKey('completer')) { - def completerClass = map.get('completer') - if(completerClass) { - try { - this.description.completer = (Completer)Thread.currentThread().contextClassLoader.loadClass(completerClass.toString()).newInstance() - } catch (e) { - // ignore - } - } - } - else { - handleArgumentOrFlag(map, 'argument') - handleArgumentOrFlag(map, 'flag') - } - } - } - } - } - } - else { - this.description = new CommandDescription(name: name, description: description.toString(), usage: data?.usage) - } - } - - @CompileDynamic - boolean handleArgumentOrFlag(Map map, String name) { - try { - if(map.containsKey(name)) { - def argName = map.remove(name) - map.put('name', argName) - this.description."$name"(map) - return true - } - } catch (Throwable e) { - GrailsConsole.getInstance().error("Invalid $name found in [$profile.name] profile ${map}: ${e.message}", e) - } - return false - } - - List getSteps() { - if(steps==null) { - steps = [] - data.steps?.each { - Map stepParameters = it.collectEntries { k,v -> [k as String, v] } - AbstractStep step = createStep(stepParameters) - if (step != null) { - steps.add(step) - } - } - } - steps - } - - protected AbstractStep createStep(Map stepParameters) { - StepRegistry.getStep(stepParameters.command?.toString(), this, stepParameters) - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/HelpCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/HelpCommand.groovy deleted file mode 100644 index 7608fbbbc3a..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/HelpCommand.groovy +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile.commands - -import grails.build.logging.GrailsConsole -import jline.console.completer.Completer -import org.grails.build.parsing.CommandLine -import org.grails.build.parsing.CommandLineParser -import org.grails.cli.profile.Command -import org.grails.cli.profile.CommandDescription -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileCommand -import org.grails.cli.profile.ProfileRepository -import org.grails.cli.profile.ProfileRepositoryAware -import org.grails.cli.profile.ProjectCommand -import org.grails.cli.profile.ProjectContext -import org.grails.cli.profile.ProjectContextAware - - -/** - * @author Graeme Rocher - */ -class HelpCommand implements ProfileCommand, Completer, ProjectContextAware, ProfileRepositoryAware{ - - public static final String NAME = "help" - - final CommandDescription description = new CommandDescription(NAME, "Prints help information for a specific command", "help [COMMAND NAME]") - - Profile profile - ProfileRepository profileRepository - ProjectContext projectContext - - CommandLineParser cliParser = new CommandLineParser() - - @Override - String getName() { - return NAME - } - - - @Override - boolean handle(ExecutionContext executionContext) { - def console = executionContext.console - def commandLine = executionContext.commandLine - Collection allCommands=findAllCommands() - String remainingArgs = commandLine.getRemainingArgsString() - if(remainingArgs?.trim()) { - CommandLine remainingArgsCommand = cliParser.parseString(remainingArgs) - String helpCommandName = remainingArgsCommand.getCommandName() - for (CommandDescription desc : allCommands) { - if(desc.name == helpCommandName) { - console.addStatus("Command: $desc.name") - console.addStatus("Description:") - console.println "${desc.description?:''}" - if(desc.usage) { - console.println() - console.addStatus("Usage:") - console.println "${desc.usage}" - } - if(desc.arguments) { - console.println() - console.addStatus("Arguments:") - for(arg in desc.arguments) { - console.println "* ${arg.name} - ${arg.description?:''} (${arg.required ? 'REQUIRED' : 'OPTIONAL'})" - } - } - if(desc.flags) { - console.println() - console.addStatus("Flags:") - for(arg in desc.flags) { - console.println "* ${arg.name} - ${arg.description ?: ''}" - } - } - return true - } - } - console.error "Help for command $helpCommandName not found" - return false - } else { - console.log ''' -Usage (optionals marked with *):' -grails [environment]* [target] [arguments]*' - -''' - console.addStatus("Examples:") - console.log('$ grails dev run-app') - console.log('$ grails create-app books') - console.log '' - console.addStatus('Available Commands (type grails help \'command-name\' for more info):') - console.addStatus("${'Command Name'.padRight(37)} Command Description") - console.println('-' * 100) - for (CommandDescription desc : allCommands) { - console.println "${desc.name.padRight(40)}${desc.description}" - } - console.println() - console.addStatus("Detailed usage with help [command]") - return true - } - - } - - @Override - int complete(String buffer, int cursor, List candidates) { - def allCommands = findAllCommands().collect() { CommandDescription desc -> desc.name } - - for(cmd in allCommands) { - if(buffer) { - if(cmd.startsWith(buffer)) { - candidates << cmd.substring(buffer.size()) - } - } - else { - candidates << cmd - } - } - return cursor - } - - - protected Collection findAllCommands() { - Iterable commands - if(profile) { - commands = profile.getCommands(projectContext) - } - else { - commands = CommandRegistry.findCommands(profileRepository).findAll() { Command cmd -> - !(cmd instanceof ProjectCommand) - } - } - return commands - .collect() { Command cmd -> cmd.description } - .unique() { CommandDescription cmd -> cmd.name } - .sort(false) { CommandDescription itDesc -> itDesc.name } - } - - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ListProfilesCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ListProfilesCommand.groovy deleted file mode 100644 index 98be06c5f62..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ListProfilesCommand.groovy +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands - -import grails.build.logging.GrailsConsole -import groovy.transform.CompileStatic -import org.grails.cli.profile.Command -import org.grails.cli.profile.CommandDescription -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileRepository -import org.grails.cli.profile.ProfileRepositoryAware - -/** - * Lists the available {@link org.grails.cli.profile.Profile} instances  - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class ListProfilesCommand implements Command, ProfileRepositoryAware { - - final String name = "list-profiles" - final CommandDescription description = new CommandDescription(name, "Lists the available profiles", "grails list-profiles") - - ProfileRepository profileRepository - - @Override - boolean handle(ExecutionContext executionContext) { - def allProfiles = profileRepository.allProfiles - def console = executionContext.console - console.addStatus("Available Profiles") - console.log('--------------------') - for(Profile p in allProfiles) { - console.log("* $p.name - ${p.description}") - } - - return true - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/OpenCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/OpenCommand.groovy deleted file mode 100644 index 78f6d492f31..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/OpenCommand.groovy +++ /dev/null @@ -1,72 +0,0 @@ -package org.grails.cli.profile.commands - -import groovy.transform.CompileStatic -import jline.console.completer.Completer -import jline.console.completer.FileNameCompleter -import org.grails.cli.profile.CommandDescription -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.ProjectCommand - -import java.awt.Desktop - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * @author graemerocher - */ -@CompileStatic -class OpenCommand implements ProjectCommand, Completer { - - public static final String NAME = "open" - - @Override - String getName() { - NAME - } - - CommandDescription description = new CommandDescription(NAME, "Opens a file in the project", "open [FILE PATH]") - - @Override - boolean handle(ExecutionContext executionContext) { - def filePath = executionContext.commandLine.remainingArgsString - if(filePath) { - if(filePath == 'test-report') { - filePath = 'build/reports/tests/index.html' - } - if(Desktop.isDesktopSupported()) { - try { - Desktop.desktop.open(new File(filePath)) - return true - } catch (e) { - executionContext.console.error("Error opening file $filePath: $e.message", e) - } - } - else { - executionContext.console.error("File opening not supported by JVM, use native OS command") - } - } - else { - return true - } - return false - } - - @Override - int complete(String buffer, int cursor, List candidates) { - return new FileNameCompleter().complete(buffer, cursor, candidates) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ProfileInfoCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ProfileInfoCommand.groovy deleted file mode 100644 index b97a7cc8ca5..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/ProfileInfoCommand.groovy +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile.commands - -import grails.build.logging.GrailsConsole -import grails.config.ConfigMap -import grails.util.BuildSettings -import groovy.transform.CompileStatic -import org.grails.cli.profile.Command -import org.grails.cli.profile.CommandDescription -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Feature -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileRepository -import org.grails.cli.profile.ProfileRepositoryAware -import org.grails.cli.profile.ProjectContext -import org.grails.config.CodeGenConfig - - -/** - * A command to find out information about the given profile - * - * @author Graeme Rocher - * @since 3.1 - */ -@CompileStatic -class ProfileInfoCommand extends ArgumentCompletingCommand implements ProfileRepositoryAware { - - public static final String NAME = 'profile-info' - - final String name = NAME - final CommandDescription description = new CommandDescription(name, "Display information about a given profile") - - ProfileRepository profileRepository - - ProfileInfoCommand() { - description.argument(name:"Profile Name", description: "The name or coordinates of the profile", required:true) - } - - void setProfileRepository(ProfileRepository profileRepository) { - this.profileRepository = profileRepository - } - - @Override - boolean handle(ExecutionContext executionContext) { - def console = executionContext.console - if(profileRepository == null) { - console.error("No profile repository provided") - return false - } - else { - - def profileName = executionContext.commandLine.remainingArgs[0] - - def profile = profileRepository.getProfile(profileName) - if(profile == null) { - console.error("Profile not found for name [$profileName]") - } - else { - console.log("Profile: ${profile.name}") - console.log('--------------------') - console.log(profile.description) - console.log('') - console.log('Provided Commands:') - console.log('--------------------') - Iterable commands = findCommands(profile, console).toUnique { Command c -> c.name} - - for(cmd in commands) { - def description = cmd.description - console.log("* ${description.name} - ${description.description}") - } - console.log('') - console.log('Provided Features:') - console.log('--------------------') - def features = profile.features - - for(feature in features) { - console.log("* ${feature.name} - ${feature.description}") - } - } - } - return true - } - - protected Iterable findCommands(Profile profile, GrailsConsole console) { - def commands = profile.getCommands(new ProjectContext() { - @Override - GrailsConsole getConsole() { - console - } - - @Override - File getBaseDir() { - return new File(".") - } - - @Override - ConfigMap getConfig() { - return new CodeGenConfig() - } - - @Override - String navigateConfig(String... path) { - return config.navigate(path) - } - - @Override - def T navigateConfigForType(Class requiredType, String... path) { - return (T) config.navigate(path) - } - }) - commands - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/events/CommandEvents.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/events/CommandEvents.groovy deleted file mode 100644 index de503b5e3f6..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/events/CommandEvents.groovy +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.events - -import groovy.transform.CompileStatic -import groovy.transform.Generated -import org.grails.cli.profile.commands.script.GroovyScriptCommand - - -/** - * Allows for listening and reacting to events triggered by other commands - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -trait CommandEvents { - - - /** - * Register to listen for an event - * - * @param eventName The name of the event - * @param callable The closure that is executed when the event is fired - */ - @Generated - void on(String eventName, @DelegatesTo(GroovyScriptCommand) Closure callable) { - EventStorage.registerEvent(eventName, callable) - } - - - /** - * Register to listen for an event that runs before the given command - * - * @param eventName The name of the event - * @param callable The closure that is executed when the event is fired - */ - @Generated - void before(String commandName, @DelegatesTo(GroovyScriptCommand) Closure callable) { - EventStorage.registerEvent("${commandName}Start", callable) - } - - /** - * Register to listen for an event that runs before the given command - * - * @param eventName The name of the event - * @param callable The closure that is executed when the event is fired - */ - @Generated - void after(String commandName, @DelegatesTo(GroovyScriptCommand) Closure callable) { - EventStorage.registerEvent("${commandName}End", callable) - } - - /** - * Notify of an event - * - * @param eventName The name of the event - * @param args The arguments to the event - */ - @Generated - void notify(String eventName, Object...args) { - EventStorage.fireEvent(this, eventName, args) - } - -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/events/EventStorage.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/events/EventStorage.groovy deleted file mode 100644 index a71146f5c29..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/events/EventStorage.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.events - -import groovy.transform.CompileStatic - - -/** - * Stores command line events - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class EventStorage { - - private static Map> eventListeners = [:].withDefault { [] } - - static void registerEvent(String eventName, Closure callable) { - if(!eventListeners[eventName].contains(callable)) { - eventListeners[eventName] << callable - } - } - - static void fireEvent(Object caller, String eventName, Object...args) { - def listeners = eventListeners[eventName] - for(listener in listeners) { - listener.delegate = caller - listener.call args - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ApplicationContextCommandFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ApplicationContextCommandFactory.groovy deleted file mode 100644 index 4f886d519b9..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ApplicationContextCommandFactory.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.factory - -import grails.build.logging.GrailsConsole -import grails.util.Named -import org.grails.cli.gradle.commands.GradleTaskCommandAdapter -import org.grails.cli.profile.Command -import org.grails.cli.profile.Profile - - - -/** - * Automatically populates ApplicationContext command instances and adapts the interface to the shell - * - * @author Graeme Rocher - * @since 3.0 - */ -class ApplicationContextCommandFactory implements CommandFactory { - @Override - Collection findCommands(Profile profile, boolean inherited) { - if(inherited) return Collections.emptyList() - - try { - def classLoader = Thread.currentThread().contextClassLoader - Class registry - try { - registry = classLoader.loadClass("grails.dev.commands.ApplicationContextCommandRegistry") - } catch (ClassNotFoundException cnf) { - return [] - } - def commands = registry.findCommands() - return commands.collect() { Named named -> new GradleTaskCommandAdapter(profile, named) } - } catch (Throwable e) { - GrailsConsole.instance.error("Error occurred loading commands: $e.message", e) - return [] - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ClasspathCommandResourceResolver.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ClasspathCommandResourceResolver.groovy deleted file mode 100644 index 4dfe4ed96ca..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ClasspathCommandResourceResolver.groovy +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.factory - -import groovy.transform.CompileStatic -import org.grails.cli.profile.Profile -import org.grails.io.support.PathMatchingResourcePatternResolver -import org.grails.io.support.Resource - - -/** - * A {@link CommandResourceResolver} that resolves commands from the classpath under the directory META-INF/commands - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class ClasspathCommandResourceResolver implements CommandResourceResolver { - final Collection matchingFileExtensions - ClassLoader classLoader - - private Collection resources = null - - ClasspathCommandResourceResolver(Collection matchingFileExtensions) { - this.matchingFileExtensions = matchingFileExtensions - } - - @Override - Collection findCommandResources(Profile profile) { - if(resources != null) return resources - def classLoader = classLoader ?: Thread.currentThread().contextClassLoader - PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(classLoader) - - try { - resources = [] - for(String ext in matchingFileExtensions) { - resources.addAll resourcePatternResolver.getResources("classpath*:META-INF/commands/*.$ext").toList() - } - return resources - } catch (Throwable e) { - return [] - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/CommandFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/CommandFactory.groovy deleted file mode 100644 index 2ad7d8e5570..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/CommandFactory.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package org.grails.cli.profile.commands.factory - -import org.grails.cli.profile.Command -import org.grails.cli.profile.Profile - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * Factory for the creation of {@link Command} instances - * - * @author Graeme Rocher - * @since 3.0 - */ -interface CommandFactory { - - /** - * Creates a command for the given name - * - * @param name The name of the command - * @param profile The {@link Profile} - * @param inherited Whether the profile passed is inherited (ie a parent profile) - * @return A command or null if it wasn't possible to create one - */ - Collection findCommands( Profile profile, boolean inherited ) - -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/CommandResourceResolver.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/CommandResourceResolver.groovy deleted file mode 100644 index 3c55bbd72b0..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/CommandResourceResolver.groovy +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.factory - -import org.grails.cli.profile.Profile -import org.grails.io.support.Resource - -/** - * @since 3.0 - * @author Graeme Rocher - */ -interface CommandResourceResolver { - - /** - * Finds {@link org.grails.cli.profile.Command} resources for the given profile - * - * @param profile The {@link Profile} instance - * @return A collection of {@link Resource} instances - */ - Collection findCommandResources(Profile profile) - - /** - * The pattern to match file names with - * - * @return A regex pattern - */ - Collection getMatchingFileExtensions() - -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/FileSystemCommandResourceResolver.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/FileSystemCommandResourceResolver.groovy deleted file mode 100644 index 904df2967a2..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/FileSystemCommandResourceResolver.groovy +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.factory - -import groovy.transform.CompileStatic -import org.grails.cli.profile.Profile -import org.grails.io.support.PathMatchingResourcePatternResolver -import org.grails.io.support.Resource -import org.grails.io.support.StaticResourceLoader - - -/** - * A {@link CommandResourceResolver} that resolves from the file system - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class FileSystemCommandResourceResolver implements CommandResourceResolver { - - final Collection matchingFileExtensions - - FileSystemCommandResourceResolver(Collection matchingFileExtensions) { - this.matchingFileExtensions = matchingFileExtensions - } - - @Override - Collection findCommandResources(Profile profile) { - Resource commandsDir = getCommandsDirectory(profile) - PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(new StaticResourceLoader(commandsDir)) - if(commandsDir.exists()) { - Collection commandFiles = [] - for(ext in matchingFileExtensions) { - commandFiles.addAll resolver.getResources("*.$ext") - } - commandFiles = commandFiles.sort(false) { Resource file -> file.filename } - return commandFiles - } - return [] - } - - protected Resource getCommandsDirectory(Profile profile) { - profile.profileDir.createRelative("commands/") - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/GroovyScriptCommandFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/GroovyScriptCommandFactory.groovy deleted file mode 100644 index 1b9aba68469..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/GroovyScriptCommandFactory.groovy +++ /dev/null @@ -1,88 +0,0 @@ -package org.grails.cli.profile.commands.factory - -import grails.build.logging.GrailsConsole -import grails.util.GrailsNameUtils -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import org.codehaus.groovy.control.CompilerConfiguration -import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer -import org.codehaus.groovy.control.customizers.ImportCustomizer -import org.grails.cli.profile.Command -import org.grails.cli.profile.Profile -import org.grails.cli.profile.commands.script.GroovyScriptCommand -import org.grails.cli.profile.commands.script.GroovyScriptCommandTransform -import org.grails.io.support.Resource - -import java.nio.charset.StandardCharsets - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * A {@link CommandFactory} that creates {@link Command} instances from Groovy scripts - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class GroovyScriptCommandFactory extends ResourceResolvingCommandFactory { - - final Collection matchingFileExtensions = ["groovy"] - final String fileNamePattern = /^.*\.(groovy)$/ - - @Override - protected GroovyScriptCommand readCommandFile(Resource resource) { - GroovyClassLoader classLoader = createGroovyScriptCommandClassLoader() - try { - return (GroovyScriptCommand) classLoader.parseClass(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8 ), resource.filename).newInstance() - } catch (Throwable e) { - GrailsConsole.getInstance().error("Failed to compile ${resource.filename}: " + e.getMessage(), e) - } - } - - @CompileDynamic - public static GroovyClassLoader createGroovyScriptCommandClassLoader() { - def configuration = new CompilerConfiguration() - // TODO: Report bug, this fails with @CompileStatic with a ClassCastException - String baseClassName = GroovyScriptCommand.class.getName() - return createClassLoaderForBaseClass(configuration, baseClassName) - } - - private static GroovyClassLoader createClassLoaderForBaseClass(CompilerConfiguration configuration, String baseClassName) { - configuration.setScriptBaseClass(baseClassName) - - - def importCustomizer = new ImportCustomizer() - importCustomizer.addStarImports("org.grails.cli.interactive.completers") - importCustomizer.addStarImports("grails.util") - importCustomizer.addStarImports("grails.codegen.model") - configuration.addCompilationCustomizers(importCustomizer,new ASTTransformationCustomizer(new GroovyScriptCommandTransform())) - def classLoader = new GroovyClassLoader(Thread.currentThread().contextClassLoader, configuration) - return classLoader - } - - @Override - protected String evaluateFileName(String fileName) { - def fn = super.evaluateFileName(fileName) - return fn.contains('-') ? fn.toLowerCase() : GrailsNameUtils.getScriptName(fn) - } - - @Override - protected Command createCommand(Profile profile, String commandName, Resource resource, GroovyScriptCommand data) { - data.setProfile(profile) - return data - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ResourceResolvingCommandFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ResourceResolvingCommandFactory.groovy deleted file mode 100644 index 71932e0958a..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ResourceResolvingCommandFactory.groovy +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.factory - -import grails.util.BuildSettings -import groovy.transform.CompileStatic -import org.grails.cli.profile.Command -import org.grails.cli.profile.Profile -import org.grails.io.support.FileSystemResource -import org.grails.io.support.Resource - -import java.util.regex.Pattern - - -/** - * A abstract {@link CommandFactory} that reads from the file system - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -abstract class ResourceResolvingCommandFactory implements CommandFactory { - - @Override - Collection findCommands(Profile profile, boolean inherited) { - def resources = findCommandResources(profile, inherited) - Collection commands = [] - for(Resource resource in resources) { - String commandName = evaluateFileName(resource.filename) - def data = readCommandFile(resource) - - def command = createCommand(profile, commandName, resource, data) - if(command) - commands << command - } - return commands - } - - protected String evaluateFileName(String fileName) { - fileName - Pattern.compile(/\.(${getMatchingFileExtensions().join('|')})$/) - } - - protected Collection findCommandResources(Profile profile, boolean inherited) { - Collection allResources = [] - for(CommandResourceResolver resolver in getCommandResolvers(inherited)) { - allResources.addAll resolver.findCommandResources(profile) - } - return allResources - } - - protected Collection getCommandResolvers(boolean inherited) { - def profileCommandsResolver = new FileSystemCommandResourceResolver(matchingFileExtensions) - Collection commandResolvers = [] - if(inherited) { - commandResolvers.add(profileCommandsResolver) - return commandResolvers - } - else { - def localCommandsResolver1 = new FileSystemCommandResourceResolver(matchingFileExtensions) { - @Override - protected Resource getCommandsDirectory(Profile profile) { - return new FileSystemResource("${BuildSettings.BASE_DIR}/src/main/scripts/" ) - } - } - def localCommandsResolver2 = new FileSystemCommandResourceResolver(matchingFileExtensions) { - @Override - protected Resource getCommandsDirectory(Profile profile) { - return new FileSystemResource("${BuildSettings.BASE_DIR}/commands/" ) - } - } - commandResolvers.addAll([profileCommandsResolver, localCommandsResolver1, localCommandsResolver2, new ClasspathCommandResourceResolver(matchingFileExtensions) ]) - return commandResolvers - } - } - - protected abstract T readCommandFile(Resource resource) - - protected abstract Command createCommand(Profile profile, String commandName, Resource resource, T data) - - protected abstract Collection getMatchingFileExtensions() - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ServiceCommandFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ServiceCommandFactory.groovy deleted file mode 100644 index a1a4441696b..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/ServiceCommandFactory.groovy +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.factory - -import groovy.transform.CompileStatic -import org.grails.cli.profile.Command -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileCommand - - - -/** - * Uses the service registry pattern to locate commands - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class ServiceCommandFactory implements CommandFactory { - @Override - Collection findCommands(Profile profile, boolean inherited) { - if(inherited) return Collections.emptyList() - ServiceLoader.load(Command).findAll() { Command cmd -> - cmd instanceof ProfileCommand - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/YamlCommandFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/YamlCommandFactory.groovy deleted file mode 100644 index 02a71a73e20..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/factory/YamlCommandFactory.groovy +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.factory - -import groovy.json.JsonParserType -import groovy.json.JsonSlurper -import groovy.transform.CompileStatic -import org.grails.cli.profile.Command -import org.grails.cli.profile.Profile -import org.grails.cli.profile.commands.DefaultMultiStepCommand -import org.grails.io.support.Resource -import org.yaml.snakeyaml.LoaderOptions -import org.yaml.snakeyaml.Yaml -import org.yaml.snakeyaml.constructor.SafeConstructor - -import java.util.regex.Pattern - - -/** - * A {@link CommandFactory} that can discover commands defined in YAML or JSON - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class YamlCommandFactory extends ResourceResolvingCommandFactory { - protected Yaml yamlParser=new Yaml(new SafeConstructor(new LoaderOptions())) - // LAX parser for JSON: http://mrhaki.blogspot.ie/2014/08/groovy-goodness-relax-groovy-will-parse.html - protected JsonSlurper jsonSlurper = new JsonSlurper().setType(JsonParserType.LAX) - - final Collection matchingFileExtensions = ["yml", "json"] - final String fileNamePattern = /^.*\.(yml|json)$/ - - @Override - protected Map readCommandFile(Resource resource) { - Map data - InputStream is - - try { - is = resource.inputStream - if(resource.filename.endsWith('.json')) { - data = jsonSlurper.parse(is, "UTF-8") as Map - } else { - data = yamlParser.load(is) - } - } finally { - is?.close() - } - return data - } - - protected Command createCommand(Profile profile, String commandName, Resource resource, Map data) { - if(!data.profile || profile.name == data.profile?.toString()) { - Command command = new DefaultMultiStepCommand( commandName, profile, data ) - Object minArguments = data?.minArguments - command.minArguments = minArguments instanceof Integer ? (Integer)minArguments : 1 - return command - } - return null - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/FileSystemInteraction.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/FileSystemInteraction.groovy deleted file mode 100644 index 0dca30817c9..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/FileSystemInteraction.groovy +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.io - -import org.grails.io.support.Resource - - -/** - * Utility methods exposed to scripts for interacting with resources (found on the file system or jars) and the file system - * - * @author Graeme Rocher - * @since 3.0 - */ -interface FileSystemInteraction { - - /** - * Makes a directory - * - * @param path The path to the directory - */ - FileSystemInteraction mkdir(path) - /** - * Deletes a file - * - * @param path The path to the file - */ - FileSystemInteraction delete(path) - /** - * Allows Gradle style simple copy specs - * - * @param callable The callable - * @return this - */ - FileSystemInteraction copy(@DelegatesTo(CopySpec) Closure callable) - /** - * Copies a resource to the target destination - * - * @param path The path - * @param destination The destination - */ - FileSystemInteraction copy(path, destination) - /** - * Copies resources to the target destination - * - * @param path The path - * @param destination The destination - */ - FileSystemInteraction copyAll(Iterable resources, destination) - /** - * Copy a Resource from the given location to the given directory or location - * - * @param from The resource to copy - * @param to The location to copy to - * @return The {@FileSystemInteraction} instance - */ - FileSystemInteraction copy(Resource from, File to) - /** - * Obtain a file for the given path - * - * @param path The path - * @return The file - */ - File file(Object path) - /** - * @return The target build directory - */ - File getBuildDir() - /** - * @return The directory where resources are processed to - */ - File getResourcesDir() - /** - * @return The directory where classes are compiled to - */ - File getClassesDir() - /** - * Finds a source file for the given class name - * @param className The class name - * @return The source resource - */ - Resource source(String className) - /** - * Obtain a resource for the given path - * @param path The path - * @return The resource - */ - Resource resource(Object path) - /** - * Obtain resources for the given pattern - * - * @param pattern The pattern - * @return The resources - */ - Collection resources(String pattern) - /** - * Obtain the path of the resource relative to the current project - * - * @param path The path to inspect - * @return The relative path - */ - String projectPath(Object path) - - /** - * The class name of the given resource - * - * @param resource The resource - * @return The class name - */ - String className(Resource resource) - - /** - * Get files matching the given pattern - * - * @param pattern The pattern - * @return the files - */ - Collection files(String pattern) - - static class CopySpec { - def from - def into - void from(path) { - this.from = path - } - void into(path) { - this.into = path - } - } -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/FileSystemInteractionImpl.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/FileSystemInteractionImpl.groovy deleted file mode 100644 index f1a11948e2f..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/FileSystemInteractionImpl.groovy +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.io - -import grails.build.logging.GrailsConsole -import grails.util.BuildSettings -import groovy.transform.CompileStatic -import org.grails.cli.profile.ExecutionContext -import org.grails.io.support.DefaultResourceLoader -import org.grails.io.support.FileSystemResource -import org.grails.io.support.GrailsResourceUtils -import org.grails.io.support.PathMatchingResourcePatternResolver -import org.grails.io.support.Resource -import org.grails.io.support.ResourceLoader -import org.grails.io.support.ResourceLocator -import org.grails.io.support.SpringIOUtils - - -/** - * Utility methods exposed to scripts for interacting with resources (found on the file system or jars) and the file system - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class FileSystemInteractionImpl implements FileSystemInteraction { - - ExecutionContext executionContext - ResourceLoader resourceLoader - PathMatchingResourcePatternResolver resourcePatternResolver - ResourceLocator resourceLocator - - FileSystemInteractionImpl(ExecutionContext executionContext, ResourceLoader resourceLoader = new DefaultResourceLoader()) { - this.executionContext = executionContext - this.resourceLoader = resourceLoader - this.resourceLocator = new ResourceLocator() - this.resourceLocator.setSearchLocation(executionContext.baseDir.absolutePath) - this.resourcePatternResolver = new PathMatchingResourcePatternResolver(resourceLoader) - } - - - /** - * Makes a directory - * - * @param path The path to the directory - */ - @Override - FileSystemInteractionImpl mkdir(path) { - file(path)?.mkdirs() - return this - } - - /** - * Deletes a file - * - * @param path The path to the file - */ - @Override - FileSystemInteractionImpl delete(path) { - file(path)?.delete() - return this - } - - /** - * Allows Gradle style simple copy specs - * - * @param callable The callable - * @return this - */ - @Override - FileSystemInteractionImpl copy(@DelegatesTo(FileSystemInteraction.CopySpec) Closure callable) { - FileSystemInteraction.CopySpec spec = new FileSystemInteraction.CopySpec() - callable.delegate = spec - callable.call() - if(spec.from && spec.into) { - if(spec.from instanceof Iterable) { - copyAll((Iterable)spec.from, spec.into) - } - else { - copy(spec.from, spec.into) - } - } - return this - } - /** - * Copies a resource to the target destination - * - * @param path The path - * @param destination The destination - */ - @Override - FileSystemInteractionImpl copy(path, destination) { - def from = resource(path) - def to = file(destination) - copy(from, to) - return this - } - - /** - * Copies resources to the target destination - * - * @param path The path - * @param destination The destination - */ - @Override - FileSystemInteractionImpl copyAll(Iterable resources, destination) { - mkdir(destination) - for(path in resources) { - def from = resource(path) - def to = file(destination) - copy(from, to) - } - return this - } - - /** - * Copy a Resource from the given location to the given directory or location - * - * @param from The resource to copy - * @param to The location to copy to - * @return The {@FileSystemInteraction} instance - */ - @Override - FileSystemInteractionImpl copy(Resource from, File to) { - if(!to?.exists()) mkdir(to) - if (from && to) { - if (to.isDirectory()) { - mkdir(to) - to = new File(to, from.filename) - } - SpringIOUtils.copy(from, to) - GrailsConsole.instance.addStatus("Copied ${from.filename} to location ${to.canonicalPath}") - } - return this - } - - /** - * Obtain a file for the given path - * - * @param path The path - * @return The file - */ - @Override - File file(Object path) { - if(path instanceof File) return (File)path - else if(path instanceof Resource) return ((Resource)path).file - else { - def baseDir = executionContext.baseDir - new File(baseDir ?: new File("."), path.toString()) - } - } - - /** - * @return The target build directory - */ - @Override - File getBuildDir() { - BuildSettings.TARGET_DIR - } - - /** - * @return The directory where resources are processed to - */ - @Override - File getResourcesDir() { - BuildSettings.RESOURCES_DIR - } - - /** - * @return The directory where classes are compiled to - */ - @Override - File getClassesDir() { - BuildSettings.CLASSES_DIR - } - - /** - * Finds a source file for the given class name - * @param className The class name - * @return The source resource - */ - @Override - Resource source(String className) { - resourceLocator.findResourceForClassName(className) - } - - /** - * The class name of the given resource - * - * @param resource The resource - * @return The class name - */ - String className(Resource resource) { - GrailsResourceUtils.getClassName(resource) - } - - /** - * Obtain a resource for the given path - * @param path The path - * @return The resource - */ - @Override - Resource resource(Object path) { - if(!path) return null - if(path instanceof Resource) return (Resource)path - def f = file(path) - if(f?.exists() && f.isFile()) { - return new FileSystemResource(f) - } - else { - def pathStr = path.toString() - def resource = resourceLoader.getResource(pathStr) - if(resource.exists()) { - return resource - } - else { - def allResources = resources(pathStr) - if(allResources) { - return allResources[0] - } - else { - return resource - } - } - } - } - - /** - * Obtain resources for the given pattern - * - * @param pattern The pattern - * @return The resources - */ - @Override - Collection resources(String pattern) { - try { - return resourcePatternResolver.getResources(pattern).toList() - } catch (e) { - return [] - } - } - - /** - * Obtain the path of the resource relative to the current project - * - * @param path The path to inspect - * @return The relative path - */ - @Override - String projectPath(Object path) { - def file = file(path) - if(file) { - def basePath = executionContext.baseDir.canonicalPath - return (file.canonicalPath - basePath).substring(1) - } - return "" - } - - /** - * Get files matching the given pattern - * - * @param pattern The pattern - * @return the files - */ - @Override - Collection files(String pattern) { - resources(pattern).collect() { Resource res -> res.file } - } - - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/GradleDependency.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/GradleDependency.groovy deleted file mode 100644 index 6b5a1987035..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/GradleDependency.groovy +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2017-2020 original 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 - * - * 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.grails.cli.profile.commands.io - -import org.eclipse.aether.graph.Dependency - -class GradleDependency { - - static final Map SCOPE_MAP = [ - compile: 'implementation', - runtime: 'runtimeOnly', - testRuntime: 'testRuntimeOnly', - testCompile: 'testImplementation', -// provided: 'developmentOnly' - ] - - private String scope - private String dependency - - GradleDependency(String scope, String dependency) { - this.scope = scope - this.dependency = dependency - } - - GradleDependency(Dependency dependency) { -// this(dependency.scope, dependency) - this(SCOPE_MAP.get(dependency.scope) ?: dependency.scope, dependency) - } - - GradleDependency(String scope, Dependency dependency) { - this.scope = scope - def artifact = dependency.artifact - def v = artifact.version.replace('BOM', '') - StringBuilder artifactString = new StringBuilder() - if (dependency.exclusions != null && !dependency.exclusions.empty) { - artifactString.append('(') - } else { - artifactString.append(' ') - } - artifactString.append('"') - artifactString.append(artifact.groupId) - artifactString.append(':').append(artifact.artifactId) - if (v) { - artifactString.append(':').append(v) - } - artifactString.append('"') - - def ln = System.getProperty("line.separator") - - if (dependency.exclusions != null && !dependency.exclusions.empty) { - artifactString.append(") {").append(ln) - for (e in dependency.exclusions) { - artifactString.append(" ") - .append("exclude") - - artifactString.append(" group: ").append('"').append(e.groupId).append('",') - artifactString.append(" module: ").append('"').append(e.artifactId).append('"') - - artifactString.append(ln) - } - artifactString.append("}") - } - this.dependency = artifactString.toString() - } - - String toString(int spaces) { - (scope + dependency).replaceAll('(?m)^', ' ' * spaces) - } - - String getScope() { - scope - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/ServerInteraction.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/ServerInteraction.groovy deleted file mode 100644 index ab8a50828a6..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/io/ServerInteraction.groovy +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile.commands.io - -import groovy.transform.CompileStatic - - -/** - * Methods to aid interacting with the server from the CLI - * - * @author Graeme Rocher - * @since 3.0.3 - */ -@CompileStatic -trait ServerInteraction { - - /** - * Waits for the server to startup - * - * @param host The host - * @param port The port - */ - void waitForStartup(String host = "localhost", int port = 8080) { - while(!isServerAvailable(host, port)) { - sleep 100 - } - try { - new URL("http://${host ?: 'localhost'}:${port ?: 8080}/is-tomcat-running").text - } catch(ignored) { - // ignore - } - } - - /** - * Returns true if the server is available - * - * @param host The host - * @param port The port - */ - boolean isServerAvailable(String host = "localhost", int port = 8080) { - try { - new Socket(host, port) - return true - } catch (e) { - return false - } - } -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/script/GroovyScriptCommand.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/script/GroovyScriptCommand.groovy deleted file mode 100644 index c39b3d22030..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/script/GroovyScriptCommand.groovy +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.script - -import grails.build.logging.ConsoleLogger -import grails.build.logging.GrailsConsole -import grails.codegen.model.ModelBuilder -import grails.util.Environment -import grails.util.GrailsNameUtils -import groovy.ant.AntBuilder -import groovy.transform.CompileStatic -import org.grails.build.logging.GrailsConsoleAntBuilder -import org.grails.cli.GrailsCli -import org.grails.cli.boot.SpringInvoker -import org.grails.cli.gradle.GradleInvoker -import org.grails.cli.profile.CommandArgument -import org.grails.cli.profile.CommandDescription -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileCommand -import org.grails.cli.profile.ProfileRepository -import org.grails.cli.profile.ProfileRepositoryAware -import org.grails.cli.profile.commands.events.CommandEvents -import org.grails.cli.profile.commands.io.FileSystemInteraction -import org.grails.cli.profile.commands.io.FileSystemInteractionImpl -import org.grails.cli.profile.commands.io.ServerInteraction -import org.grails.cli.profile.commands.templates.TemplateRenderer -import org.grails.cli.profile.commands.templates.TemplateRendererImpl - -/** - * A base class for Groovy scripts that implement commands - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -abstract class GroovyScriptCommand extends Script implements ProfileCommand, ProfileRepositoryAware, ConsoleLogger, ModelBuilder, FileSystemInteraction, TemplateRenderer, CommandEvents, ServerInteraction { - - Profile profile - ProfileRepository profileRepository - String name = getClass().name.contains('-') ? getClass().name : GrailsNameUtils.getScriptName(getClass().name) - CommandDescription description = new CommandDescription(name) - @Delegate ExecutionContext executionContext - @Delegate TemplateRenderer templateRenderer - @Delegate ConsoleLogger consoleLogger = GrailsConsole.getInstance() - @Delegate FileSystemInteraction fileSystemInteraction - - /** - * Allows invoking of Gradle commands - */ - GradleInvoker gradle - /** - * Allows invoking of Spring Boot's CLI - */ - SpringInvoker spring = SpringInvoker.getInstance() - /** - * Access to Ant via AntBuilder - */ - AntBuilder ant = new GrailsConsoleAntBuilder() - - /** - * The location of the user.home directory - */ - String userHome = System.getProperty('user.home') - /** - * The version of Grails being used - */ - String grailsVersion = getClass().getPackage()?.getImplementationVersion() - - /** - * Provides a description for the command - * - * @param desc The description - * @param usage The usage information - */ - void description(String desc, String usage) { - // ignore, just a stub for documentation purposes, populated by CommandScriptTransform - } - - /** - * Provides a description for the command - * - * @param desc The description - * @param usage The usage information - */ - void description(String desc, Closure detail) { - // ignore, just a stub for documentation purposes, populated by CommandScriptTransform - } - - /** - * Obtains details of the given flag if it has been set by the user - * - * @param name The name of the flag - * @return The flag information, or null if it isn't set by the user - */ - def flag(String name) { - if(commandLine.hasOption(name)) { - return commandLine.optionValue(name) - } - else { - def value = commandLine?.undeclaredOptions?.get(name) - return value ?: null - } - } - - /** - * @return The undeclared command line arguments - */ - Map getArgsMap() { - executionContext.commandLine.undeclaredOptions - } - - /** - * @return The arguments as a list of strings - */ - List getArgs() { - executionContext.commandLine.remainingArgs - } - - /** - * @return The name of the current Grails environment - */ - String getGrailsEnv() { Environment.current.name } - - /** - * @return The {@link GrailsConsole} instance - */ - GrailsConsole getGrailsConsole() { executionContext.console } - - /** - * Implementation of the handle method that runs the script - * - * @param executionContext The ExecutionContext - * @return True if the script succeeds, false otherwise - */ - @Override - boolean handle(ExecutionContext executionContext) { - setExecutionContext(executionContext) - notify("${name}Start", executionContext) - def result = run() - notify("${name}End", executionContext) - if(result instanceof Boolean) { - return ((Boolean)result) - } - return true - } - - /** - * Method missing handler used to invoke other commands from a command script - * - * @param name The name of the command as a method name (for example 'run-app' would be runApp()) - * @param args The arguments to the command - */ - def methodMissing(String name, args) { - Object[] argsArray = (Object[])args - def commandName = GrailsNameUtils.getScriptName(name) - def context = executionContext - if(profile?.hasCommand(context, commandName )) { - def commandLine = context.commandLine - def newArgs = [commandName] - newArgs.addAll argsArray.collect() { it.toString() } - def newContext = new GrailsCli.ExecutionContextImpl(commandLine.parseNew(newArgs as String[]), context) - return profile.handleCommand(newContext) - } - else { - throw new MissingMethodException(name, getClass(), argsArray) - } - } - - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext - this.consoleLogger = executionContext.console - this.templateRenderer = new TemplateRendererImpl(executionContext, profile, profileRepository) - this.fileSystemInteraction = new FileSystemInteractionImpl(executionContext) - this.gradle = new GradleInvoker(executionContext) - setDefaultPackage( executionContext.navigateConfig('grails', 'codegen', 'defaultPackage') ) - } - - ExecutionContext getExecutionContext() { - return executionContext - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/script/GroovyScriptCommandTransform.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/script/GroovyScriptCommandTransform.groovy deleted file mode 100644 index df7ccd300da..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/script/GroovyScriptCommandTransform.groovy +++ /dev/null @@ -1,138 +0,0 @@ -package org.grails.cli.profile.commands.script -import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* -import org.codehaus.groovy.ast.expr.* -import org.codehaus.groovy.ast.stmt.BlockStatement -import org.codehaus.groovy.ast.stmt.ExpressionStatement -import org.codehaus.groovy.ast.stmt.Statement -import org.codehaus.groovy.control.CompilePhase -import org.codehaus.groovy.control.SourceUnit -import org.codehaus.groovy.transform.ASTTransformation -import org.codehaus.groovy.transform.GroovyASTTransformation -import org.grails.cli.profile.CommandDescription - -import java.lang.reflect.Modifier -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * Transformation applied to command scripts - * - * @author Graeme Rocher - * @since 3.0 - */ -@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) -@CompileStatic -class GroovyScriptCommandTransform implements ASTTransformation { - @Override - void visit(ASTNode[] nodes, SourceUnit source) { - for(ClassNode cNode in source.AST.classes) { - if(cNode.superClass.name == "org.grails.cli.profile.commands.script.GroovyScriptCommand") - new CommandScriptTransformer(source, cNode).visitClass(cNode) - } - } - - static class CommandScriptTransformer extends ClassCodeVisitorSupport { - SourceUnit sourceUnit - ClassNode classNode - - CommandScriptTransformer(SourceUnit sourceUnit, ClassNode classNode) { - this.sourceUnit = sourceUnit - this.classNode = classNode - } - - @Override - void visitMethodCallExpression(MethodCallExpression call) { - if(call.methodAsString == 'description' && (call.arguments instanceof ArgumentListExpression)) { - def constructorBody = new BlockStatement() - def defaultConstructor = getDefaultConstructor(classNode) - if(defaultConstructor == null) { - defaultConstructor = new ConstructorNode(Modifier.PUBLIC, constructorBody) - classNode.addConstructor(defaultConstructor) - } - else { - constructorBody.addStatement(defaultConstructor.getCode()) - defaultConstructor.setCode(constructorBody) - } - - - ArgumentListExpression existing = (ArgumentListExpression) call.arguments - - def arguments = existing.expressions - if(arguments.size() == 2) { - def constructorArgs = new ArgumentListExpression() - constructorArgs.addExpression(new VariableExpression("name")) - def secondArg = arguments.get(1) - Expression constructDescription = new ConstructorCallExpression(ClassHelper.make(CommandDescription), constructorArgs) - if(secondArg instanceof ClosureExpression) { - constructorArgs.addExpression(arguments.get(0)) - ClosureExpression closureExpression = (ClosureExpression)secondArg - def body = closureExpression.code - if(body instanceof BlockStatement) { - BlockStatement bodyBlock = (BlockStatement)body - for(Statement s in bodyBlock.statements) { - if(s instanceof ExpressionStatement) { - ExpressionStatement es = (ExpressionStatement)s - - def expr = es.expression - if(expr instanceof MethodCallExpression) { - MethodCallExpression mce = (MethodCallExpression)expr - def methodCallArgs = mce.getArguments() - - switch(mce.methodAsString) { - case 'usage': - if(methodCallArgs instanceof ArgumentListExpression) { - constructorArgs.addExpression( ((ArgumentListExpression)methodCallArgs).getExpression(0)) - } - - break - default: - constructDescription = new MethodCallExpression(constructDescription, mce.methodAsString, methodCallArgs) - break - - } - } - } - } - } - - } - else { - constructorArgs.expressions.addAll(arguments) - } - - def assignDescription = new MethodCallExpression(new VariableExpression("this"),"setDescription", constructDescription) - constructorBody.addStatement(new ExpressionStatement(assignDescription)) - } - - - } - else { - super.visitMethodCallExpression(call) - } - } - } - - public static ConstructorNode getDefaultConstructor(ClassNode classNode) { - for (ConstructorNode cons in classNode.getDeclaredConstructors()) { - if (cons.getParameters().length == 0) { - return cons - } - } - return null - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/SimpleTemplate.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/SimpleTemplate.groovy deleted file mode 100644 index 3f8b136d564..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/SimpleTemplate.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.cli.profile.commands.templates - -import groovy.transform.CompileStatic -import groovy.transform.Immutable - -@CompileStatic -@Immutable -class SimpleTemplate { - String template - - public String render(Map variables) { - String result = template?:'' - variables.each { k, v -> - result = result.replace("@${k}@".toString(), v?:'') - } - result - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateException.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateException.groovy deleted file mode 100644 index aa439817c67..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateException.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.templates - -import groovy.transform.InheritConstructors - - -/** - * Exception thrown when an error in template rendering occurs - * - * @author Graeme Rocher - * @since 3.0 - */ -@InheritConstructors -class TemplateException extends RuntimeException { -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateRenderer.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateRenderer.groovy deleted file mode 100644 index 2addb6da86c..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateRenderer.groovy +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.templates - -import grails.codegen.model.Model -import groovy.transform.CompileDynamic -import org.grails.io.support.Resource - - - -/** - * API for locating and rendering templates in the code generation layer - * - * @author Graeme Rocher - * @since 3.0 - */ -interface TemplateRenderer { - - /** - * Render with the given named arguments - * - * @param namedArguments The named arguments are 'template', 'destination' and 'model' - */ - @CompileDynamic - void render(Map namedArguments) - /** - * Render the given template to the give destination for the given model - * - * @param template The contents template - * @param destination The destination - * @param model The model - */ - void render(CharSequence template, File destination, Model model) - - /** - * Render the given template to the given destination - * - * @param template The contents of the template - * @param destination The destination - * @param model The model - */ - void render(CharSequence template, File destination ) - - /** - * Render the given template to the given destination - * - * @param template The contents of the template - * @param destination The destination - * @param model The model - */ - void render(CharSequence template, File destination, Map model ) - /** - * Render the given template to the given destination - * - * @param template The contents of the template - * @param destination The destination - * @param model The model - */ - void render(CharSequence template, File destination, Map model, boolean overwrite) - - /** - * Render the given template to the give destination for the given model - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(File template, File destination, Model model) - - /** - * Render the given template to the given destination - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(File template, File destination) - - /** - * Render the given template to the given destination - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(File template, File destination, Map model ) - - /** - * Render the given template to the given destination - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(File template, File destination, Map model , boolean overwrite) - - /** - * Render the given template to the give destination for the given model - * - * @param template The contents template - * @param destination The destination - * @param model The model - */ - void render(Resource template, File destination, Model model) - - - /** - * Render the given template to the give destination for the given model - * - * @param template The contents template - * @param destination The destination - * @param model The model - */ - void render(Resource template, File destination, Model model, boolean overwrite) - - /** - * Render the given template to the given destination - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(Resource template, File destination) - - /** - * Render the given template to the given destination - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(Resource template, File destination, Map model) - - /** - * Render the given template to the given destination - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(Resource template, File destination, Map model, boolean overwrite) - - /** - * Find templates matching the given pattern - * - * @param pattern The pattern - * @return The available templates - */ - Iterable templates(String pattern) - - /** - * Find a template at the given location - * - * @param location The location - * @return The resource or null if it doesn't exist - */ - Resource template(Object location) -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateRendererImpl.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateRendererImpl.groovy deleted file mode 100644 index 7f74d5fabd9..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/commands/templates/TemplateRendererImpl.groovy +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands.templates - -import grails.codegen.model.Model -import groovy.text.GStringTemplateEngine -import groovy.text.Template -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import org.grails.cli.interactive.completers.ClassNameCompleter -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileRepository -import org.grails.cli.profile.ProfileRepositoryAware -import org.grails.cli.profile.commands.io.FileSystemInteraction -import org.grails.cli.profile.commands.io.FileSystemInteractionImpl -import org.grails.io.support.DefaultResourceLoader -import org.grails.io.support.Resource -import org.grails.io.support.ResourceLoader - - -/** - * Interface for classes that can render templates - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class TemplateRendererImpl implements TemplateRenderer, ProfileRepositoryAware { - - ExecutionContext executionContext - Profile profile - ProfileRepository profileRepository - @Delegate FileSystemInteraction fileSystemInteraction - private Map templateCache = [:] - - TemplateRendererImpl(ExecutionContext executionContext, ProfileRepository profileRepository, ResourceLoader resourceLoader = new DefaultResourceLoader()) { - this.executionContext = executionContext - this.profileRepository = profileRepository - this.profile = profile - this.fileSystemInteraction = new FileSystemInteractionImpl(executionContext, resourceLoader) - } - - TemplateRendererImpl(ExecutionContext executionContext, Profile profile, ProfileRepository profileRepository, ResourceLoader resourceLoader = new DefaultResourceLoader()) { - this.executionContext = executionContext - this.profile = profile - this.profileRepository = profileRepository - this.fileSystemInteraction = new FileSystemInteractionImpl(executionContext, resourceLoader) - } - - /** - * Render with the given named arguments - * - * @param namedArguments The named arguments are 'template', 'destination' and 'model' - */ - @Override - @CompileDynamic - void render(Map namedArguments) { - if(namedArguments?.template && namedArguments?.destination) { - def templateArg = namedArguments.template - def template = templateArg instanceof Resource ? templateArg : template(templateArg) - boolean overwrite = namedArguments.overwrite as Boolean ?: false - render template, file(namedArguments.destination), namedArguments.model ?: [:], overwrite - } - } - - /** - * Render the given template to the give destination for the given model - * - * @param template The contents template - * @param destination The destination - * @param model The model - */ - @Override - void render(CharSequence template, File destination, Model model) { - render(template, destination, model.asMap()) - } - - /** - * Render the given template to the given destination - * - * @param template The contents of the template - * @param destination The destination - * @param model The model - */ - void render(CharSequence template, File destination, Map model = Collections.emptyMap(), boolean overwrite = false) { - if(template && destination) { - if(destination.exists() && !overwrite) { - executionContext.console.warn("Destination file ${projectPath( destination )} already exists, skipping...") - } - else { - def templateEngine = new GStringTemplateEngine() - try { - def t = templateEngine.createTemplate(template.toString()) - writeTemplateToDestination(t, model, destination) - } catch (e) { - destination.delete() - throw new TemplateException("Error rendering template to destination ${projectPath( destination )}: ${e.message}", e) - } - } - } - } - - - - /** - * Render the given template to the give destination for the given model - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(File template, File destination, Model model) { - render(template, destination, model.asMap()) - } - /** - * Render the given template to the given destination - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(File template, File destination, Map model = Collections.emptyMap(), boolean overwrite = false) { - if(template && destination) { - if(destination.exists() && !overwrite) { - executionContext.console.warn("Destination file ${projectPath( destination )} already exists, skipping...") - } - else { - Template t = templateCache[template.absolutePath] - if(t == null) { - try { - def templateEngine = new GStringTemplateEngine() - t = templateEngine.createTemplate(template) - } catch (e) { - throw new TemplateException("Error rendering template [$template] to destination ${projectPath( destination )}: ${e.message}", e) - } - } - try { - writeTemplateToDestination(t, model, destination) - executionContext.console.addStatus("Rendered template ${template.name} to destination ${projectPath( destination )}") - } catch (Throwable e) { - destination.delete() - throw new TemplateException("Error rendering template [$template] to destination ${projectPath( destination )}: ${e.message}", e) - } - } - } - } - - /** - * Render the given template to the give destination for the given model - * - * @param template The contents template - * @param destination The destination - * @param model The model - */ - void render(Resource template, File destination, Model model, boolean overwrite = false) { - render(template, destination, model.asMap(), overwrite) - } - /** - * Render the given template to the given destination - * - * @param template The template - * @param destination The destination - * @param model The model - */ - void render(Resource template, File destination, Map model = Collections.emptyMap(), boolean overwrite = false) { - if(template && destination) { - if(destination.exists() && !overwrite) { - executionContext.console.warn("Destination file ${projectPath( destination )} already exists, skipping...") - } - else if(!template?.exists()) { - throw new TemplateException("Template [$template.filename] not found.") - } - else { - Template t = templateCache[template.filename] - if(t == null) { - - try { - def templateEngine = new GStringTemplateEngine() - def reader = new InputStreamReader(template.inputStream, "UTF-8") - try { - t = templateEngine.createTemplate(reader) - } finally { - try { - reader.close() - } catch (e) { - // ignore - } - } - } catch (e) { - throw new TemplateException("Error rendering template [$template.filename] to destination ${projectPath( destination )}: ${e.message}", e) - } - } - if(t != null) { - try { - writeTemplateToDestination(t, model, destination) - executionContext.console.addStatus("Rendered template ${template.filename} to destination ${projectPath( destination )}") - } catch (Throwable e) { - destination.delete() - throw new TemplateException("Error rendering template [$template.filename] to destination ${projectPath( destination )}: ${e.message}", e) - } - } - } - } - } - - /** - * Find templates matching the given pattern - * - * @param pattern The pattern - * @return The available templates - */ - Iterable templates(String pattern) { - Collection resList = [] - resList.addAll( resources(pattern) ) - resList.addAll( resources("classpath*:META-INF/templates/$pattern")) - return resList.unique() - } - - /** - * Find a template at the given location - * - * @param location The location - * @return The resource or null if it doesn't exist - */ - Resource template(Object location) { - Resource f = resource(file("src/main/templates/$location")) - if(!f?.exists()) { - if( file('profile.yml').exists() ) { - f = resource( file("templates/$location") ) - if(f.exists()) { - return f - } - } - if(profile) { - def path = location.toString() - f = profile.getTemplate(path) - if(!f.exists()) { - def allProfiles = profileRepository.getProfileAndDependencies(profile) - for(parent in allProfiles) { - f = parent.getTemplate(path) - if(f.exists()) break - } - } - } - if(!f?.exists()) { - return resource("classpath*:META-INF/templates/" + location) - } - } - return resource(f) - } - - - private static void writeTemplateToDestination(Template template, Map model, File destination) { - destination.parentFile.mkdirs() - destination.withWriter("UTF-8") { Writer w -> - template.make(model).writeTo(w) - w.flush() - } - - ClassNameCompleter.refreshAll() - } -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/AbstractJarProfileRepository.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/repository/AbstractJarProfileRepository.groovy deleted file mode 100644 index 0b644b59161..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/AbstractJarProfileRepository.groovy +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile.repository - -import groovy.transform.CompileStatic -import org.eclipse.aether.artifact.Artifact -import org.eclipse.aether.artifact.DefaultArtifact -import org.grails.cli.GrailsCli -import org.grails.cli.profile.AbstractProfile -import org.grails.cli.profile.Command -import org.grails.cli.profile.Profile -import org.grails.cli.profile.ProfileRepository -import org.grails.cli.profile.ProjectContext -import org.grails.cli.profile.ProjectContextAware -import org.grails.io.support.ClassPathResource -import org.grails.io.support.Resource - -/** - * A repository that loads profiles from JAR files - * - * @author Graeme Rocher - * @since 3.1 - */ -@CompileStatic -abstract class AbstractJarProfileRepository implements ProfileRepository { - - protected final List allProfiles = [] - protected final Map profilesByName = [:] - protected static final String DEFAULT_PROFILE_GROUPID = "org.grails.profiles" - - private Set registeredUrls = [] - - @Override - Profile getProfile(String profileName) { - return profilesByName[profileName] - } - - @Override - Profile getProfile(String profileName, Boolean parentProfile) { - return getProfile(profileName) - } - - List getAllProfiles() { - return allProfiles - } - - @Override - Resource getProfileDirectory(String profile) { - return getProfile(profile)?.profileDir - } - - @Override - List getProfileAndDependencies(Profile profile) { - List sortedProfiles = [] - Set visitedProfiles = [] as Set - visitTopologicalSort(profile, sortedProfiles, visitedProfiles) - return sortedProfiles - } - - Artifact getProfileArtifact(String profileName) { - if (profileName.contains(':')) { - return new DefaultArtifact(profileName) - } - - String groupId = DEFAULT_PROFILE_GROUPID - String version = null - - Map defaultValues = GrailsCli.getSetting("grails.profiles", Map, [:]) - defaultValues.remove("repositories") - def data = defaultValues.get(profileName) - if(data instanceof Map) { - groupId = data.get("groupId") - version = data.get("version") - } - - return new DefaultArtifact(groupId, profileName, null, version) - } - - protected void registerProfile(URL url, ClassLoader parent) { - if(registeredUrls.contains(url)) return - - def classLoader = new URLClassLoader([url] as URL[], parent) - def profileYml = classLoader.getResource("META-INF/grails-profile/profile.yml") - if (profileYml != null) { - registeredUrls.add(url) - def profile = new JarProfile(this, new ClassPathResource("META-INF/grails-profile/", classLoader), classLoader) - profile.profileRepository = this - allProfiles.add profile - profilesByName[profile.name] = profile - } - } - private void visitTopologicalSort(Profile profile, List sortedProfiles, Set visitedProfiles) { - if(profile != null && !visitedProfiles.contains(profile)) { - visitedProfiles.add(profile) - profile.getExtends().each { Profile dependentProfile -> - visitTopologicalSort(dependentProfile, sortedProfiles, visitedProfiles); - } - sortedProfiles.add(profile) - } - } - - static class JarProfile extends AbstractProfile { - - JarProfile(ProfileRepository repository, Resource profileDir, ClassLoader classLoader) { - super(profileDir,classLoader) - this.profileRepository = repository - initialize() - } - - @Override - String getName() { - super.name - } - - @Override - Iterable getCommands(ProjectContext context) { - super.getCommands(context) - for(cmd in internalCommands) { - if(cmd instanceof ProjectContextAware) { - ((ProjectContextAware)cmd).setProjectContext(context) - } - commandsByName[cmd.name] = cmd - } - - return commandsByName.values() - } - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/GrailsAetherGrapeEngineFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/repository/GrailsAetherGrapeEngineFactory.groovy deleted file mode 100644 index f9c6d1f1b92..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/GrailsAetherGrapeEngineFactory.groovy +++ /dev/null @@ -1,91 +0,0 @@ -package org.grails.cli.profile.repository - -import groovy.transform.CompileStatic -import org.apache.maven.repository.internal.MavenRepositorySystemUtils -import org.eclipse.aether.DefaultRepositorySystemSession -import org.eclipse.aether.RepositorySystem -import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory -import org.eclipse.aether.impl.DefaultServiceLocator -import org.eclipse.aether.internal.impl.DefaultRepositorySystem -import org.eclipse.aether.repository.RemoteRepository -import org.eclipse.aether.repository.RepositoryPolicy -import org.eclipse.aether.spi.connector.RepositoryConnectorFactory -import org.eclipse.aether.spi.connector.transport.TransporterFactory -import org.eclipse.aether.spi.locator.ServiceLocator -import org.eclipse.aether.transport.file.FileTransporterFactory -import org.eclipse.aether.transport.http.HttpTransporterFactory -import org.eclipse.aether.util.repository.AuthenticationBuilder -import org.springframework.boot.cli.compiler.grape.AetherGrapeEngine -import org.springframework.boot.cli.compiler.grape.DefaultRepositorySystemSessionAutoConfiguration -import org.springframework.boot.cli.compiler.grape.DependencyResolutionContext -import org.springframework.boot.cli.compiler.grape.RepositorySystemSessionAutoConfiguration - -/** - * Creates aether engine to resolve profiles. Mostly copied from {@link AetherGrapeEngine}. - * Created to support repositories with authentication. - * - * @author James Kleeh - * @since 3.2 - */ -@CompileStatic -class GrailsAetherGrapeEngineFactory { - - static AetherGrapeEngine create(GroovyClassLoader classLoader, - List repositoryConfigurations, - DependencyResolutionContext dependencyResolutionContext) { - - RepositorySystem repositorySystem = createServiceLocator() - .getService(RepositorySystem.class) - - DefaultRepositorySystemSession repositorySystemSession = MavenRepositorySystemUtils - .newSession() - - ServiceLoader autoConfigurations = ServiceLoader - .load(RepositorySystemSessionAutoConfiguration.class) - - for (RepositorySystemSessionAutoConfiguration autoConfiguration : autoConfigurations) { - autoConfiguration.apply(repositorySystemSession, repositorySystem) - } - - new DefaultRepositorySystemSessionAutoConfiguration() - .apply(repositorySystemSession, repositorySystem) - - return new AetherGrapeEngine(classLoader, repositorySystem, - repositorySystemSession, createRepositories(repositoryConfigurations), - dependencyResolutionContext, false) - } - - private static ServiceLocator createServiceLocator() { - DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator() - locator.addService(RepositorySystem.class, DefaultRepositorySystem.class) - locator.addService(RepositoryConnectorFactory.class, - BasicRepositoryConnectorFactory.class) - locator.addService(TransporterFactory.class, HttpTransporterFactory.class) - locator.addService(TransporterFactory.class, FileTransporterFactory.class) - return locator - } - - private static List createRepositories( - List repositoryConfigurations) { - List repositories = new ArrayList( - repositoryConfigurations.size()) - for (GrailsRepositoryConfiguration repositoryConfiguration : repositoryConfigurations) { - RemoteRepository.Builder builder = new RemoteRepository.Builder( - repositoryConfiguration.getName(), "default", - repositoryConfiguration.getUri().toASCIIString()) - if (repositoryConfiguration.hasCredentials()) { - builder.authentication = new AuthenticationBuilder() - .addUsername(repositoryConfiguration.username) - .addPassword(repositoryConfiguration.password) - .build() - } - if (!repositoryConfiguration.getSnapshotsEnabled()) { - builder.setSnapshotPolicy( - new RepositoryPolicy(false, RepositoryPolicy.UPDATE_POLICY_NEVER, - RepositoryPolicy.CHECKSUM_POLICY_IGNORE)) - } - repositories.add(builder.build()) - } - return repositories - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/GrailsRepositoryConfiguration.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/repository/GrailsRepositoryConfiguration.groovy deleted file mode 100644 index 1710d7ec535..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/GrailsRepositoryConfiguration.groovy +++ /dev/null @@ -1,93 +0,0 @@ -package org.grails.cli.profile.repository - -import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration - -/** - * The configuration of a repository. See {@link org.springframework.boot.cli.compiler.grape.RepositoryConfiguration} - * Created to support configuration with authentication - * - * @author James Kleeh - * @since 3.2 - */ -class GrailsRepositoryConfiguration { - - private static final int INITIAL_HASH = 7 - private static final int MULTIPLIER = 31 - - final String name - final URI uri - final boolean snapshotsEnabled - final String username - final String password - - /** - * Creates a new {@code GrailsRepositoryConfiguration} instance. - * @param name The name of the repository - * @param uri The uri of the repository - * @param snapshotsEnabled {@code true} if the repository should enable access to snapshots, {@code false} otherwise - */ - public GrailsRepositoryConfiguration(String name, URI uri, boolean snapshotsEnabled) { - this.name = name - this.uri = uri - this.snapshotsEnabled = snapshotsEnabled - } - - - /** - * Creates a new {@code GrailsRepositoryConfiguration} instance. - * @param name The name of the repository - * @param uri The uri of the repository - * @param snapshotsEnabled {@code true} if the repository should enable access to snapshots, {@code false} otherwise - * @param username The username needed to authenticate with the repository - * @param password The password needed to authenticate with the repository - */ - public GrailsRepositoryConfiguration(String name, URI uri, boolean snapshotsEnabled, String username, String password) { - this.name = name - this.uri = uri - this.snapshotsEnabled = snapshotsEnabled - this.username = username - this.password = password - } - - @Override - String toString() { - "GrailsRepositoryConfiguration [name=$name, uri=$uri, snapshotsEnabled=$snapshotsEnabled]" - } - - @Override - int hashCode() { - nullSafeHashCode(name) - } - - boolean hasCredentials() { - username && password - } - - @Override - boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - String name = null - if (obj instanceof RepositoryConfiguration) { - name = obj.name - } else if (obj instanceof GrailsRepositoryConfiguration) { - name = obj.name - } - this.name == name - } - - static int nullSafeHashCode(char[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (char element : array) { - hash = MULTIPLIER * hash + element; - } - return hash; - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/MavenProfileRepository.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/repository/MavenProfileRepository.groovy deleted file mode 100644 index 7342dc16d24..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/MavenProfileRepository.groovy +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile.repository - -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import org.eclipse.aether.artifact.Artifact -import org.eclipse.aether.artifact.DefaultArtifact -import org.eclipse.aether.graph.Dependency -import org.grails.cli.boot.GrailsDependencyVersions -import org.grails.cli.profile.Profile -import org.springframework.boot.cli.compiler.grape.AetherGrapeEngine -import org.springframework.boot.cli.compiler.grape.DependencyResolutionContext -import org.springframework.boot.cli.compiler.grape.DependencyResolutionFailedException - -/** - * Resolves profiles from a configured list of repositories using Aether - * - * @author Graeme Rocher - * @since 3.1 - */ -@CompileStatic -class MavenProfileRepository extends AbstractJarProfileRepository { - - public static final GrailsRepositoryConfiguration DEFAULT_REPO = new GrailsRepositoryConfiguration("grailsCentral", new URI("https://repo.grails.org/grails/core"), true) - - List repositoryConfigurations - AetherGrapeEngine grapeEngine - GroovyClassLoader classLoader - DependencyResolutionContext resolutionContext - GrailsDependencyVersions profileDependencyVersions - private boolean resolved = false - - MavenProfileRepository(List repositoryConfigurations) { - this.repositoryConfigurations = repositoryConfigurations - classLoader = new GroovyClassLoader(Thread.currentThread().contextClassLoader) - resolutionContext = new DependencyResolutionContext() - this.grapeEngine = GrailsAetherGrapeEngineFactory.create(classLoader, repositoryConfigurations, resolutionContext) - profileDependencyVersions = new GrailsDependencyVersions(grapeEngine) - resolutionContext.addDependencyManagement(profileDependencyVersions) - } - - MavenProfileRepository() { - this([DEFAULT_REPO]) - } - - @Override - Profile getProfile(String profileName, Boolean parentProfile) { - String profileShortName = profileName - if(profileName.contains(':')) { - def art = new DefaultArtifact(profileName) - profileShortName = art.artifactId - } - if (!profilesByName.containsKey(profileShortName)) { - if(parentProfile && profileDependencyVersions.find(DEFAULT_PROFILE_GROUPID, profileShortName)) { - return resolveProfile(profileShortName) - } else { - return resolveProfile(profileName) - } - } - return super.getProfile(profileShortName) - } - - @Override - Profile getProfile(String profileName) { - getProfile(profileName, false) - } - - protected Profile resolveProfile(String profileName) { - Artifact art = getProfileArtifact(profileName) - - try { - grapeEngine.grab(group: art.groupId, module: art.artifactId, version: art.version ?: null) - } catch (DependencyResolutionFailedException e ) { - - def localData = new File(System.getProperty("user.home"),"/.m2/repository/${art.groupId.replace('.','/')}/$art.artifactId/maven-metadata-local.xml") - if(localData.exists()) { - def currentVersion = parseCurrentVersion(localData) - def profileFile = new File(localData.parentFile, "$currentVersion/${art.artifactId}-${currentVersion}.jar") - if(profileFile.exists()) { - classLoader.addURL(profileFile.toURI().toURL()) - } - else { - throw e - } - } - else { - throw e - } - } - - processUrls() - return super.getProfile(art.artifactId) - } - - @CompileDynamic - protected String parseCurrentVersion(File localData) { - new XmlSlurper().parse(localData).versioning.versions.version[0].text() - } - - protected void processUrls() { - def urls = classLoader.getURLs() - for (URL url in urls) { - registerProfile(url, new URLClassLoader([url] as URL[], Thread.currentThread().contextClassLoader)) - } - } - - @Override - List getAllProfiles() { - if(!resolved) { - List profiles = [] - resolutionContext.managedDependencies.each { Dependency dep -> - if (dep.artifact.groupId == "org.grails.profiles") { - profiles.add([group: dep.artifact.groupId, module: dep.artifact.artifactId]) - } - } - profiles.sort { it.module } - - for (Map profile in profiles) { - grapeEngine.grab(profile) - } - - def localData = new File(System.getProperty("user.home"),"/.m2/repository/org/grails/profiles") - if(localData.exists()) { - localData.eachDir { File dir -> - if(!dir.name.startsWith('.')) { - def profileData = new File(dir, "/maven-metadata-local.xml") - if(profileData.exists()) { - def currentVersion = parseCurrentVersion(profileData) - def profileFile = new File(dir, "$currentVersion/${dir.name}-${currentVersion}.jar") - if(profileFile.exists()) { - classLoader.addURL(profileFile.toURI().toURL()) - } - } - } - } - } - - processUrls() - resolved = true - } - return super.getAllProfiles() - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/StaticJarProfileRepository.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/repository/StaticJarProfileRepository.groovy deleted file mode 100644 index a9be3702b08..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/repository/StaticJarProfileRepository.groovy +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2015 original 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 - * - * 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.grails.cli.profile.repository -import groovy.transform.CompileStatic -import org.eclipse.aether.artifact.DefaultArtifact -import org.grails.cli.profile.Profile - -/** - * A JAR file repository that resolves profiles from a static array of JAR file URLs - * - * @author Graeme Rocher - * @since 3.1 - */ -@CompileStatic -class StaticJarProfileRepository extends AbstractJarProfileRepository { - - - final URL[] urls - - StaticJarProfileRepository(ClassLoader parent, URL...urls) { - this.urls = urls - for(url in urls) { - registerProfile(url, parent) - } - } - - Profile getProfile(String profileName) { - def profile = super.getProfile(profileName) - if(profile == null && profileName.contains(':')) { - def art = new DefaultArtifact(profileName) - profile = super.getProfile(art.artifactId) - } - return profile - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/DefaultStepFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/steps/DefaultStepFactory.groovy deleted file mode 100644 index 7de75668003..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/DefaultStepFactory.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.steps - -import groovy.transform.CompileStatic -import org.grails.cli.profile.Command -import org.grails.cli.profile.ProfileCommand -import org.grails.cli.profile.Step - -/** - * Dynamic creation of {@link Step} instances - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class DefaultStepFactory implements StepFactory { - - Map> steps = [ - render: RenderStep, - gradle: GradleStep, - execute: ExecuteStep, - mkdir: MkdirStep - ] - - @Override - Step createStep(String name, Command command, Map parameters) { - if(command instanceof ProfileCommand) { - return steps[name]?.newInstance(command, parameters) - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/ExecuteStep.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/steps/ExecuteStep.groovy deleted file mode 100644 index a217843254b..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/ExecuteStep.groovy +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.steps - -import org.grails.cli.profile.AbstractStep -import org.grails.cli.profile.Command -import org.grails.cli.profile.CommandException -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.ProfileCommand - -/** - * A {@link org.grails.cli.profile.Step} that can execute another command - * - * @author Graeme Rocher - * @since 3.0 - */ -class ExecuteStep extends AbstractStep { - - public static final String NAME = "execute" - public static final String CLASS_NAME = "class" - - - Command target - - - ExecuteStep(ProfileCommand command, Map parameters) { - super(command, parameters) - - try { - String className = parameters.get(CLASS_NAME) - def cmd = className ? Class.forName(className, true, Thread.currentThread().contextClassLoader) - .newInstance() : null - if(cmd instanceof Command) { - if(cmd instanceof ProfileCommand) { - ((ProfileCommand)cmd).profile = command.profile - } - this.target = cmd - } - else { - throw new CommandException("Invalid command class [$className] specified") - } - } catch (Throwable e) { - throw new CommandException("Unable to create step for command [${command.name}] for parameters $parameters", e) - } - } - - @Override - String getName() { NAME } - - @Override - boolean handle(ExecutionContext context) { - return target.handle(context) - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/GradleStep.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/steps/GradleStep.groovy deleted file mode 100644 index 42c1410690c..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/GradleStep.groovy +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.steps - -import groovy.transform.CompileStatic -import org.gradle.tooling.BuildException -import org.gradle.tooling.BuildLauncher -import org.grails.build.parsing.CommandLine -import org.grails.cli.gradle.GradleUtil -import org.grails.cli.profile.* -import org.grails.exceptions.ExceptionUtils - -/** - * A {@link org.grails.cli.profile.Step} that invokes Gradle - * - * @author Lari Hotari - * @author Graeme Rocher - * - * @since 3.0 - */ -@CompileStatic -class GradleStep extends AbstractStep { - protected static final Map GRADLE_ARGUMENT_ADAPTER = [ - 'plain-output' : '--console plain', - 'verbose' : '-d' - ] - protected List tasks = [] - protected String baseArguments = "" - protected boolean passArguments = true - - GradleStep(ProfileCommand command, Map parameters) { - super(command, parameters) - initialize() - } - - - @Override - String getName() { "gradle" } - - @Override - public boolean handle(ExecutionContext context) { - try { - GradleUtil.runBuildWithConsoleOutput(context) { BuildLauncher buildLauncher -> - buildLauncher.forTasks(tasks as String[]) - fillArguments(context, buildLauncher) - } - } catch (BuildException e) { - def cause = ExceptionUtils.getRootCause(e) - context.console.error("Gradle build terminated with error: ${cause.message}", cause) - return false - } - return true; - } - - protected void initialize() { - tasks = (List)parameters.tasks - baseArguments = parameters.baseArguments ?: '' - passArguments = Boolean.valueOf(parameters.passArguments?.toString() ?: 'true' ) - } - - protected BuildLauncher fillArguments(ExecutionContext context, BuildLauncher buildLauncher) { - def commandLine = context.commandLine - - List argList = baseArguments ? [baseArguments] : new ArrayList() - - for(Map.Entry entry in commandLine.undeclaredOptions) { - def flagName = entry.key - if(GRADLE_ARGUMENT_ADAPTER.containsKey(flagName)) { - argList.addAll( GRADLE_ARGUMENT_ADAPTER[flagName].split(/\s/) ) - continue - } - - def flag = command.description.getFlag(flagName) - if(flag) { - flagName = flag.target ?: flagName - } - argList << "-$flagName".toString() - - } - - if(passArguments) { - argList.addAll(commandLine.remainingArgs.collect() { String arg -> "-${arg}".toString() } ) - } - - - if(argList) { - - buildLauncher.withArguments(argList as String[]) - } - buildLauncher - } - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/MkdirStep.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/steps/MkdirStep.groovy deleted file mode 100644 index b94f8d0df30..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/MkdirStep.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.steps - -import groovy.transform.CompileStatic -import org.grails.cli.profile.AbstractStep -import org.grails.cli.profile.CommandException -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.ProfileCommand -import org.grails.cli.profile.support.ArtefactVariableResolver - -/** - * A step that makes a directory - * - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class MkdirStep extends AbstractStep { - - public static final String NAME = "mkdir" - - String location - - MkdirStep(ProfileCommand command, Map parameters) { - super(command, parameters) - location = parameters.location - if(!location) { - throw new CommandException("Location not specified for mkdir step") - } - } - - @Override - String getName() { NAME } - - @Override - boolean handle(ExecutionContext context) { - def args = context.commandLine.remainingArgs - if(args) { - def name = args[0] - def variableResolver = new ArtefactVariableResolver(name) - File destination = variableResolver.resolveFile(location, context) - return destination.mkdirs() - } - else { - return new File(context.baseDir, location).mkdirs() - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/RenderStep.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/steps/RenderStep.groovy deleted file mode 100644 index 4443cf28226..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/RenderStep.groovy +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.steps - -import grails.build.logging.GrailsConsole -import grails.util.GrailsNameUtils -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.build.parsing.CommandLine -import org.grails.cli.interactive.completers.ClassNameCompleter -import org.grails.cli.profile.AbstractStep -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.Profile -import org.grails.cli.profile.commands.templates.SimpleTemplate -import org.grails.cli.profile.support.ArtefactVariableResolver -import org.grails.io.support.Resource - -/** - * A {@link org.grails.cli.profile.Step} that renders a template - * - * @author Lari Hotari - * @author Graeme Rocher - * - * @since 3.0 - */ -@InheritConstructors -@CompileStatic -class RenderStep extends AbstractStep { - - public static final String NAME = "render" - public static final String TEMPLATES_DIR = "templates/" - - @Override - @CompileStatic - String getName() { NAME } - - @Override - public boolean handle(ExecutionContext context) { - def commandLine = context.getCommandLine() - String nameAsArgument = commandLine.getRemainingArgs()[0] - String artifactName - String artifactPackage - def nameAndPackage = resolveNameAndPackage(context, nameAsArgument) - artifactName = nameAndPackage[0] - artifactPackage = nameAndPackage[1] - def variableResolver = new ArtefactVariableResolver(artifactName, (String) parameters.convention,artifactPackage) - File destination = variableResolver.resolveFile(parameters.destination.toString(), context) - - try { - - String relPath = relativePath(context.baseDir, destination) - if(destination.exists() && !flag(commandLine, 'force')) { - context.console.error("${relPath} already exists.") - return false - } - - renderToDestination(destination, variableResolver.variables) - context.console.addStatus("Created $relPath") - - return true - } catch (Throwable e) { - GrailsConsole.instance.error("Failed to render template to destination: ${e.message}", e) - return false - } - } - - protected Resource searchTemplateDepthFirst(Profile profile, String template) { - if(template.startsWith(TEMPLATES_DIR)) { - return searchTemplateDepthFirst(profile, template.substring(TEMPLATES_DIR.length())) - } - Resource templateFile = profile.getTemplate(template) - if(templateFile.exists()) { - return templateFile - } else { - for(parent in profile.extends) { - templateFile = searchTemplateDepthFirst(parent, template) - if(templateFile) { - return templateFile - } - } - } - null - } - - protected void renderToDestination(File destination, Map variables) { - Profile profile = command.profile - Resource templateFile = searchTemplateDepthFirst(profile, parameters.template.toString()) - if(!templateFile) { - throw new IOException("cannot find template " + parameters.template) - } - destination.setText(new SimpleTemplate(templateFile.inputStream.getText("UTF-8")).render(variables), "UTF-8") - ClassNameCompleter.refreshAll() - } - - protected List resolveNameAndPackage(ExecutionContext context, String nameAsArgument) { - List parts = nameAsArgument.split(/\./) as List - - String artifactName - String artifactPackage - - if(parts.size() == 1) { - artifactName = parts[0] - artifactPackage = context.navigateConfig('grails', 'codegen', 'defaultPackage')?:'' - } else { - artifactName = parts[-1] - artifactPackage = parts[0..-2].join('.') - } - - [GrailsNameUtils.getClassName(artifactName), artifactPackage] - } - - protected String relativePath(File relbase, File file) { - def pathParts = [] - def currentFile = file - while (currentFile != null && currentFile != relbase) { - pathParts += currentFile.name - currentFile = currentFile.parentFile - } - pathParts.reverse().join('/') - } - - -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/StepFactory.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/steps/StepFactory.groovy deleted file mode 100644 index 1957cae7e38..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/StepFactory.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package org.grails.cli.profile.steps - -import org.grails.cli.profile.Command -import org.grails.cli.profile.Step - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * Creates steps - * - * @author Graeme Rocher - * @since 3.0 - */ -interface StepFactory { - - /** - * Creates a step for the given name, command and parameters - * - * @param name The name of the step - * @param command The command - * @param parameters The parameters - * - * @return The step instance - */ - Step createStep(String name, Command command, Map parameters) -} \ No newline at end of file diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/StepRegistry.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/steps/StepRegistry.groovy deleted file mode 100644 index 84df7cad819..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/steps/StepRegistry.groovy +++ /dev/null @@ -1,58 +0,0 @@ -package org.grails.cli.profile.steps - -import groovy.transform.CompileStatic -import org.grails.cli.profile.Command -import org.grails.cli.profile.Step - - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * Registry of steps - * - * @author Graeme Rocher - * - * @since 3.0 - */ -@CompileStatic -class StepRegistry { - - private static Collection registeredStepFactories = [] - - static { - def stepFactories = ServiceLoader.load(StepFactory).iterator() - - while(stepFactories.hasNext()) { - StepFactory stepFactory = stepFactories.next() - registeredStepFactories << stepFactory - } - } - - /** - * Looks up a {@link Step} - * - * @param name The name of the {@link Step} - * @return A step or null if it doesn't exist for the given name - */ - static Step getStep(String name, Command command, Map parameters) { - if(!name) return null - for(StepFactory sf in registeredStepFactories) { - def step = sf.createStep(name, command, parameters) - if(step) return step - } - } -} diff --git a/grails-shell/src/main/groovy/org/grails/cli/profile/support/ArtefactVariableResolver.groovy b/grails-shell/src/main/groovy/org/grails/cli/profile/support/ArtefactVariableResolver.groovy deleted file mode 100644 index ac154e9f7f8..00000000000 --- a/grails-shell/src/main/groovy/org/grails/cli/profile/support/ArtefactVariableResolver.groovy +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.support - -import grails.util.GrailsNameUtils -import groovy.transform.CompileStatic -import org.grails.cli.profile.ExecutionContext -import org.grails.cli.profile.commands.templates.SimpleTemplate - - - -/** - * @author Graeme Rocher - * @since 3.0 - */ -@CompileStatic -class ArtefactVariableResolver { - /** - * The artifact name and package - */ - String artifactPackage, artifactName - /** - * The suffix used as a convention for the file - */ - String convention - Map variables = [:] - - ArtefactVariableResolver(String artifactName, String artifactPackage = null) { - this(artifactName, null, artifactPackage) - } - - ArtefactVariableResolver(String artifactName, String convention, String artifactPackage) { - this.artifactPackage = artifactPackage - this.artifactName = artifactName - this.convention = convention - createVariables() - } - - Map createVariables() { - if(artifactPackage) { - variables['artifact.package.name'] = artifactPackage - variables['artifact.package.path'] = artifactPackage?.replace('.','/') - variables['artifact.package'] = "package $artifactPackage\n".toString() - } - if(convention && artifactName.endsWith(convention)) { - artifactName = artifactName.substring(0, artifactName.length() - convention.length()) - } - variables['artifact.name'] = artifactName - variables['artifact.propertyName'] = GrailsNameUtils.getPropertyName(artifactName) - return variables - } - - File resolveFile(String pathToResolve, ExecutionContext context) { - String destinationName = new SimpleTemplate(pathToResolve).render(variables) - File destination = new File(context.baseDir, destinationName).absoluteFile - - if(!destination.getParentFile().exists()) { - destination.getParentFile().mkdirs() - } - return destination - } -} diff --git a/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.Command b/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.Command deleted file mode 100644 index 487d8176593..00000000000 --- a/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.Command +++ /dev/null @@ -1,10 +0,0 @@ -org.grails.cli.profile.commands.CreateAppCommand -org.grails.cli.profile.commands.CreatePluginCommand -org.grails.cli.profile.commands.CreateProfileCommand -org.grails.cli.profile.commands.OpenCommand -org.grails.cli.profile.commands.HelpCommand -org.grails.cli.profile.commands.ListProfilesCommand -org.grails.cli.profile.commands.ProfileInfoCommand -org.grails.cli.gradle.commands.GradleCommand - - diff --git a/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.commands.factory.CommandFactory b/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.commands.factory.CommandFactory deleted file mode 100644 index 1467d32bfd9..00000000000 --- a/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.commands.factory.CommandFactory +++ /dev/null @@ -1,4 +0,0 @@ -org.grails.cli.profile.commands.factory.YamlCommandFactory -org.grails.cli.profile.commands.factory.GroovyScriptCommandFactory -org.grails.cli.profile.commands.factory.ServiceCommandFactory -org.grails.cli.profile.commands.factory.ApplicationContextCommandFactory diff --git a/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.steps.StepFactory b/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.steps.StepFactory deleted file mode 100644 index 0138a747d76..00000000000 --- a/grails-shell/src/main/resources/META-INF/services/org.grails.cli.profile.steps.StepFactory +++ /dev/null @@ -1 +0,0 @@ -org.grails.cli.profile.steps.DefaultStepFactory \ No newline at end of file diff --git a/grails-shell/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration b/grails-shell/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration deleted file mode 100644 index 97c345017d9..00000000000 --- a/grails-shell/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration +++ /dev/null @@ -1,2 +0,0 @@ -org.grails.cli.boot.GrailsApplicationCompilerAutoConfiguration -org.grails.cli.boot.GrailsTestCompilerAutoConfiguration \ No newline at end of file diff --git a/grails-shell/src/main/resources/unixStartScript.txt b/grails-shell/src/main/resources/unixStartScript.txt deleted file mode 100644 index 2f725453e97..00000000000 --- a/grails-shell/src/main/resources/unixStartScript.txt +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## ${applicationName} 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\"`/${appHomeRelativePath}" >/dev/null -APP_HOME="`pwd -P`" -cd "\$SAVED" >/dev/null - -APP_NAME="${applicationName}" -APP_BASE_NAME=`basename "\$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and ${optsEnvironmentVar} to pass JVM options to this script. -DEFAULT_JVM_OPTS=${defaultJvmOpts} - -# 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=$classpath - -# 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/mn.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 \$${optsEnvironmentVar} <% if ( appNameSystemProperty ) { %>"\"-D${appNameSystemProperty}=\$APP_BASE_NAME\"" <% } %>-classpath "\"\$CLASSPATH\"" ${mainClassName} "\$APP_ARGS" - -exec "\$JAVACMD" "\$@" \ No newline at end of file diff --git a/grails-shell/src/test/groovy/org/grails/cli/TestTerminal.java b/grails-shell/src/test/groovy/org/grails/cli/TestTerminal.java deleted file mode 100644 index 538f66d794a..00000000000 --- a/grails-shell/src/test/groovy/org/grails/cli/TestTerminal.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.grails.cli; - -import jline.TerminalSupport; - -public class TestTerminal extends TerminalSupport { - public TestTerminal() { - super(true); - setAnsiSupported(false); - setEchoEnabled(false); - } -} diff --git a/grails-shell/src/test/groovy/org/grails/cli/interactive/completers/RegexCompletorSpec.groovy b/grails-shell/src/test/groovy/org/grails/cli/interactive/completers/RegexCompletorSpec.groovy deleted file mode 100644 index ef1cbf69363..00000000000 --- a/grails-shell/src/test/groovy/org/grails/cli/interactive/completers/RegexCompletorSpec.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package org.grails.cli.interactive.completers - -import spock.lang.* - -class RegexCompletorSpec extends Specification { - @Unroll("String '#source' is not matching") - def "Simple pattern matches"() { - given: "a regex completor and an empty candidate list" - def completor = new RegexCompletor(/!\w+/) - def candidateList = [] - - when: "the completor is invoked for a given string" - def retval = completor.complete(source, 0, candidateList) - - then: "that string is the sole candidate and the return value is 0" - candidateList.size() == 1 - candidateList[0] == source - retval == 0 - - where: - source << [ "!ls", "!test_stuff" ] - } - - @Unroll("String '#source' is incorrectly matching") - def "Non matching strings"() { - given: "a regex completor and an empty candidate list" - def completor = new RegexCompletor(/!\w+/) - def candidateList = [] - - when: "the completor is invoked for a given (non-matching) string" - def retval = completor.complete(source, 0, candidateList) - - then: "the candidate list is empty and the return value is -1" - candidateList.size() == 0 - retval == -1 - - where: - source << [ "!ls ls", "!", "test", "" ] - } -} diff --git a/grails-shell/src/test/groovy/org/grails/cli/profile/ResourceProfileSpec.groovy b/grails-shell/src/test/groovy/org/grails/cli/profile/ResourceProfileSpec.groovy deleted file mode 100644 index cd4c071e874..00000000000 --- a/grails-shell/src/test/groovy/org/grails/cli/profile/ResourceProfileSpec.groovy +++ /dev/null @@ -1,245 +0,0 @@ -package org.grails.cli.profile - -import groovy.transform.CompileStatic -import org.eclipse.aether.artifact.DefaultArtifact -import org.eclipse.aether.graph.Dependency -import org.grails.cli.profile.commands.factory.YamlCommandFactory -import org.grails.io.support.Resource -import spock.lang.Specification - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * @author graemerocher - */ -class ResourceProfileSpec extends Specification { - - void "Test resource version"() { - given:"A resource profile" - def mockResource = Mock(Resource) - - def mockProfileYml = Mock(Resource) - mockProfileYml.getInputStream() >> new ByteArrayInputStream(getYamlWithCommandAndFeatures()) - mockResource.createRelative("profile.yml") >> mockProfileYml - mockResource.getURL() >> new URL("file:/path/to/my-profile-1.0.1.jar!profile.yml") - - def mockCommandYml = Mock(Resource) - mockCommandYml.getInputStream() >> new ByteArrayInputStream(getCommandYaml()) - mockCommandYml.exists() >> true - mockResource.createRelative("commands/clean.yml") >> mockCommandYml - mockResource.getURL() >> new URL("file:/path/to/my-profile-1.0.1.jar!/clean.yml") - - def mockFeatureYml = Mock(Resource) - mockFeatureYml.getInputStream() >> new ByteArrayInputStream(getFeatureYaml()) - mockFeatureYml.exists() >> true - mockResource.createRelative("features/hibernate/feature.yml") >> mockFeatureYml - mockResource.createRelative("features/hibernate/") >> mockResource - mockResource.createRelative("feature.yml") >> mockFeatureYml - mockResource.getURL() >> new URL("file:/path/to/my-profile-1.0.1.jar!/feature.yml") - - def profileRepository = Mock(ProfileRepository) - def profile = new ResourceProfile(profileRepository, "web", mockResource) - profileRepository.getProfile("web" ) >> profile - - def baseProfile = Mock(Profile) - baseProfile.getDependencies() >> [ new Dependency(new DefaultArtifact("foo:bar:2.0"), "test")] - baseProfile.getBuildPlugins() >> [ "foo-plug"] - baseProfile.features >> [] - profileRepository.getProfile("base") >> baseProfile - profileRepository.getProfile("base", true) >> baseProfile - - expect: - profile.version == '1.0.1' - !profile.dependencies.isEmpty() - !profile.features.isEmpty() - - when: - Feature feature = profile.features.find { (it.name == "hibernate") } - - then: - feature - !feature.dependencies.isEmpty() - - } - - void "test YamlCommandFactory readCommands"() { - - given: "A resource and profile" - Resource mockCommandYml = Mock() - TestYamlCommandFactory yamlCommandFactory = new TestYamlCommandFactory() - - when: - mockCommandYml.getInputStream() >> new ByteArrayInputStream(getCommandYaml()) - mockCommandYml.filename >> "clean.yml" - Map data = yamlCommandFactory.testReadCommandFile(mockCommandYml) - - then: - data - data.description == "Cleans a Grails application's compiled sources" - } - - void "Test dependencies"() { - given:"A resource profile" - - def mockResource = Mock(Resource) - def mockProfileYml = Mock(Resource) - mockProfileYml.getInputStream() >> new ByteArrayInputStream(getYaml()) - mockResource.createRelative("profile.yml") >> mockProfileYml - - def profileRepository = Mock(ProfileRepository) - - def profile = new ResourceProfile(profileRepository, "web", mockResource) - profileRepository.getProfile("web", true) >> profile - - def baseProfile = Mock(Profile) - baseProfile.getDependencies() >> [ new Dependency(new DefaultArtifact("foo:bar:2.0"), "test")] - baseProfile.getBuildPlugins() >> [ "foo-plug"] - profileRepository.getProfile("base", true) >> baseProfile - - - when:"The dependencies are accessed" - def deps = profile.dependencies - def plugins = profile.buildPlugins - - then:"They are correct" - plugins.size() == 2 - deps.size() == 2 - plugins == ['foo-plug', 'bar'] - deps[1].scope == 'compile' - deps[1].artifact.groupId == 'org.grails' - deps[1].artifact.artifactId == 'grails-core' - deps[1].artifact.version == '3.1.0' - deps[0].scope == 'test' - deps[0].artifact.groupId == 'foo' - deps[0].artifact.artifactId == 'bar' - deps[0].artifact.version == '2.0' - } - - - void "Test dependency exclusions"() { - given:"A resource profile" - - def mockResource = Mock(Resource) - def mockProfileYml = Mock(Resource) - mockProfileYml.getInputStream() >> new ByteArrayInputStream(getExcludesYaml()) - mockResource.createRelative("profile.yml") >> mockProfileYml - - def profileRepository = Mock(ProfileRepository) - - def profile = new ResourceProfile(profileRepository, "web", mockResource) - profileRepository.getProfile("web", true) >> profile - - def baseProfile = Mock(Profile) - baseProfile.getDependencies() >> [ new Dependency(new DefaultArtifact("foo:bar:2.0"), "test")] - baseProfile.getBuildPlugins() >> [ "foo-plug"] - profileRepository.getProfile("base", true) >> baseProfile - - - when:"The dependencies are accessed" - def deps = profile.dependencies - def plugins = profile.buildPlugins - - then:"They are correct" - deps.size() == 1 - plugins == ['bar'] - - deps.size() == 1 - deps[0].scope == 'compile' - deps[0].artifact.groupId == 'org.grails' - deps[0].artifact.artifactId == 'grails-core' - deps[0].artifact.version == '3.1.0' - } - - byte[] getYaml() { - """ -name: web -extends: base -build: - plugins: - - bar -dependencies: - - scope: compile - coords: org.grails:grails-core:3.1.0 -""".bytes - } - - byte[] getYamlWithCommandAndFeatures() { - """ -name: web -extends: base -features: - provided: - - hibernate -commands: - clean: clean.yml -build: - plugins: - - bar -dependencies: - - scope: compile - coords: org.grails:grails-core:3.1.0 -""".bytes - } - - byte[] getExcludesYaml() { - """ -name: web -extends: base -build: - plugins: - - bar - excludes: - - foo-plug -dependencies: - - scope: excludes - coords: foo:bar:* - - scope: compile - coords: org.grails:grails-core:3.1.0 -""".bytes - } - - byte[] getCommandYaml() { - """ -description: Cleans a Grails application's compiled sources -minArguments: 0 -usage: | - clean -steps: - - command: gradle - tasks: - - clean - -""".bytes - } - - byte[] getFeatureYaml() { - """ -description: Adds GORM for Hibernate 5 to the project -dependencies: - - scope: compile - coords: "org.hibernate:hibernate-core:5.4.0.Final" -""".bytes - } - - @CompileStatic - static class TestYamlCommandFactory extends YamlCommandFactory { - - Map testReadCommandFile(Resource resource) { - readCommandFile(resource) - } - } -} diff --git a/grails-shell/src/test/groovy/org/grails/cli/profile/commands/CommandScriptTransformSpec.groovy b/grails-shell/src/test/groovy/org/grails/cli/profile/commands/CommandScriptTransformSpec.groovy deleted file mode 100644 index 7d5a42486c6..00000000000 --- a/grails-shell/src/test/groovy/org/grails/cli/profile/commands/CommandScriptTransformSpec.groovy +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2014 original 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 - * - * 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.grails.cli.profile.commands - -import org.grails.cli.interactive.completers.DomainClassCompleter -import org.grails.cli.profile.commands.factory.GroovyScriptCommandFactory -import org.grails.cli.profile.commands.script.GroovyScriptCommand -import spock.lang.Specification - -/** - * @author graemerocher - */ -class CommandScriptTransformSpec extends Specification { - - - void "Test that the CommandScriptTransform correctly populates the description"() { - given:"A GroovyClassLoader with the CommandScriptTransform applied" - def gcl = GroovyScriptCommandFactory.createGroovyScriptCommandClassLoader() - - when:"A script is parsed" - def script = (GroovyScriptCommand)(gcl.parseClass(''' -import org.grails.cli.interactive.completers.DomainClassCompleter - -description("example script") { - usage "example usage" - completer DomainClassCompleter - argument name: 'controllerName', description:'The name of the controller' - flag name:'test', description:'Do something' - -} - - -println "Hello!" -''', "MyScript").newInstance()) - - then:"The scripts description is correctly populated" - script.description.name == 'my-script' - script.description.description == 'example script' - script.description.usage == 'example usage' - script.description.arguments.size() == 1 - script.description.arguments[0].name == 'controllerName' - script.description.arguments[0].description == 'The name of the controller' - - script.description.flags.size() == 1 - script.description.flags[0].name == 'test' - script.description.flags[0].description == 'Do something' - script.description.completer instanceof DomainClassCompleter - } -} diff --git a/grails-shell/src/test/groovy/org/grails/cli/profile/commands/CreateAppCommandSpec.groovy b/grails-shell/src/test/groovy/org/grails/cli/profile/commands/CreateAppCommandSpec.groovy deleted file mode 100644 index 8d3fa498bb0..00000000000 --- a/grails-shell/src/test/groovy/org/grails/cli/profile/commands/CreateAppCommandSpec.groovy +++ /dev/null @@ -1,105 +0,0 @@ -package org.grails.cli.profile.commands - -import grails.build.logging.GrailsConsole -import org.grails.cli.profile.Feature -import org.grails.cli.profile.Profile -import org.spockframework.util.StringMessagePrintStream -import spock.lang.Shared -import spock.lang.Specification -/** - * Created by Jim on 7/18/2016. - */ -class CreateAppCommandSpec extends Specification { - - @Shared - StringPrintStream sps - - PrintStream originalOut - - void setup() { - System.setProperty("org.fusesource.jansi.Ansi.disable", "true") - originalOut = GrailsConsole.instance.out - sps = new StringPrintStream() - GrailsConsole.instance.out = sps - } - - void cleanup() { - System.setProperty("org.fusesource.jansi.Ansi.disable", "false") - GrailsConsole.instance.out = originalOut - } - - void "test evaluateFeatures - multiple, some valid"() { - given: - Feature bar = Mock(Feature) { - 2 * getName() >> "bar" - } - Profile profile = Mock(Profile) { - 1 * getName() >> "web" - 2 * getFeatures() >> [bar] - 1 * getRequiredFeatures() >> [] - } - - when: - Iterable features = new CreateAppCommand().evaluateFeatures(profile, ['foo', 'bar']) - - then: - features.size() == 1 - features[0] == bar - sps.toString() == "Warning |\nFeature foo does not exist in the profile web!\n" - } - - void "test evaluateFeatures - multiple, all valid"() { - given: - Feature foo = Mock(Feature) { - 2 * getName() >> "foo" - } - Feature bar = Mock(Feature) { - 2 * getName() >> "bar" - } - Profile profile = Mock(Profile) { - 0 * getName() - 2 * getFeatures() >> [foo, bar] - 1 * getRequiredFeatures() >> [] - } - - when: - Iterable features = new CreateAppCommand().evaluateFeatures(profile, ['foo', 'bar']) - - then: - features.size() == 2 - features[0] == foo - features[1] == bar - sps.toString() == "" - } - - void "test evaluateFeatures fat finger"() { - given: - Feature bar = Mock(Feature) { - 2 * getName() >> "mongodb" - } - Profile profile = Mock(Profile) { - 1 * getName() >> "web" - 2 * getFeatures() >> [bar] - 1 * getRequiredFeatures() >> [] - } - - when: - Iterable features = new CreateAppCommand().evaluateFeatures(profile, ['mongo']) - - then: - features.size() == 0 - sps.toString() == "Warning |\nFeature mongo does not exist in the profile web! Possible solutions: mongodb\n" - } - - class StringPrintStream extends StringMessagePrintStream { - StringBuilder stringBuilder = new StringBuilder() - @Override - protected void printed(String message) { - stringBuilder.append(message) - } - - String toString() { - stringBuilder.toString() - } - } -} diff --git a/grails-shell/src/test/groovy/org/grails/cli/profile/commands/events/CommandEventsTraitGeneratedSpec.groovy b/grails-shell/src/test/groovy/org/grails/cli/profile/commands/events/CommandEventsTraitGeneratedSpec.groovy deleted file mode 100644 index 326cab9f8e8..00000000000 --- a/grails-shell/src/test/groovy/org/grails/cli/profile/commands/events/CommandEventsTraitGeneratedSpec.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.grails.cli.profile.commands.events - -import groovy.transform.Generated -import spock.lang.Specification - -import java.lang.reflect.Method - -class CommandEventsTraitGeneratedSpec extends Specification { - - void "test that all CommandEvents trait methods are marked as Generated"() { - expect: "all CommandEvents methods are marked as Generated on implementation class" - CommandEvents.getMethods().each { Method traitMethod -> - assert TestCommandEvents.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) - } - } -} - -class TestCommandEvents implements CommandEvents { - -} diff --git a/grails-shell/src/test/groovy/org/grails/cli/profile/repository/MavenRepositorySpec.groovy b/grails-shell/src/test/groovy/org/grails/cli/profile/repository/MavenRepositorySpec.groovy deleted file mode 100644 index 2b2586bcb8b..00000000000 --- a/grails-shell/src/test/groovy/org/grails/cli/profile/repository/MavenRepositorySpec.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package org.grails.cli.profile.repository - -import spock.lang.Ignore -import spock.lang.Specification - - - -/** - * @author graemerocher - */ -class MavenRepositorySpec extends Specification { - - @Ignore - void "Test resolve profile"() { - given:"A maven profile repository" - def repo = new MavenProfileRepository() - - when:"We resolve the web profile" - def profile = repo.getProfile("web") - - then:"The profile is not null" - profile != null - profile.name == 'web' - } - - @Ignore - void "Test list all profiles"() { - given:"A maven profile repository" - def repo = new MavenProfileRepository() - - when:"We resolve the web profile" - def profiles = repo.allProfiles - - then:"The profiles are not null or empty" - profiles - } -} diff --git a/grails-shell/src/test/groovy/org/grails/cli/profile/steps/StepRegistrySpec.groovy b/grails-shell/src/test/groovy/org/grails/cli/profile/steps/StepRegistrySpec.groovy deleted file mode 100644 index f82b8701eca..00000000000 --- a/grails-shell/src/test/groovy/org/grails/cli/profile/steps/StepRegistrySpec.groovy +++ /dev/null @@ -1,31 +0,0 @@ -package org.grails.cli.profile.steps - -import org.grails.cli.profile.commands.ClosureExecutingCommand -import spock.lang.Specification - -/* - * Copyright 2014 original 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 - * - * 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. - */ - -/** - * @author graemerocher - */ -class StepRegistrySpec extends Specification { - - void "Test the step registry finds registered steps"() { - expect:"The step registry to find steps" - StepRegistry.getStep("render", new ClosureExecutingCommand("test", {}), [foo:true]) instanceof RenderStep - } -} diff --git a/grails-shell/src/test/resources/gradle-sample/build.gradle b/grails-shell/src/test/resources/gradle-sample/build.gradle deleted file mode 100644 index d6ef8c0d4f5..00000000000 --- a/grails-shell/src/test/resources/gradle-sample/build.gradle +++ /dev/null @@ -1,5 +0,0 @@ -apply plugin:'java' - -subprojects { - task hello << {println "Hello World!"} -} diff --git a/grails-shell/src/test/resources/gradle-sample/gradle/wrapper/gradle-wrapper.jar b/grails-shell/src/test/resources/gradle-sample/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 3d0dee6e8edfecc92e04653ec780de06f7b34f8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51017 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 H-~Rf4?cF@p diff --git a/grails-shell/src/test/resources/gradle-sample/gradle/wrapper/gradle-wrapper.properties b/grails-shell/src/test/resources/gradle-sample/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a1b81796d7e..00000000000 --- a/grails-shell/src/test/resources/gradle-sample/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Sep 30 10:07:59 EEST 2014 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-bin.zip diff --git a/grails-shell/src/test/resources/gradle-sample/gradlew b/grails-shell/src/test/resources/gradle-sample/gradlew deleted file mode 100755 index 91a7e269e19..00000000000 --- a/grails-shell/src/test/resources/gradle-sample/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# 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\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/grails-shell/src/test/resources/gradle-sample/gradlew.bat b/grails-shell/src/test/resources/gradle-sample/gradlew.bat deleted file mode 100644 index aec99730b4e..00000000000 --- a/grails-shell/src/test/resources/gradle-sample/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/grails-shell/src/test/resources/gradle-sample/settings.gradle b/grails-shell/src/test/resources/gradle-sample/settings.gradle deleted file mode 100644 index 295eb0ef438..00000000000 --- a/grails-shell/src/test/resources/gradle-sample/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include 'subproj', 'subproj2' \ No newline at end of file diff --git a/grails-shell/src/test/resources/gradle-sample/subproj/build.gradle b/grails-shell/src/test/resources/gradle-sample/subproj/build.gradle deleted file mode 100644 index 27039c509b6..00000000000 --- a/grails-shell/src/test/resources/gradle-sample/subproj/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -apply plugin:'java' - -task hello2 << {println "Another hello world!"} diff --git a/grails-shell/src/test/resources/gradle-sample/subproj2/build.gradle b/grails-shell/src/test/resources/gradle-sample/subproj2/build.gradle deleted file mode 100644 index d8e1a654889..00000000000 --- a/grails-shell/src/test/resources/gradle-sample/subproj2/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -apply plugin:'java' - -task hello3 << {println "Third hello world!"} diff --git a/grails-shell/src/test/resources/profiles-repository/profiles/web/commands/TestGroovy.groovy b/grails-shell/src/test/resources/profiles-repository/profiles/web/commands/TestGroovy.groovy deleted file mode 100644 index 2107e6413e9..00000000000 --- a/grails-shell/src/test/resources/profiles-repository/profiles/web/commands/TestGroovy.groovy +++ /dev/null @@ -1,3 +0,0 @@ -description "Tests out a Groovy script", "grails test-groovy" - -println "good" \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index bd3500c886d..597f27c5839 100644 --- a/settings.gradle +++ b/settings.gradle @@ -40,7 +40,6 @@ include ( 'grails-docs', 'grails-encoder', 'grails-logging', - 'grails-shell', 'grails-spring', 'grails-test', 'grails-web', From 204c20b769e5c395301233b76c7e9bcee3217f74 Mon Sep 17 00:00:00 2001 From: Guillermo Calvo Date: Fri, 8 Mar 2024 09:16:29 +0100 Subject: [PATCH 2/2] Update Gradle build file --- gradle/assemble.gradle | 48 ++---------------------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/gradle/assemble.gradle b/gradle/assemble.gradle index eddeccc314a..7852fbf1ae6 100644 --- a/gradle/assemble.gradle +++ b/gradle/assemble.gradle @@ -6,7 +6,7 @@ def libsConfigurations = [] subprojects { subproject -> if(subproject.name == 'grails-dependencies') return if(subproject.name == 'grails-bom') return - if(subproject.name == 'grails-shell' || subproject.name == 'grails-core') { + if(subproject.name == 'grails-core') { configurations { libsConfigurations << libs { @@ -137,57 +137,13 @@ task sourcesJars(type: Sync) { from { sourcesFor(libsConfigurations*.copyRecursive { it.name.startsWith('grails-datastore') }.collect { it.transitive = false; it }) } } -task grailsCreateStartScripts(type: GrailsCreateStartScripts) { - description = "Creates OS specific scripts to run grails-shell as a JVM application." - mainClass.set('org.grails.cli.GrailsCli') - applicationName = 'grails' - defaultJvmOpts = ["-XX:+TieredCompilation", "-XX:TieredStopAtLevel=1", "-XX:CICompilerCount=3"] - outputDir = file('bin') - classpath = rootProject.childProjects['grails-shell'].configurations.runtimeClasspath - projectArtifacts = rootProject.childProjects['grails-shell'].tasks['jar'].outputs.files.collect { "dist/${it.name}" } - doLast { - ant.replace(file: file('bin/grails'), token: 'media/gradle.icns', value: 'media/icons/grails.icns') - ant.chmod(file: file('bin/grails'), perm: 'ugo+rx') - } -} - -class GrailsCreateStartScripts extends org.gradle.api.tasks.application.CreateStartScripts { - - @Input - Collection projectArtifacts=[] - - @org.gradle.api.tasks.TaskAction - void generate() { - def generator = new org.gradle.api.internal.plugins.StartScriptGenerator() - generator.unixStartScriptGenerator.template = project.rootProject.childProjects['grails-shell'].resources.text.fromFile('src/main/resources/unixStartScript.txt') - generator.applicationName = getApplicationName() - generator.mainClassName = getMainClassName() - generator.defaultJvmOpts = getDefaultJvmOpts() - generator.optsEnvironmentVar = getOptsEnvironmentVar() - generator.exitEnvironmentVar = getExitEnvironmentVar() - generator.classpath = projectArtifacts + getClasspath().resolvedConfiguration.resolvedArtifacts.collect { artifact -> - def dependency = artifact.moduleVersion.id - String installedFile = "lib/$dependency.group/$dependency.name/jars/$artifact.file.name" - if(dependency.group=='org.grails' && !project.file(installedFile).exists()) { - installedFile = "dist/$artifact.file.name" - } - installedFile - } - generator.scriptRelPath = "bin/${getUnixScript().name}" - generator.generateUnixScript(getUnixScript()) - generator.generateWindowsScript(getWindowsScript()) - } -} - -task install(dependsOn: [populateDependencies, grailsCreateStartScripts]) { task -> +task install(dependsOn: [populateDependencies]) { task -> subprojects { Project project -> if(!project.name.startsWith('grails-test-suite')) { task.dependsOn("$project.name:publishToMavenLocal") } } } -//task install(dependsOn: [populateDependencies, grailsCreateStartScripts] + subprojects.findAll { !it.name.startsWith('grails-test-suite') } -// *.collect { Project p -> p.tasks.withType(PublishToMavenLocal)}) task zipDist(type: Zip, dependsOn: [sourcesJars, install]) { destinationDir = "${buildDir}/distributions" as File