Commit a5f16d46 authored by Dave Syer's avatar Dave Syer

Remove ScriptCommand support

InitCommand remains for now, so that you can @Grab a jar with
custom commands if you so choose.

Contributes to gh-212
parent c921c941
...@@ -16,12 +16,10 @@ ...@@ -16,12 +16,10 @@
package org.springframework.boot.cli.command; package org.springframework.boot.cli.command;
import groovy.lang.Closure;
import groovy.lang.GroovyClassLoader; import groovy.lang.GroovyClassLoader;
import groovy.lang.Script; import groovy.lang.Script;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import joptsimple.OptionSet; import joptsimple.OptionSet;
...@@ -101,8 +99,6 @@ public class InitCommand extends OptionParsingCommand { ...@@ -101,8 +99,6 @@ public class InitCommand extends OptionParsingCommand {
options, this, repositoryConfiguration); options, this, repositoryConfiguration);
this.compiler = new GroovyCompiler(configuration); this.compiler = new GroovyCompiler(configuration);
this.compiler
.addCompilationCustomizers(new ScriptCompilationCustomizer());
loader = this.compiler.getLoader(); loader = this.compiler.getLoader();
Thread.currentThread().setContextClassLoader(loader); Thread.currentThread().setContextClassLoader(loader);
...@@ -118,37 +114,9 @@ public class InitCommand extends OptionParsingCommand { ...@@ -118,37 +114,9 @@ public class InitCommand extends OptionParsingCommand {
if (this.compiler != null && sources.length > 0) { if (this.compiler != null && sources.length > 0) {
Class<?>[] classes = this.compiler.compile(sources); Class<?>[] classes = this.compiler.compile(sources);
for (Class<?> type : classes) { for (Class<?> type : classes) {
Command script = ScriptCommand.command(type); if (Script.class.isAssignableFrom(type)) {
if (script != null) { Script script = (Script) type.newInstance();
this.cli.register(script); script.run();
}
else if (CommandFactory.class.isAssignableFrom(type)) {
for (Command command : ((CommandFactory) type.newInstance())
.getCommands(this.cli)) {
this.cli.register(command);
}
}
else if (Commands.class.isAssignableFrom(type)) {
Commands instance = (Commands) type.newInstance();
Map<String, Closure<?>> commands = instance.getCommands();
Map<String, OptionHandler> handlers = instance.getOptions();
for (String command : commands.keySet()) {
if (handlers.containsKey(command)) {
// An OptionHandler is available
OptionHandler handler = handlers.get(command);
handler.setClosure(commands.get(command));
this.cli.register(new ScriptCommand(command, handler));
}
else {
// Otherwise just a plain Closure
this.cli.register(new ScriptCommand(command, commands
.get(command)));
}
}
}
else if (Script.class.isAssignableFrom(type)) {
((Script) type.newInstance()).run();
} }
} }
enhanced = true; enhanced = true;
...@@ -182,10 +150,4 @@ public class InitCommand extends OptionParsingCommand { ...@@ -182,10 +150,4 @@ public class InitCommand extends OptionParsingCommand {
} }
} }
public static interface Commands {
Map<String, Closure<?>> getCommands();
Map<String, OptionHandler> getOptions();
}
} }
/*
* 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.Closure;
import groovy.lang.GroovyObject;
import java.util.Collection;
import java.util.Collections;
import org.springframework.boot.cli.Command;
import org.springframework.boot.cli.OptionHelp;
/**
* {@link Command} to run a Groovy script.
*
* @author Dave Syer
*/
public class ScriptCommand implements Command {
private Object main;
private String defaultName;
public ScriptCommand(String name, Object main) {
this.main = main;
this.defaultName = name;
}
@Override
public String getName() {
if (this.main instanceof Command) {
return ((Command) this.main).getName();
}
else if (this.main instanceof GroovyObject) {
GroovyObject object = (GroovyObject) this.main;
if (object.getMetaClass().hasProperty(object, "name") != null) {
return (String) object.getProperty("name");
}
}
return this.defaultName;
}
@Override
public boolean isOptionCommand() {
return false;
}
@Override
public String getDescription() {
if (this.main instanceof Command) {
return ((Command) this.main).getDescription();
}
return this.defaultName;
}
@Override
public String getHelp() {
if (this.main instanceof OptionHandler) {
return ((OptionHandler) this.main).getHelp();
}
if (this.main instanceof Command) {
return ((Command) this.main).getHelp();
}
return null;
}
@Override
public Collection<OptionHelp> getOptionsHelp() {
if (this.main instanceof OptionHandler) {
return ((OptionHandler) this.main).getOptionsHelp();
}
if (this.main instanceof Command) {
return ((Command) this.main).getOptionsHelp();
}
return Collections.emptyList();
}
@Override
public void run(String... args) throws Exception {
if (this.main instanceof Command) {
((Command) this.main).run(args);
}
else if (this.main instanceof OptionHandler) {
((OptionHandler) this.main).run(args);
}
else if (this.main instanceof Closure) {
((Closure<?>) this.main).call((Object[]) args);
}
}
@Override
public String getUsageHelp() {
if (this.main instanceof Command) {
return ((Command) this.main).getDescription();
}
return "[options] <args>";
}
public static ScriptCommand command(Class<?> type) {
Object main = null;
try {
main = type.newInstance();
}
catch (Exception ex) {
// Inner classes and closures will not be instantiatable
return null;
}
if (main instanceof Command) {
return new ScriptCommand(type.getSimpleName(), main);
}
else if (main instanceof OptionHandler) {
((OptionHandler) main).options();
return new ScriptCommand(type.getSimpleName(), main);
}
return null;
}
}
...@@ -72,39 +72,6 @@ public class InitCommandTests { ...@@ -72,39 +72,6 @@ public class InitCommandTests {
assertTrue(this.output.toString().contains("Hello Grab")); assertTrue(this.output.toString().contains("Hello Grab"));
} }
@Test
public void initCommand() throws Exception {
this.command.run("src/test/resources/commands/command.groovy");
verify(this.cli, times(this.defaultCount + 1)).register(any(Command.class));
}
@Test
public void initHandler() throws Exception {
this.command.run("src/test/resources/commands/handler.groovy");
verify(this.cli, times(this.defaultCount + 1)).register(any(Command.class));
}
@Test
public void initClosure() throws Exception {
this.command.run("src/test/resources/commands/closure.groovy");
verify(this.cli, times(this.defaultCount + 1)).register(any(Command.class));
}
@Test
public void initOptions() throws Exception {
this.command.run("src/test/resources/commands/options.groovy");
verify(this.cli, times(this.defaultCount + 1)).register(any(Command.class));
}
@Test
public void runOptions() throws Exception {
SpringCli cli = new SpringCli();
InitCommand command = new InitCommand(cli);
command.run("src/test/resources/commands/options.groovy");
cli.find("foo").run("--foo=bar", "--bar=123");
assertTrue(this.output.toString().contains("Hello Foo: bar=123"));
}
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void initNonExistentScript() throws Exception { public void initNonExistentScript() throws Exception {
this.command.run("nonexistent.groovy"); this.command.run("nonexistent.groovy");
......
/*
* 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 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.SpringCli;
import static org.junit.Assert.assertTrue;
/**
* @author Dave Syer
*/
public class ScriptCommandTests {
@Rule
public OutputCapture output = new OutputCapture();
public static boolean executed = false;
private SpringCli cli;
private InitCommand init;
private ClassLoader classLoader;
@Before
public void init() {
this.classLoader = Thread.currentThread().getContextClassLoader();
this.cli = new SpringCli();
this.init = new InitCommand(this.cli);
executed = false;
}
@After
public void close() {
Thread.currentThread().setContextClassLoader(this.classLoader);
}
@Test
public void command() throws Exception {
this.init.run("src/test/resources/commands/command.groovy");
this.cli.find("foo").run("Foo");
assertTrue(this.output.toString().contains("Hello Foo"));
}
@Test
public void handler() throws Exception {
this.init.run("src/test/resources/commands/handler.groovy");
this.cli.find("foo").run("Foo", "--foo=bar");
assertTrue(this.output.toString().contains("Hello [Foo]"));
}
@Test
public void options() throws Exception {
this.init.run("src/test/resources/commands/options.groovy");
this.cli.find("foo").run("Foo", "--foo=bar");
assertTrue(this.output.toString().contains("Hello Foo"));
}
}
/*
* 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.Closure;
import java.util.List;
import java.util.Map;
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.command.InitCommand.Commands;
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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Dave Syer
*/
public class ScriptCompilationCustomizerTests {
private TestGroovyCompilerConfiguration configuration = new TestGroovyCompilerConfiguration();
private GroovyCompiler compiler = new GroovyCompiler(this.configuration);
@Rule
public OutputCapture output = new OutputCapture();
@Before
public void init() {
this.compiler.addCompilationCustomizers(new ScriptCompilationCustomizer());
}
@Test
public void simpleCompile() throws Exception {
Class<?>[] types = this.compiler
.compile("src/test/resources/scripts/command.groovy");
Class<?> main = types[0];
assertEquals("org.test.command.TestCommand", main.getName());
assertTrue(Command.class.isAssignableFrom(main));
}
@Test
public void addsOptionHandler() throws Exception {
Class<?>[] types = this.compiler.compile("classpath:/scripts/handler.groovy");
Class<?> main = types[0];
assertTrue(OptionHandler.class.isAssignableFrom(main));
}
@Test
public void addsCommands() throws Exception {
Class<?>[] types = this.compiler.compile("classpath:scripts/commands.groovy");
Class<?> main = types[0];
assertTrue(Commands.class.isAssignableFrom(main));
}
@Test
public void closureWithStringArgs() throws Exception {
Class<?>[] types = this.compiler.compile("classpath:scripts/commands.groovy");
Class<?> main = types[0];
Map<String, Closure<?>> commands = ((Commands) main.newInstance()).getCommands();
assertEquals(1, commands.size());
assertEquals("foo", commands.keySet().iterator().next());
Closure<?> closure = commands.values().iterator().next();
closure.call("foo", "bar");
assertTrue(this.output.toString().contains("Hello Command"));
}
@Test
public void closureWithEmptyArgs() throws Exception {
Class<?>[] types = this.compiler
.compile("src/test/resources/scripts/commands.groovy");
Class<?> main = types[0];
Map<String, Closure<?>> commands = ((Commands) main.newInstance()).getCommands();
assertEquals(1, commands.size());
assertEquals("foo", commands.keySet().iterator().next());
Closure<?> closure = commands.values().iterator().next();
closure.call();
assertTrue(this.output.toString().contains("Hello Command"));
}
@Test
public void closureAndOptionsDefined() throws Exception {
Class<?>[] types = this.compiler
.compile("src/test/resources/scripts/options.groovy");
Class<?> main = types[0];
Commands commands = (Commands) main.newInstance();
Map<String, Closure<?>> closures = commands.getCommands();
assertEquals(1, closures.size());
assertEquals("foo", closures.keySet().iterator().next());
final Closure<?> closure = closures.values().iterator().next();
Map<String, OptionHandler> options = commands.getOptions();
assertEquals(1, options.size());
OptionHandler handler = options.get("foo");
handler.setClosure(closure);
handler.run("--foo=bar", "--bar=blah", "spam");
assertTrue(this.output.toString().contains("Hello [spam]: true blah"));
}
private static class TestGroovyCompilerConfiguration implements
GroovyCompilerConfiguration {
@Override
public GroovyCompilerScope getScope() {
return GroovyCompilerScope.EXTENSION;
}
@Override
public boolean isGuessImports() {
return true;
}
@Override
public boolean isGuessDependencies() {
return false;
}
@Override
public boolean isAutoconfigure() {
return true;
}
@Override
public String[] getClasspath() {
return new String[0];
}
@Override
public List<RepositoryConfiguration> getRepositoryConfiguration() {
return RepositoryConfigurationFactory.createDefaultRepositoryConfiguration();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment