diff --git a/spring-boot-cli/grab-samples/grab.groovy b/spring-boot-cli/grab-samples/grab.groovy new file mode 100644 index 00000000000..05a3b9d5fd8 --- /dev/null +++ b/spring-boot-cli/grab-samples/grab.groovy @@ -0,0 +1,4 @@ +@Grab('spring-jdbc') +class GrabTest { + +} \ No newline at end of file diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/CompilerOptionHandler.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/CompilerOptionHandler.java new file mode 100644 index 00000000000..dce0d79c8b9 --- /dev/null +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/CompilerOptionHandler.java @@ -0,0 +1,63 @@ +/* + * 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 joptsimple.OptionSpec; + +import static java.util.Arrays.asList; + +/** + * An {@link OptionHandler} for commands that result in the compilation of one or more + * Groovy scripts + * + * @author Andy Wilkinson + */ +public class CompilerOptionHandler extends OptionHandler { + + private OptionSpec noGuessImportsOption; + + private OptionSpec noGuessDependenciesOption; + + private OptionSpec classpathOption; + + @Override + protected final void options() { + this.noGuessImportsOption = option("no-guess-imports", + "Do not attempt to guess imports"); + this.noGuessDependenciesOption = option("no-guess-dependencies", + "Do not attempt to guess dependencies"); + this.classpathOption = option(asList("classpath", "cp"), + "Additional classpath entries").withRequiredArg(); + doOptions(); + } + + protected void doOptions() { + } + + public OptionSpec getNoGuessImportsOption() { + return this.noGuessImportsOption; + } + + public OptionSpec getNoGuessDependenciesOption() { + return this.noGuessDependenciesOption; + } + + public OptionSpec getClasspathOption() { + return this.classpathOption; + } + +} diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/DefaultCommandFactory.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/DefaultCommandFactory.java index 08d7dc1b6d4..ca05222207e 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/DefaultCommandFactory.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/DefaultCommandFactory.java @@ -30,9 +30,9 @@ import org.springframework.boot.cli.CommandFactory; */ public class DefaultCommandFactory implements CommandFactory { - private static final List DEFAULT_COMMANDS = Arrays - . asList(new VersionCommand(), new RunCommand(), new CleanCommand(), - new TestCommand()); + private static final List DEFAULT_COMMANDS = Arrays. asList( + new VersionCommand(), new RunCommand(), new CleanCommand(), + new TestCommand(), new GrabCommand()); @Override public Collection getCommands() { diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/GrabCommand.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/GrabCommand.java new file mode 100644 index 00000000000..28cde0dfd79 --- /dev/null +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/GrabCommand.java @@ -0,0 +1,74 @@ +/* + * 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 java.io.File; +import java.util.List; + +import joptsimple.OptionSet; + +import org.springframework.boot.cli.Command; +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.RepositoryConfigurationFactory; +import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; +import org.springframework.util.StringUtils; + +/** + * {@link Command} to grab the dependencies of one or more Groovy scripts + * + * @author Andy Wilkinson + */ +public class GrabCommand extends OptionParsingCommand { + + public GrabCommand() { + super("grab", "Download a spring groovy script's dependencies to ./repository", + new GrabOptionHandler()); + } + + private static final class GrabOptionHandler extends CompilerOptionHandler { + + @Override + protected void run(OptionSet options) throws Exception { + FileOptions fileOptions = new FileOptions(options); + + List repositoryConfiguration = RepositoryConfigurationFactory + .createDefaultRepositoryConfiguration(); + repositoryConfiguration.add(0, new RepositoryConfiguration("local", new File( + getM2HomeDirectory(), "repository").toURI(), true)); + + GroovyCompilerConfiguration configuration = new GroovyCompilerConfigurationAdapter( + options, this, repositoryConfiguration); + + if (System.getProperty("grape.root") == null) { + System.setProperty("grape.root", "."); + } + + GroovyCompiler groovyCompiler = new GroovyCompiler(configuration); + groovyCompiler.compile(fileOptions.getFilesArray()); + } + + private File getM2HomeDirectory() { + String mavenRoot = System.getProperty("maven.home"); + if (StringUtils.hasLength(mavenRoot)) { + return new File(mavenRoot); + } + return new File(System.getProperty("user.home"), ".m2"); + } + } +} diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/RunCommand.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/RunCommand.java index 5cc3357836e..78667de4e52 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/RunCommand.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/RunCommand.java @@ -17,13 +17,18 @@ package org.springframework.boot.cli.command; import java.awt.Desktop; +import java.io.File; +import java.util.List; import java.util.logging.Level; import joptsimple.OptionSet; import joptsimple.OptionSpec; import org.springframework.boot.cli.Command; +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; import org.springframework.boot.cli.runner.SpringApplicationRunner; import org.springframework.boot.cli.runner.SpringApplicationRunnerConfiguration; @@ -53,41 +58,25 @@ public class RunCommand extends OptionParsingCommand { } } - private static class RunOptionHandler extends OptionHandler { + private static class RunOptionHandler extends CompilerOptionHandler { private OptionSpec watchOption; private OptionSpec editOption; - private OptionSpec noGuessImportsOption; - - private OptionSpec noGuessDependenciesOption; - private OptionSpec verboseOption; private OptionSpec quietOption; - private OptionSpec localOption; - - private OptionSpec classpathOption; - private SpringApplicationRunner runner; @Override - protected void options() { + protected void doOptions() { this.watchOption = option("watch", "Watch the specified file for changes"); - this.localOption = option("local", - "Accumulate the dependencies in a local folder (./repository)"); this.editOption = option(asList("edit", "e"), "Open the file with the default system editor"); - this.noGuessImportsOption = option("no-guess-imports", - "Do not attempt to guess imports"); - this.noGuessDependenciesOption = option("no-guess-dependencies", - "Do not attempt to guess dependencies"); this.verboseOption = option(asList("verbose", "v"), "Verbose logging"); this.quietOption = option(asList("quiet", "q"), "Quiet logging"); - this.classpathOption = option(asList("classpath", "cp"), - "Additional classpath entries").withRequiredArg(); } @Override @@ -98,11 +87,14 @@ public class RunCommand extends OptionParsingCommand { Desktop.getDesktop().edit(fileOptions.getFiles().get(0)); } + List repositoryConfiguration = RepositoryConfigurationFactory + .createDefaultRepositoryConfiguration(); + repositoryConfiguration.add(0, new RepositoryConfiguration("local", new File( + "repository").toURI(), true)); + SpringApplicationRunnerConfiguration configuration = new SpringApplicationRunnerConfigurationAdapter( - options); - if (configuration.isLocal() && System.getProperty("grape.root") == null) { - System.setProperty("grape.root", "."); - } + options, this, repositoryConfiguration); + this.runner = new SpringApplicationRunner(configuration, fileOptions.getFilesArray(), fileOptions.getArgsArray()); this.runner.compileAndRun(); @@ -112,13 +104,14 @@ public class RunCommand extends OptionParsingCommand { * Simple adapter class to present the {@link OptionSet} as a * {@link SpringApplicationRunnerConfiguration}. */ - private class SpringApplicationRunnerConfigurationAdapter implements + private class SpringApplicationRunnerConfigurationAdapter extends + GroovyCompilerConfigurationAdapter implements SpringApplicationRunnerConfiguration { - private OptionSet options; - - public SpringApplicationRunnerConfigurationAdapter(OptionSet options) { - this.options = options; + public SpringApplicationRunnerConfigurationAdapter(OptionSet options, + CompilerOptionHandler optionHandler, + List repositoryConfiguration) { + super(options, optionHandler, repositoryConfiguration); } @Override @@ -128,44 +121,19 @@ public class RunCommand extends OptionParsingCommand { @Override public boolean isWatchForFileChanges() { - return this.options.has(RunOptionHandler.this.watchOption); - } - - @Override - public boolean isGuessImports() { - return !this.options.has(RunOptionHandler.this.noGuessImportsOption); - } - - @Override - public boolean isGuessDependencies() { - return !this.options.has(RunOptionHandler.this.noGuessDependenciesOption); - } - - @Override - public boolean isLocal() { - return this.options.has(RunOptionHandler.this.localOption); + return getOptions().has(RunOptionHandler.this.watchOption); } @Override public Level getLogLevel() { - if (this.options.has(RunOptionHandler.this.verboseOption)) { + if (getOptions().has(RunOptionHandler.this.verboseOption)) { return Level.FINEST; } - if (this.options.has(RunOptionHandler.this.quietOption)) { + if (getOptions().has(RunOptionHandler.this.quietOption)) { return Level.OFF; } return Level.INFO; } - - @Override - public String[] getClasspath() { - if (this.options.has(RunOptionHandler.this.classpathOption)) { - return this.options.valueOf(RunOptionHandler.this.classpathOption) - .split(":"); - } - return NO_CLASSPATH; - } - } } diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/ScriptCommand.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/ScriptCommand.java index 0c248514d9a..a615134d0b3 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/ScriptCommand.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/ScriptCommand.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.net.URL; import java.util.Collection; import java.util.Collections; +import java.util.List; import joptsimple.OptionParser; @@ -37,6 +38,8 @@ import org.springframework.boot.cli.OptionHelp; import org.springframework.boot.cli.compiler.GroovyCompiler; import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration; import org.springframework.boot.cli.compiler.GroovyCompilerScope; +import org.springframework.boot.cli.compiler.RepositoryConfigurationFactory; +import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; import org.springframework.util.FileCopyUtils; /** @@ -271,6 +274,11 @@ public class ScriptCommand implements Command { return NO_CLASSPATH; } + @Override + public List getRepositoryConfiguration() { + return RepositoryConfigurationFactory.createDefaultRepositoryConfiguration(); + } + } } diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/TestCommand.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/TestCommand.java index b612f066b52..6b7079f09bd 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/TestCommand.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/TestCommand.java @@ -17,15 +17,12 @@ package org.springframework.boot.cli.command; import joptsimple.OptionSet; -import joptsimple.OptionSpec; import org.springframework.boot.cli.Command; -import org.springframework.boot.cli.compiler.GroovyCompilerScope; +import org.springframework.boot.cli.compiler.GroovyCompilerConfigurationAdapter; import org.springframework.boot.cli.testrunner.TestRunner; import org.springframework.boot.cli.testrunner.TestRunnerConfiguration; -import static java.util.Arrays.asList; - /** * {@link Command} to run a groovy test script or scripts. * @@ -43,31 +40,15 @@ public class TestCommand extends OptionParsingCommand { return "[options] [--] [args]"; } - private static class TestOptionHandler extends OptionHandler { - - private OptionSpec noGuessImportsOption; - - private OptionSpec noGuessDependenciesOption; - - private OptionSpec classpathOption; + private static class TestOptionHandler extends CompilerOptionHandler { private TestRunner runner; - @Override - protected void options() { - this.noGuessImportsOption = option("no-guess-imports", - "Do not attempt to guess imports"); - this.noGuessDependenciesOption = option("no-guess-dependencies", - "Do not attempt to guess dependencies"); - this.classpathOption = option(asList("classpath", "cp"), - "Additional classpath entries").withRequiredArg(); - } - @Override protected void run(OptionSet options) throws Exception { FileOptions fileOptions = new FileOptions(options); TestRunnerConfiguration configuration = new TestRunnerConfigurationAdapter( - options); + options, this); this.runner = new TestRunner(configuration, fileOptions.getFilesArray(), fileOptions.getArgsArray()); this.runner.compileAndRunTests(); @@ -77,39 +58,13 @@ public class TestCommand extends OptionParsingCommand { * Simple adapter class to present the {@link OptionSet} as a * {@link TestRunnerConfiguration}. */ - private class TestRunnerConfigurationAdapter implements TestRunnerConfiguration { + private class TestRunnerConfigurationAdapter extends + GroovyCompilerConfigurationAdapter implements TestRunnerConfiguration { - private OptionSet options; - - public TestRunnerConfigurationAdapter(OptionSet options) { - this.options = options; + public TestRunnerConfigurationAdapter(OptionSet options, + CompilerOptionHandler optionHandler) { + super(options, optionHandler); } - - @Override - public GroovyCompilerScope getScope() { - return GroovyCompilerScope.DEFAULT; - } - - @Override - public boolean isGuessImports() { - return !this.options.has(TestOptionHandler.this.noGuessImportsOption); - } - - @Override - public boolean isGuessDependencies() { - return !this.options - .has(TestOptionHandler.this.noGuessDependenciesOption); - } - - @Override - public String[] getClasspath() { - if (this.options.has(TestOptionHandler.this.classpathOption)) { - return this.options.valueOf(TestOptionHandler.this.classpathOption) - .split(":"); - } - return NO_CLASSPATH; - } - } } } 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 3a06e3586cc..d575a56e0f4 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 @@ -41,8 +41,11 @@ import org.codehaus.groovy.control.customizers.CompilationCustomizer; import org.codehaus.groovy.control.customizers.ImportCustomizer; import org.codehaus.groovy.transform.ASTTransformation; import org.codehaus.groovy.transform.ASTTransformationVisitor; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.repository.RepositoryPolicy; 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.ResolveDependencyCoordinatesTransformation; @@ -88,7 +91,8 @@ public class GroovyCompiler { this.loader = createLoader(configuration); this.coordinatesResolver = new PropertiesArtifactCoordinatesResolver(this.loader); - GrapeEngineInstaller.install(new AetherGrapeEngine(this.loader)); + GrapeEngineInstaller.install(new AetherGrapeEngine(this.loader, + createRepositories(configuration.getRepositoryConfiguration()))); this.loader.getConfiguration().addCompilationCustomizers( new CompilerAutoConfigureCustomizer()); @@ -115,6 +119,26 @@ public class GroovyCompiler { return loader; } + private List createRepositories( + List repositoryConfigurations) { + List repositories = new ArrayList( + repositoryConfigurations.size()); + for (RepositoryConfiguration repositoryConfiguration : repositoryConfigurations) { + RemoteRepository.Builder builder = new RemoteRepository.Builder( + repositoryConfiguration.getName(), "default", repositoryConfiguration + .getUri().toASCIIString()); + + if (!repositoryConfiguration.getSnapshotsEnabled()) { + builder.setSnapshotPolicy(new RepositoryPolicy(false, + RepositoryPolicy.UPDATE_POLICY_NEVER, + RepositoryPolicy.CHECKSUM_POLICY_IGNORE)); + } + + repositories.add(builder.build()); + } + return repositories; + } + public void addCompilationCustomizers(CompilationCustomizer... customizers) { this.loader.getConfiguration().addCompilationCustomizers(customizers); } diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerConfiguration.java index dea85bc990f..233869c12ed 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerConfiguration.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerConfiguration.java @@ -16,15 +16,20 @@ package org.springframework.boot.cli.compiler; +import java.util.List; + +import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; + /** * Configuration for the {@link GroovyCompiler}. * * @author Phillip Webb + * @author Andy Wilkinson */ public interface GroovyCompilerConfiguration { /** - * Constant to be used when there is not {@link #getClasspath() classpath}. + * Constant to be used when there is no {@link #getClasspath() classpath}. */ public static final String[] NO_CLASSPATH = {}; @@ -48,4 +53,10 @@ public interface GroovyCompilerConfiguration { */ String[] getClasspath(); + /** + * @return the configuration for the repositories that will be used by the compiler to + * resolve dependencies. + */ + List getRepositoryConfiguration(); + } diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerConfigurationAdapter.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerConfigurationAdapter.java new file mode 100644 index 00000000000..b2688e5c4d0 --- /dev/null +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompilerConfigurationAdapter.java @@ -0,0 +1,87 @@ +/* + * 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.compiler; + +import java.util.List; + +import joptsimple.OptionSet; +import joptsimple.OptionSpec; + +import org.springframework.boot.cli.command.CompilerOptionHandler; +import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; + +/** + * Simple adapter class to present an {@link OptionSet} as a + * {@link GroovyCompilerConfiguration} + * + * @author Andy Wilkinson + */ +public class GroovyCompilerConfigurationAdapter implements GroovyCompilerConfiguration { + + private final OptionSet options; + + private final CompilerOptionHandler optionHandler; + + private final List repositoryConfiguration; + + protected GroovyCompilerConfigurationAdapter(OptionSet optionSet, + CompilerOptionHandler compilerOptionHandler) { + this(optionSet, compilerOptionHandler, RepositoryConfigurationFactory + .createDefaultRepositoryConfiguration()); + } + + public GroovyCompilerConfigurationAdapter(OptionSet optionSet, + CompilerOptionHandler compilerOptionHandler, + List repositoryConfiguration) { + this.options = optionSet; + this.optionHandler = compilerOptionHandler; + this.repositoryConfiguration = repositoryConfiguration; + } + + protected OptionSet getOptions() { + return this.options; + } + + @Override + public GroovyCompilerScope getScope() { + return GroovyCompilerScope.DEFAULT; + } + + @Override + public boolean isGuessImports() { + return !this.options.has(this.optionHandler.getNoGuessImportsOption()); + } + + @Override + public boolean isGuessDependencies() { + return !this.options.has(this.optionHandler.getNoGuessDependenciesOption()); + } + + @Override + public String[] getClasspath() { + OptionSpec classpathOption = this.optionHandler.getClasspathOption(); + if (this.options.has(classpathOption)) { + return this.options.valueOf(classpathOption).split(":"); + } + return NO_CLASSPATH; + } + + @Override + public List getRepositoryConfiguration() { + return this.repositoryConfiguration; + } +} 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 new file mode 100644 index 00000000000..df560c3b10c --- /dev/null +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java @@ -0,0 +1,54 @@ +/* + * 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.compiler; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; + +/** + * @author Andy Wilkinson + */ +public final class RepositoryConfigurationFactory { + + private static final RepositoryConfiguration MAVEN_CENTRAL = new RepositoryConfiguration( + "central", URI.create("http://repo1.maven.org/maven2/"), false); + + private static final RepositoryConfiguration SPRING_MILESTONE = new RepositoryConfiguration( + "spring-milestone", URI.create("http://repo.spring.io/milestone"), false); + + private static final RepositoryConfiguration SPRING_SNAPSHOT = new RepositoryConfiguration( + "spring-snapshot", URI.create("http://repo.spring.io/snapshot"), true); + + /** + * @return the newly-created default repository configuration + */ + public static List createDefaultRepositoryConfiguration() { + List repositoryConfiguration = new ArrayList(); + + repositoryConfiguration.add(MAVEN_CENTRAL); + + if (!Boolean.getBoolean("disableSpringSnapshotRepos")) { + repositoryConfiguration.add(SPRING_SNAPSHOT); + repositoryConfiguration.add(SPRING_MILESTONE); + } + + return 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 dba7010833b..60487a5a99b 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 @@ -25,10 +25,8 @@ import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.eclipse.aether.DefaultRepositorySystemSession; @@ -80,9 +78,10 @@ public class AetherGrapeEngine implements GrapeEngine { private final RepositorySystem repositorySystem; - private final Set repositories; + private final List repositories; - public AetherGrapeEngine(GroovyClassLoader classLoader) { + public AetherGrapeEngine(GroovyClassLoader classLoader, + List remoteRepositories) { this.classLoader = classLoader; this.repositorySystem = createServiceLocator().getService(RepositorySystem.class); DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); @@ -91,7 +90,7 @@ public class AetherGrapeEngine implements GrapeEngine { .newLocalRepositoryManager(session, localRepository); session.setLocalRepositoryManager(localRepositoryManager); this.session = session; - this.repositories = getRemoteRepositories(); + this.repositories = new ArrayList(remoteRepositories); this.progressReporter = getProgressReporter(session); } @@ -125,22 +124,6 @@ public class AetherGrapeEngine implements GrapeEngine { return new File(System.getProperty("user.home"), ".m2"); } - private Set getRemoteRepositories() { - LinkedHashSet repositories = new LinkedHashSet(); - String grapeRoot = System.getProperty("grape.root"); - if (StringUtils.hasLength(grapeRoot)) { - addRemoteRepository(repositories, "local", new File( - getDefaultM2HomeDirectory(), "repository").toURI().toASCIIString()); - } - addRemoteRepository(repositories, "central", "http://repo1.maven.org/maven2/"); - return repositories; - } - - private void addRemoteRepository(Set repositories, String id, - String url) { - repositories.add(new RemoteRepository.Builder(id, "default", url).build()); - } - private ProgressReporter getProgressReporter(DefaultRepositorySystemSession session) { if (Boolean.getBoolean("groovy.grape.report.downloads")) { return new DetailedProgressReporter(session, System.out); @@ -263,7 +246,8 @@ public class AetherGrapeEngine implements GrapeEngine { String name = (String) args.get("name"); String root = (String) args.get("root"); - addRemoteRepository(this.repositories, name, root); + this.repositories + .add(new RemoteRepository.Builder(name, "default", root).build()); } @Override diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/RepositoryConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/RepositoryConfiguration.java new file mode 100644 index 00000000000..601c7db0b39 --- /dev/null +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/RepositoryConfiguration.java @@ -0,0 +1,70 @@ +/* + * 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.compiler.grape; + +import java.net.URI; + +/** + * The configuration of a repository + * + * @author Andy Wilkinson + */ +public final class RepositoryConfiguration { + + private final String name; + + private final URI uri; + + private final boolean snapshotsEnabled; + + /** + * Creates a new {@code RepositoryConfiguration}. + * + * @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 RepositoryConfiguration(String name, URI uri, boolean snapshotsEnabled) { + this.name = name; + this.uri = uri; + this.snapshotsEnabled = snapshotsEnabled; + } + + /** + * @return the name of the repository + */ + public String getName() { + return this.name; + } + + /** + * @return the uri of the repository + */ + public URI getUri() { + return this.uri; + } + + /** + * @return {@code true} if the repository should enable access to snapshots, + * {@code false} otherwise + */ + public boolean getSnapshotsEnabled() { + return this.snapshotsEnabled; + } + +} \ No newline at end of file diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/runner/SpringApplicationRunnerConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/runner/SpringApplicationRunnerConfiguration.java index c587111f558..1c31131001e 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/runner/SpringApplicationRunnerConfiguration.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/runner/SpringApplicationRunnerConfiguration.java @@ -37,10 +37,4 @@ public interface SpringApplicationRunnerConfiguration extends GroovyCompilerConf * Returns the logging level to use. */ Level getLogLevel(); - - /** - * Returns {@code true} if the dependencies should be cached locally - */ - boolean isLocal(); - } diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/CliTester.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/CliTester.java index 7431e4e5370..2f1121b2884 100644 --- a/spring-boot-cli/src/test/java/org/springframework/boot/cli/CliTester.java +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/CliTester.java @@ -34,6 +34,8 @@ import org.junit.runners.model.Statement; import org.springframework.boot.OutputCapture; import org.springframework.boot.cli.command.AbstractCommand; import org.springframework.boot.cli.command.CleanCommand; +import org.springframework.boot.cli.command.GrabCommand; +import org.springframework.boot.cli.command.OptionParsingCommand; import org.springframework.boot.cli.command.RunCommand; import org.springframework.boot.cli.command.TestCommand; @@ -42,6 +44,7 @@ import org.springframework.boot.cli.command.TestCommand; * * @author Phillip Webb * @author Dave Syer + * @author Andy Wilkinson */ public class CliTester implements TestRule { @@ -62,35 +65,35 @@ public class CliTester implements TestRule { } public String run(String... args) throws Exception { - final String[] sources = getSources(args); - Future future = Executors.newSingleThreadExecutor().submit( - new Callable() { - @Override - public RunCommand call() throws Exception { - RunCommand command = new RunCommand(); - command.run(sources); - return command; - } - }); + Future future = submitCommand(new RunCommand(), args); this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS)); return getOutput(); } public String test(String... args) throws Exception { - final String[] sources = getSources(args); - Future future = Executors.newSingleThreadExecutor().submit( - new Callable() { - @Override - public TestCommand call() throws Exception { - TestCommand command = new TestCommand(); - command.run(sources); - return command; - } - }); + Future future = submitCommand(new TestCommand(), args); this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS)); return getOutput(); } + public String grab(String... args) throws Exception { + Future future = submitCommand(new GrabCommand(), args); + this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS)); + return getOutput(); + } + + private Future submitCommand(final T command, + String... args) { + final String[] sources = getSources(args); + return Executors.newSingleThreadExecutor().submit(new Callable() { + @Override + public T call() throws Exception { + command.run(sources); + return command; + } + }); + } + protected String[] getSources(String... args) { final String[] sources = new String[args.length]; for (int i = 0; i < args.length; i++) { diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/GrabCommandIntegrationTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/GrabCommandIntegrationTests.java new file mode 100644 index 00000000000..bd2ef755411 --- /dev/null +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/GrabCommandIntegrationTests.java @@ -0,0 +1,62 @@ +/* + * 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; + +import java.io.File; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.springframework.boot.cli.command.GrabCommand; +import org.springframework.util.FileSystemUtils; + +import static org.junit.Assert.assertTrue; + +/** + * Integration tests for {@link GrabCommand} + * + * @author Andy Wilkinson + */ +public class GrabCommandIntegrationTests { + + @Rule + public CliTester cli = new CliTester("grab-samples/"); + + @Before + @After + public void deleteLocalRepository() { + FileSystemUtils.deleteRecursively(new File("target/repository")); + } + + @Test + public void grab() throws Exception { + System.setProperty("grape.root", "target"); + System.setProperty("groovy.grape.report.downloads", "true"); + + try { + String output = this.cli.grab("grab.groovy"); + assertTrue(output.contains("Downloading: file:")); + assertTrue(new File("target/repository/org/springframework/spring-jdbc") + .isDirectory()); + } + finally { + System.clearProperty("grape.root"); + System.clearProperty("groovy.grape.report.downloads"); + } + } +} diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/AetherGrapeEngineTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/AetherGrapeEngineTests.java index 21880af3d08..2debedf1520 100644 --- a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/AetherGrapeEngineTests.java +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/AetherGrapeEngineTests.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import org.eclipse.aether.repository.RemoteRepository; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -36,7 +37,8 @@ public class AetherGrapeEngineTests { private final GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); private final AetherGrapeEngine grapeEngine = new AetherGrapeEngine( - this.groovyClassLoader); + this.groovyClassLoader, Arrays.asList(new RemoteRepository.Builder("central", + "default", "http://repo1.maven.org/maven2/").build())); @Test public void dependencyResolution() {