From cd7b1b19c5fd62f24cb37fd444428569064c166b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 2 Jan 2014 08:52:36 +0000 Subject: [PATCH] Add InitCommand to execute groovy script on startup InitCommand runs on creation of SpringCli so it can search for additional Commands in updated classpath. Also added as interactive command in Shell session. --- spring-boot-cli/pom.xml | 56 +------ .../springframework/boot/cli/SpringCli.java | 18 +-- .../boot/cli/command/FileOptions.java | 30 +++- .../boot/cli/command/InitCommand.java | 141 ++++++++++++++++++ .../boot/cli/command/ShellCommand.java | 1 + .../compiler/ExtendedGroovyClassLoader.java | 2 +- .../boot/cli/compiler/GroovyCompiler.java | 7 +- .../cli/compiler/GroovyCompilerScope.java | 2 +- .../RepositoryConfigurationFactory.java | 2 +- .../cli/compiler/grape/AetherGrapeEngine.java | 3 + .../test/java/cli/command/CustomCommand.java | 35 +++++ .../cli/command/CustomCommandFactory.java | 36 +++++ .../boot/cli/command/InitCommandTests.java | 84 +++++++++++ ...rg.springframework.boot.cli.CommandFactory | 1 + .../custom/custom/0.0.1/custom-0.0.1.jar | Bin 0 -> 2710 bytes .../custom/custom/0.0.1/custom-0.0.1.pom | 0 .../src/test/resources/grab.groovy | 6 + .../src/test/resources/init.groovy | 1 + 18 files changed, 347 insertions(+), 78 deletions(-) create mode 100644 spring-boot-cli/src/main/java/org/springframework/boot/cli/command/InitCommand.java create mode 100644 spring-boot-cli/src/test/java/cli/command/CustomCommand.java create mode 100644 spring-boot-cli/src/test/java/cli/command/CustomCommandFactory.java create mode 100644 spring-boot-cli/src/test/java/org/springframework/boot/cli/command/InitCommandTests.java create mode 100644 spring-boot-cli/src/test/plugins/custom/META-INF/services/org.springframework.boot.cli.CommandFactory create mode 100644 spring-boot-cli/src/test/plugins/custom/custom/0.0.1/custom-0.0.1.jar create mode 100644 spring-boot-cli/src/test/plugins/custom/custom/0.0.1/custom-0.0.1.pom create mode 100644 spring-boot-cli/src/test/resources/grab.groovy create mode 100644 spring-boot-cli/src/test/resources/init.groovy diff --git a/spring-boot-cli/pom.xml b/spring-boot-cli/pom.xml index 33cf8056f86..9a1a12a95c4 100644 --- a/spring-boot-cli/pom.xml +++ b/spring-boot-cli/pom.xml @@ -233,14 +233,11 @@ true - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.JarLauncher ${start-class} - - groovy.lang.GroovyClassLoader - @@ -348,57 +345,6 @@ - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.apache.maven.plugins - maven-antrun-plugin - [1.7,) - - run - - - - - - - - - - org.apache.maven.plugins - - - maven-dependency-plugin - - - [2.8,) - - - - copy-dependencies - - - - - - - - - - - - - diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/SpringCli.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/SpringCli.java index 63f7135ba2d..ac61fe598e1 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/SpringCli.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/SpringCli.java @@ -22,10 +22,10 @@ import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.List; -import java.util.ServiceLoader; import java.util.Set; import org.springframework.boot.cli.command.AbstractCommand; +import org.springframework.boot.cli.command.InitCommand; /** * Spring Command Line Interface. This is the main entry-point for the Spring command line @@ -48,7 +48,7 @@ public class SpringCli { private static final Set NO_EXCEPTION_OPTIONS = EnumSet .noneOf(SpringCliException.Option.class); - private List commands; + private List commands = new ArrayList(); private String displayName = CLI_APP + " "; @@ -56,15 +56,11 @@ public class SpringCli { * Create a new {@link SpringCli} implementation with the default set of commands. */ public SpringCli() { - setCommands(ServiceLoader.load(CommandFactory.class, getClass().getClassLoader())); - } - - private void setCommands(Iterable iterable) { - this.commands = new ArrayList(); - for (CommandFactory factory : iterable) { - for (Command command : factory.getCommands(this)) { - this.commands.add(command); - } + try { + new InitCommand(this).run(); + } + catch (Exception e) { + throw new IllegalStateException("Cannot init with those args", e); } this.commands.add(0, new HelpCommand()); this.commands.add(new HintCommand()); diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/FileOptions.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/FileOptions.java index e6264883d9c..f38a723fb9f 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/FileOptions.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/FileOptions.java @@ -46,12 +46,20 @@ public class FileOptions { } /** - * Create a new {@link FileOptions} instance. + * Create a new {@link FileOptions} instance. If it is an error to pass options that + * specify non-existent files, but the default paths are allowed not to exist (the + * paths are tested before use). If default paths are provided and the option set + * contains no file arguments it is not an error even if none of the default paths + * exist). + * * @param optionSet the source option set * @param classLoader an optional classloader used to try and load files that are not - * found directly. + * found in the local filesystem + * @param defaultPaths the default paths to use if no files are provided in the option + * set */ - public FileOptions(OptionSet optionSet, ClassLoader classLoader) { + public FileOptions(OptionSet optionSet, ClassLoader classLoader, + String... defaultPaths) { List nonOptionArguments = optionSet.nonOptionArguments(); List files = new ArrayList(); for (Object option : nonOptionArguments) { @@ -63,18 +71,26 @@ public class FileOptions { if (filename.endsWith(".groovy") || filename.endsWith(".java")) { File file = getFile(filename, classLoader); if (file == null) { - throw new RuntimeException("Can't find " + filename); + throw new IllegalArgumentException("Can't find " + filename); } files.add(file); } } } + this.args = Collections.unmodifiableList(nonOptionArguments.subList(files.size(), + nonOptionArguments.size())); if (files.size() == 0) { - throw new RuntimeException("Please specify a file to run"); + if (defaultPaths.length == 0) { + throw new RuntimeException("Please specify at least one file to run"); + } + for (String path : defaultPaths) { + File file = getFile(path, classLoader); + if (file != null && file.exists()) { + files.add(file); + } + } } this.files = Collections.unmodifiableList(files); - this.args = Collections.unmodifiableList(nonOptionArguments.subList(files.size(), - nonOptionArguments.size())); } private File getFile(String filename, ClassLoader classLoader) { diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/InitCommand.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/InitCommand.java new file mode 100644 index 00000000000..272f7f48520 --- /dev/null +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/InitCommand.java @@ -0,0 +1,141 @@ +/* + * Copyright 2012-2013 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.springframework.boot.cli.command; + +import groovy.lang.GroovyClassLoader; +import groovy.lang.Script; + +import java.io.File; +import java.util.List; +import java.util.ServiceLoader; + +import joptsimple.OptionSet; + +import org.springframework.boot.cli.Command; +import org.springframework.boot.cli.CommandFactory; +import org.springframework.boot.cli.SpringCli; +import org.springframework.boot.cli.compiler.GroovyCompiler; +import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration; +import org.springframework.boot.cli.compiler.GroovyCompilerConfigurationAdapter; +import org.springframework.boot.cli.compiler.GroovyCompilerScope; +import org.springframework.boot.cli.compiler.RepositoryConfigurationFactory; +import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; + +/** + *

+ * Command to initialize the Spring CLI with commands from the classpath. If the current + * context class loader is a GroovyClassLoader then it can be enhanced by passing in + * compiler options (e.g. --classpath=...). + *

+ *

+ * If the current context class loader is not already GroovyClassLoader then one will be + * created and will replace the current context loader. In this case command arguments can + * include files to compile that have @Grab annotations to process. By + * default a script called "init.groovy" or "spring.groovy" is used if it exists in the + * current directory or the root of the classpath. + *

+ * + * @author Dave Syer + */ +public class InitCommand extends OptionParsingCommand { + + public static final String NAME = "init"; + + public InitCommand(SpringCli cli) { + super(NAME, "(Re)-initialize the Spring cli", new InitOptionHandler(cli)); + } + + private static class InitOptionHandler extends CompilerOptionHandler { + + private SpringCli cli; + private GroovyCompiler compiler; + + public InitOptionHandler(SpringCli cli) { + this.cli = cli; + } + + @Override + protected void run(OptionSet options) throws Exception { + + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + boolean enhanced = false; + + FileOptions fileOptions = new FileOptions(options, loader, "init.groovy", + "spring.groovy"); + File[] files = fileOptions.getFilesArray(); + + if (!(loader instanceof GroovyClassLoader)) { + + List repositoryConfiguration = RepositoryConfigurationFactory + .createDefaultRepositoryConfiguration(); + + GroovyCompilerConfiguration configuration = new InitGroovyCompilerConfigurationAdapter( + options, this, repositoryConfiguration); + + this.compiler = new GroovyCompiler(configuration); + loader = this.compiler.getLoader(); + Thread.currentThread().setContextClassLoader(loader); + + } + else { + String classpath = getClasspathOption().value(options); + if (classpath != null && classpath.length() > 0) { + ((GroovyClassLoader) loader).addClasspath(classpath); + enhanced = true; + } + } + + if (this.compiler != null && files.length > 0) { + Class[] classes = this.compiler.compile(files); + for (Class type : classes) { + if (Script.class.isAssignableFrom(type)) { + ((Script) type.newInstance()).run(); + } + } + enhanced = true; + } + + if (this.cli.getCommands().isEmpty() || enhanced) { + + for (CommandFactory factory : ServiceLoader.load(CommandFactory.class, + loader)) { + for (Command command : factory.getCommands(this.cli)) { + this.cli.register(command); + } + } + + } + + } + + } + + private static class InitGroovyCompilerConfigurationAdapter extends + GroovyCompilerConfigurationAdapter { + private InitGroovyCompilerConfigurationAdapter(OptionSet optionSet, + CompilerOptionHandler compilerOptionHandler, + List repositoryConfiguration) { + super(optionSet, compilerOptionHandler, repositoryConfiguration); + } + + @Override + public GroovyCompilerScope getScope() { + return GroovyCompilerScope.EXTENSION; + } + } + +} diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/ShellCommand.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/ShellCommand.java index f567b74a359..31d67e38ae8 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/ShellCommand.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/ShellCommand.java @@ -99,6 +99,7 @@ public class ShellCommand extends AbstractCommand { PromptCommand prompt = new PromptCommand(this); cli.register(prompt); + cli.register(new InitCommand(cli)); } private ConsoleReader createConsoleReader() throws IOException { diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/ExtendedGroovyClassLoader.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/ExtendedGroovyClassLoader.java index 11bf532d150..629196b1b05 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/ExtendedGroovyClassLoader.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/ExtendedGroovyClassLoader.java @@ -46,7 +46,7 @@ import org.springframework.util.FileCopyUtils; * @author Phillip Webb * @author Dave Syer */ -class ExtendedGroovyClassLoader extends GroovyClassLoader { +public class ExtendedGroovyClassLoader extends GroovyClassLoader { private static final String SHARED_PACKAGE = "org.springframework.boot.groovy"; diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompiler.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompiler.java index c8880af12c1..086f7df51b4 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompiler.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompiler.java @@ -48,7 +48,6 @@ import org.springframework.boot.cli.compiler.grape.AetherGrapeEngine; import org.springframework.boot.cli.compiler.grape.GrapeEngineInstaller; import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; import org.springframework.boot.cli.compiler.transformation.DependencyAutoConfigurationTransformation; -import org.springframework.boot.cli.compiler.transformation.GrabResolversAutoConfigurationTransformation; import org.springframework.boot.cli.compiler.transformation.GroovyBeansTransformation; import org.springframework.boot.cli.compiler.transformation.ResolveDependencyCoordinatesTransformation; @@ -108,7 +107,7 @@ public class GroovyCompiler { } this.transformations = new ArrayList(); - this.transformations.add(new GrabResolversAutoConfigurationTransformation()); + // this.transformations.add(new GrabResolversAutoConfigurationTransformation()); this.transformations.add(new DependencyAutoConfigurationTransformation( this.loader, this.coordinatesResolver, this.compilerAutoConfigurations)); this.transformations.add(new GroovyBeansTransformation()); @@ -118,6 +117,10 @@ public class GroovyCompiler { } } + public ExtendedGroovyClassLoader getLoader() { + return this.loader; + } + private ExtendedGroovyClassLoader createLoader( GroovyCompilerConfiguration configuration) { ExtendedGroovyClassLoader loader = new ExtendedGroovyClassLoader( diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerScope.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerScope.java index 6693313295f..e5784fc3124 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerScope.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerScope.java @@ -24,7 +24,7 @@ package org.springframework.boot.cli.compiler; public enum GroovyCompilerScope { /** - * Default scope, exposes groovy-all.jar (loaded from the parent) and the shared cli + * Default scope, exposes groovy.jar (loaded from the parent) and the shared cli * package (loaded via groovy classloader). */ DEFAULT, diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java index 413cfd2f1c6..e015ee1a72b 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java @@ -50,8 +50,8 @@ public final class RepositoryConfigurationFactory { repositoryConfiguration.add(MAVEN_CENTRAL); if (!Boolean.getBoolean("disableSpringSnapshotRepos")) { - repositoryConfiguration.add(SPRING_SNAPSHOT); repositoryConfiguration.add(SPRING_MILESTONE); + repositoryConfiguration.add(SPRING_SNAPSHOT); } addDefaultCacheAsRespository(repositoryConfiguration); diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/AetherGrapeEngine.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/AetherGrapeEngine.java index 96441a24590..fe24bc5e98e 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/AetherGrapeEngine.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/AetherGrapeEngine.java @@ -263,6 +263,9 @@ public class AetherGrapeEngine implements GrapeEngine { } protected void addRepository(RemoteRepository repository) { + if (this.repositories.contains(repository)) { + return; + } if (repository.getProxy() == null) { RemoteRepository.Builder builder = new RemoteRepository.Builder(repository); builder.setProxy(this.proxySelector.getProxy(repository)); diff --git a/spring-boot-cli/src/test/java/cli/command/CustomCommand.java b/spring-boot-cli/src/test/java/cli/command/CustomCommand.java new file mode 100644 index 00000000000..24c9a363825 --- /dev/null +++ b/spring-boot-cli/src/test/java/cli/command/CustomCommand.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2013 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 cli.command; + +import org.springframework.boot.cli.command.AbstractCommand; + +/** + * @author Dave Syer + */ +public class CustomCommand extends AbstractCommand { + + public CustomCommand() { + super("custom", "Custom command added in tests"); + } + + @Override + public void run(String... args) throws Exception { + System.err.println("Custom Command Hello"); + } + +} diff --git a/spring-boot-cli/src/test/java/cli/command/CustomCommandFactory.java b/spring-boot-cli/src/test/java/cli/command/CustomCommandFactory.java new file mode 100644 index 00000000000..0c0231a97a0 --- /dev/null +++ b/spring-boot-cli/src/test/java/cli/command/CustomCommandFactory.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012-2013 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 cli.command; + +import java.util.Collection; +import java.util.Collections; + +import org.springframework.boot.cli.Command; +import org.springframework.boot.cli.CommandFactory; +import org.springframework.boot.cli.SpringCli; + +/** + * @author Dave Syer + */ +public class CustomCommandFactory implements CommandFactory { + + @Override + public Collection getCommands(SpringCli cli) { + return Collections. singleton(new CustomCommand()); + } + +} diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/InitCommandTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/InitCommandTests.java new file mode 100644 index 00000000000..5587618e009 --- /dev/null +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/InitCommandTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012-2013 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.springframework.boot.cli.command; + +import groovy.lang.GroovyClassLoader; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.springframework.boot.OutputCapture; +import org.springframework.boot.cli.Command; +import org.springframework.boot.cli.SpringCli; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Dave Syer + */ +public class InitCommandTests { + + @Rule + public OutputCapture output = new OutputCapture(); + + private SpringCli cli = mock(SpringCli.class); + private InitCommand command = new InitCommand(this.cli); + private int defaultCount = new DefaultCommandFactory().getCommands(this.cli).size(); + private ClassLoader classLoader; + + @Before + public void init() { + this.classLoader = Thread.currentThread().getContextClassLoader(); + } + + @After + public void close() { + Thread.currentThread().setContextClassLoader(this.classLoader); + } + + @Test + public void explicitClasspath() throws Exception { + Thread.currentThread().setContextClassLoader(new GroovyClassLoader()); + this.command.run("--cp=src/test/plugins/custom/custom/0.0.1/custom-0.0.1.jar"); + verify(this.cli, times(this.defaultCount + 1)).register(any(Command.class)); + } + + @Test + public void initScript() throws Exception { + this.command.run("src/test/resources/grab.groovy"); + verify(this.cli, times(this.defaultCount + 1)).register(any(Command.class)); + assertTrue(this.output.toString().contains("Hello Grab")); + } + + @Test(expected = IllegalArgumentException.class) + public void initNonExistentScript() throws Exception { + this.command.run("nonexistent.groovy"); + } + + // There is an init.groovy on the test classpath so this succeeds + @Test + public void initDefault() throws Exception { + this.command.run(); + assertTrue(this.output.toString().contains("Hello World")); + } + +} diff --git a/spring-boot-cli/src/test/plugins/custom/META-INF/services/org.springframework.boot.cli.CommandFactory b/spring-boot-cli/src/test/plugins/custom/META-INF/services/org.springframework.boot.cli.CommandFactory new file mode 100644 index 00000000000..727204a63ad --- /dev/null +++ b/spring-boot-cli/src/test/plugins/custom/META-INF/services/org.springframework.boot.cli.CommandFactory @@ -0,0 +1 @@ +cli.command.CustomCommandFactory diff --git a/spring-boot-cli/src/test/plugins/custom/custom/0.0.1/custom-0.0.1.jar b/spring-boot-cli/src/test/plugins/custom/custom/0.0.1/custom-0.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..6623163c9317783856e79ad492f9da94a11c282c GIT binary patch literal 2710 zcmb_eOK%%h6h7CFj6HGsa9(wjwBrU^J5}tqDj;wv1UH5#c52B{B!omY9^blC#xvE- zxDbgAYs7{f5=(vnu%HMeHtf1Yhz0+Ji0{r!GLO1$kr?ZG?!Erb(kv$XJiu3 z-EYcwyh-qtrwnzr_qR58_FDC$r$pTt)Oz#l?E8RMquQjdFNHqs7RdX%-Q0!>_POUk1Tx%5nJ>u)uwNXWZ0h~7s#>p8OU8y`9q-S?T*v^FVJ&!U7 zG`DR=i#}er>RrUxMWnepLK=L7@oh$usC?Hzf)*#3t{#9m5^6_0DPjnkjPF^j-k>yQ zMEQ*(E2f@M`Uejps#pe;P-{6_r8&$BK9Ek)X{^4WGjtXRp=1khfzAI&nPT=Qnn@~A zprq_6S@MB_5{OWd=Al^JJ{i0hF_th-(QpFM#~$lmObAJ-1Z@@}O)wd#7_ebzMeM%Ax| zv8x;Prezph6J!#sL>w5sv>v3srw>il9ox7J9=x>NWc#Y!fA z6MhG8LA=>tDfJ=9`!i*}$I@q|ucGX!@M$+2sDJ>tTZF24550idqBmRW?y{8Z>7Lw7 z02O&o`UStWh>Iqhi%{+=rYEA2RwHVBQkM{F_%5m;(ldk}OzIj!`9CMh|A!tT>T0qD z5KTh(bdg9=s?#Jymcs|Pf9!foN+z3#Q1aV^WQ=G2jhIxHyjMeIf8iW2;@Gjy?2M4h N;qw~mao78&`4{wgdT9Uv literal 0 HcmV?d00001 diff --git a/spring-boot-cli/src/test/plugins/custom/custom/0.0.1/custom-0.0.1.pom b/spring-boot-cli/src/test/plugins/custom/custom/0.0.1/custom-0.0.1.pom new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-boot-cli/src/test/resources/grab.groovy b/spring-boot-cli/src/test/resources/grab.groovy new file mode 100644 index 00000000000..d9394424ca7 --- /dev/null +++ b/spring-boot-cli/src/test/resources/grab.groovy @@ -0,0 +1,6 @@ +@GrabResolver(name="test", root="file:./src/test/plugins") +@Grab("custom:custom:0.0.1") +@Controller +class Foo {} + +println "Hello Grab" \ No newline at end of file diff --git a/spring-boot-cli/src/test/resources/init.groovy b/spring-boot-cli/src/test/resources/init.groovy new file mode 100644 index 00000000000..31665bffc0d --- /dev/null +++ b/spring-boot-cli/src/test/resources/init.groovy @@ -0,0 +1 @@ +println "Hello World" \ No newline at end of file