Add grab command to collect script's dependencies

Previously, run --local could be used to collect a script's
dependencies in ./repository. However, with this mechanism it wasn't
possible to collect the dependencies without running the application.

This commit adds a new command, grab, that can be used to collect
a script's dependencies in ./repository without having to run it.
run is configured with ./repository as a location in which it can find
its dependencies so that the previously collected dependencies
can be used when subsequently running the app.

As part of this work RunCommand and TestCommand have been refactored
to use common code for their common options:

	--no-guess-imports
	--no-guess-dependencies
	--classpath

Previously, the declaration and handling of the options was duplicated
in the two classes. GrabCommand also has these three options and uses
the same common code.
This commit is contained in:
Andy Wilkinson 2013-11-11 17:07:22 +00:00
parent c50fe0733b
commit 820f43d3bc
17 changed files with 525 additions and 162 deletions

View File

@ -0,0 +1,4 @@
@Grab('spring-jdbc')
class GrabTest {
}

View File

@ -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<Void> noGuessImportsOption;
private OptionSpec<Void> noGuessDependenciesOption;
private OptionSpec<String> 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<Void> getNoGuessImportsOption() {
return this.noGuessImportsOption;
}
public OptionSpec<Void> getNoGuessDependenciesOption() {
return this.noGuessDependenciesOption;
}
public OptionSpec<String> getClasspathOption() {
return this.classpathOption;
}
}

View File

@ -30,9 +30,9 @@ import org.springframework.boot.cli.CommandFactory;
*/
public class DefaultCommandFactory implements CommandFactory {
private static final List<Command> DEFAULT_COMMANDS = Arrays
.<Command> asList(new VersionCommand(), new RunCommand(), new CleanCommand(),
new TestCommand());
private static final List<Command> DEFAULT_COMMANDS = Arrays.<Command> asList(
new VersionCommand(), new RunCommand(), new CleanCommand(),
new TestCommand(), new GrabCommand());
@Override
public Collection<Command> getCommands() {

View File

@ -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> 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");
}
}
}

View File

@ -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<Void> watchOption;
private OptionSpec<Void> editOption;
private OptionSpec<Void> noGuessImportsOption;
private OptionSpec<Void> noGuessDependenciesOption;
private OptionSpec<Void> verboseOption;
private OptionSpec<Void> quietOption;
private OptionSpec<Void> localOption;
private OptionSpec<String> 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> 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> 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;
}
}
}

View File

@ -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<RepositoryConfiguration> getRepositoryConfiguration() {
return RepositoryConfigurationFactory.createDefaultRepositoryConfiguration();
}
}
}

View File

@ -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] <files> [--] [args]";
}
private static class TestOptionHandler extends OptionHandler {
private OptionSpec<Void> noGuessImportsOption;
private OptionSpec<Void> noGuessDependenciesOption;
private OptionSpec<String> 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;
}
}
}
}

View File

@ -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<RemoteRepository> createRepositories(
List<RepositoryConfiguration> repositoryConfigurations) {
List<RemoteRepository> repositories = new ArrayList<RemoteRepository>(
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);
}

View File

@ -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<RepositoryConfiguration> getRepositoryConfiguration();
}

View File

@ -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> repositoryConfiguration;
protected GroovyCompilerConfigurationAdapter(OptionSet optionSet,
CompilerOptionHandler compilerOptionHandler) {
this(optionSet, compilerOptionHandler, RepositoryConfigurationFactory
.createDefaultRepositoryConfiguration());
}
public GroovyCompilerConfigurationAdapter(OptionSet optionSet,
CompilerOptionHandler compilerOptionHandler,
List<RepositoryConfiguration> 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<String> classpathOption = this.optionHandler.getClasspathOption();
if (this.options.has(classpathOption)) {
return this.options.valueOf(classpathOption).split(":");
}
return NO_CLASSPATH;
}
@Override
public List<RepositoryConfiguration> getRepositoryConfiguration() {
return this.repositoryConfiguration;
}
}

View File

@ -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<RepositoryConfiguration> createDefaultRepositoryConfiguration() {
List<RepositoryConfiguration> repositoryConfiguration = new ArrayList<RepositoryConfiguration>();
repositoryConfiguration.add(MAVEN_CENTRAL);
if (!Boolean.getBoolean("disableSpringSnapshotRepos")) {
repositoryConfiguration.add(SPRING_SNAPSHOT);
repositoryConfiguration.add(SPRING_MILESTONE);
}
return repositoryConfiguration;
}
}

View File

@ -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<RemoteRepository> repositories;
private final List<RemoteRepository> repositories;
public AetherGrapeEngine(GroovyClassLoader classLoader) {
public AetherGrapeEngine(GroovyClassLoader classLoader,
List<RemoteRepository> 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<RemoteRepository>(remoteRepositories);
this.progressReporter = getProgressReporter(session);
}
@ -125,22 +124,6 @@ public class AetherGrapeEngine implements GrapeEngine {
return new File(System.getProperty("user.home"), ".m2");
}
private Set<RemoteRepository> getRemoteRepositories() {
LinkedHashSet<RemoteRepository> repositories = new LinkedHashSet<RemoteRepository>();
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<RemoteRepository> 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

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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<RunCommand> future = Executors.newSingleThreadExecutor().submit(
new Callable<RunCommand>() {
@Override
public RunCommand call() throws Exception {
RunCommand command = new RunCommand();
command.run(sources);
return command;
}
});
Future<RunCommand> 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<TestCommand> future = Executors.newSingleThreadExecutor().submit(
new Callable<TestCommand>() {
@Override
public TestCommand call() throws Exception {
TestCommand command = new TestCommand();
command.run(sources);
return command;
}
});
Future<TestCommand> future = submitCommand(new TestCommand(), args);
this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS));
return getOutput();
}
public String grab(String... args) throws Exception {
Future<GrabCommand> future = submitCommand(new GrabCommand(), args);
this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS));
return getOutput();
}
private <T extends OptionParsingCommand> Future<T> submitCommand(final T command,
String... args) {
final String[] sources = getSources(args);
return Executors.newSingleThreadExecutor().submit(new Callable<T>() {
@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++) {

View File

@ -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");
}
}
}

View File

@ -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() {