FileOptions -> SourceOptions to work with String paths instead of Files

We check for existence of the sources and (as before) resolve multiple
resources on the classpath if a path is not a File. In addition supports
Spring pseudo-URL prefixes as well as normal URLs as source locations.

In addition sources can now be specified as a directory (searched
recursively by default), or a resource pattern (e.g. app/**/*.groovy).

Fixes gh-207
This commit is contained in:
Dave Syer 2014-01-10 10:41:08 +00:00
parent 62e02d3d81
commit bd73705393
15 changed files with 560 additions and 200 deletions

View File

@ -1,140 +0,0 @@
/*
* 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.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import joptsimple.OptionSet;
/**
* Extract file options (anything following '--' in an {@link OptionSet}).
*
* @author Phillip Webb
* @author Dave Syer
* @author Greg Turnquist
*/
public class FileOptions {
private List<File> files;
private List<?> args;
/**
* Create a new {@link FileOptions} instance.
* @param options the source option set
*/
public FileOptions(OptionSet options) {
this(options, null);
}
/**
* 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 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,
String... defaultPaths) {
List<?> nonOptionArguments = optionSet.nonOptionArguments();
List<File> files = new ArrayList<File>();
for (Object option : nonOptionArguments) {
if (option instanceof String) {
String filename = (String) option;
if ("--".equals(filename)) {
break;
}
if (filename.endsWith(".groovy") || filename.endsWith(".java")) {
List<File> file = getFiles(filename, classLoader);
if (file.isEmpty()) {
throw new IllegalArgumentException("Can't find " + filename);
}
files.addAll(file);
}
}
}
this.args = Collections.unmodifiableList(nonOptionArguments.subList(files.size(),
nonOptionArguments.size()));
if (files.size() == 0) {
if (defaultPaths.length == 0) {
throw new RuntimeException("Please specify at least one file to run");
}
for (String path : defaultPaths) {
for (File file : getFiles(path, classLoader)) {
if (file != null && file.exists()) {
files.add(file);
}
}
}
}
this.files = Collections.unmodifiableList(files);
}
private List<File> getFiles(String filename, ClassLoader classLoader) {
File file = new File(filename);
if (file.isFile() && file.canRead()) {
return Arrays.asList(file);
}
List<File> result = new ArrayList<File>();
if (classLoader != null) {
Enumeration<URL> urls;
try {
urls = classLoader.getResources(filename);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null && url.toString().startsWith("file:")) {
result.add(new File(url.toString().substring("file:".length())));
}
}
}
catch (IOException e) {
// Ignore
}
}
return result;
}
public List<?> getArgs() {
return this.args;
}
public String[] getArgsArray() {
return this.args.toArray(new String[this.args.size()]);
}
public List<File> getFiles() {
return this.files;
}
public File[] getFilesArray() {
return this.files.toArray(new File[this.files.size()]);
}
}

View File

@ -43,7 +43,7 @@ public class GrabCommand extends OptionParsingCommand {
@Override
protected void run(OptionSet options) throws Exception {
FileOptions fileOptions = new FileOptions(options);
SourceOptions fileOptions = new SourceOptions(options);
List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
.createDefaultRepositoryConfiguration();
@ -56,7 +56,7 @@ public class GrabCommand extends OptionParsingCommand {
}
GroovyCompiler groovyCompiler = new GroovyCompiler(configuration);
groovyCompiler.compile(fileOptions.getFilesArray());
groovyCompiler.compile(fileOptions.getSourcesArray());
}
}

View File

@ -20,7 +20,6 @@ import groovy.lang.Closure;
import groovy.lang.GroovyClassLoader;
import groovy.lang.Script;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
@ -76,9 +75,9 @@ public class InitCommand extends OptionParsingCommand {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
boolean enhanced = false;
FileOptions fileOptions = new FileOptions(options, loader, "init.groovy",
SourceOptions fileOptions = new SourceOptions(options, loader, "init.groovy",
"spring.groovy");
File[] files = fileOptions.getFilesArray();
String[] files = fileOptions.getSourcesArray();
if (!(loader instanceof GroovyClassLoader)) {

View File

@ -36,7 +36,7 @@ import static java.util.Arrays.asList;
/**
* {@link Command} to 'run' a groovy script or scripts.
*
*
* @author Phillip Webb
* @author Dave Syer
* @author Andy Wilkinson
@ -95,22 +95,22 @@ public class RunCommand extends OptionParsingCommand {
"Already running. Please stop the current application before running another.");
}
FileOptions fileOptions = new FileOptions(options);
SourceOptions fileOptions = new SourceOptions(options);
if (options.has(this.editOption)) {
Desktop.getDesktop().edit(fileOptions.getFiles().get(0));
Desktop.getDesktop().edit(new File(fileOptions.getSources().get(0)));
}
List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
.createDefaultRepositoryConfiguration();
repositoryConfiguration.add(0, new RepositoryConfiguration("local", new File(
"repository").toURI(), true));
"repository").toURI(), true));
SpringApplicationRunnerConfiguration configuration = new SpringApplicationRunnerConfigurationAdapter(
options, this, repositoryConfiguration);
this.runner = new SpringApplicationRunner(configuration,
fileOptions.getFilesArray(), fileOptions.getArgsArray());
fileOptions.getSourcesArray(), fileOptions.getArgsArray());
this.runner.compileAndRun();
}

View File

@ -0,0 +1,113 @@
/*
* 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.util.ArrayList;
import java.util.Collections;
import java.util.List;
import joptsimple.OptionSet;
import org.springframework.boot.cli.util.ResourceUtils;
/**
* Extract source file options (anything following '--' in an {@link OptionSet}).
*
* @author Phillip Webb
* @author Dave Syer
* @author Greg Turnquist
*/
public class SourceOptions {
private List<String> sources;
private List<?> args;
/**
* Create a new {@link SourceOptions} instance.
* @param options the source option set
*/
public SourceOptions(OptionSet options) {
this(options, null);
}
/**
* Create a new {@link SourceOptions} instance. If it is an error to pass options that
* specify non-existent sources, 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 source 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 in the local filesystem
* @param defaultPaths the default paths to use if no files are provided in the option
* set
*/
public SourceOptions(OptionSet optionSet, ClassLoader classLoader,
String... defaultPaths) {
List<?> nonOptionArguments = optionSet.nonOptionArguments();
List<String> sources = new ArrayList<String>();
for (Object option : nonOptionArguments) {
if (option instanceof String) {
String filename = (String) option;
if ("--".equals(filename)) {
break;
}
List<String> urls = ResourceUtils.getUrls(filename, classLoader);
for (String url : urls) {
if (url.endsWith(".groovy") || url.endsWith(".java")) {
sources.add(url);
}
}
if ((filename.endsWith(".groovy") || filename.endsWith(".java"))
&& urls.isEmpty()) {
throw new IllegalArgumentException("Can't find " + filename);
}
}
}
this.args = Collections.unmodifiableList(nonOptionArguments.subList(
sources.size(), nonOptionArguments.size()));
if (sources.size() == 0) {
if (defaultPaths.length == 0) {
throw new IllegalArgumentException(
"Please specify at least one file to run");
}
for (String path : defaultPaths) {
sources.addAll(ResourceUtils.getUrls(path, classLoader));
}
}
this.sources = Collections.unmodifiableList(sources);
}
public List<?> getArgs() {
return this.args;
}
public String[] getArgsArray() {
return this.args.toArray(new String[this.args.size()]);
}
public List<String> getSources() {
return this.sources;
}
public String[] getSourcesArray() {
return this.sources.toArray(new String[this.sources.size()]);
}
}

View File

@ -46,10 +46,10 @@ public class TestCommand extends OptionParsingCommand {
@Override
protected void run(OptionSet options) throws Exception {
FileOptions fileOptions = new FileOptions(options);
SourceOptions fileOptions = new SourceOptions(options);
TestRunnerConfiguration configuration = new TestRunnerConfigurationAdapter(
options, this);
this.runner = new TestRunner(configuration, fileOptions.getFilesArray(),
this.runner = new TestRunner(configuration, fileOptions.getSourcesArray(),
fileOptions.getArgsArray());
this.runner.compileAndRunTests();
}

View File

@ -18,8 +18,8 @@ package org.springframework.boot.cli.compiler;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyClassLoader.ClassCollector;
import groovy.lang.GroovyCodeSource;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
@ -49,10 +49,12 @@ import org.springframework.boot.cli.compiler.grape.GrapeEngineInstaller;
import org.springframework.boot.cli.compiler.transformation.DependencyAutoConfigurationTransformation;
import org.springframework.boot.cli.compiler.transformation.GroovyBeansTransformation;
import org.springframework.boot.cli.compiler.transformation.ResolveDependencyCoordinatesTransformation;
import org.springframework.boot.cli.util.ResourceUtils;
/**
* Compiler for Groovy source files. Primarily a simple Facade for
* {@link GroovyClassLoader#parseClass(File)} with the following additional features:
* Compiler for Groovy sources. Primarily a simple Facade for
* {@link GroovyClassLoader#parseClass(GroovyCodeSource)} with the following additional
* features:
* <ul>
* <li>{@link CompilerAutoConfiguration} strategies will be read from
* <code>META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration</code>
@ -152,32 +154,33 @@ public class GroovyCompiler {
this.loader.getConfiguration().addCompilationCustomizers(customizers);
}
public Object[] sources(File... files) throws CompilationFailedException, IOException {
List<File> compilables = new ArrayList<File>();
public Object[] sources(String... sources) throws CompilationFailedException,
IOException {
List<String> compilables = new ArrayList<String>();
List<Object> others = new ArrayList<Object>();
for (File file : files) {
if (file.getName().endsWith(".groovy") || file.getName().endsWith(".java")) {
compilables.add(file);
for (String source : sources) {
if (source.endsWith(".groovy") || source.endsWith(".java")) {
compilables.add(source);
}
else {
others.add(file);
others.add(source);
}
}
Class<?>[] compiled = compile(compilables.toArray(new File[compilables.size()]));
Class<?>[] compiled = compile(compilables.toArray(new String[compilables.size()]));
others.addAll(0, Arrays.asList(compiled));
return others.toArray(new Object[others.size()]);
}
/**
* Compile the specified Groovy source files, applying any
* {@link CompilerAutoConfiguration}s. All classes defined in the files will be
* Compile the specified Groovy sources, applying any
* {@link CompilerAutoConfiguration}s. All classes defined in the sources will be
* returned from this method.
* @param file the file to compile
* @param sources the sources to compile
* @return compiled classes
* @throws CompilationFailedException
* @throws IOException
*/
public Class<?>[] compile(File... file) throws CompilationFailedException,
public Class<?>[] compile(String... sources) throws CompilationFailedException,
IOException {
this.loader.clearCache();
@ -187,13 +190,15 @@ public class GroovyCompiler {
CompilationUnit compilationUnit = new CompilationUnit(configuration, null,
this.loader);
SourceUnit sourceUnit = new SourceUnit(file[0], configuration, this.loader,
compilationUnit.getErrorCollector());
ClassCollector collector = this.loader.createCollector(compilationUnit,
sourceUnit);
ClassCollector collector = this.loader.createCollector(compilationUnit, null);
compilationUnit.setClassgenCallback(collector);
compilationUnit.addSources(file);
for (String source : sources) {
List<String> paths = ResourceUtils.getUrls(source, this.loader);
for (String path : paths) {
compilationUnit.addSource(new URL(path));
}
}
addAstTransformations(compilationUnit);

View File

@ -39,7 +39,7 @@ public class SpringApplicationRunner {
private final SpringApplicationRunnerConfiguration configuration;
private final File[] files;
private final String[] files;
private final String[] args;
@ -56,7 +56,7 @@ public class SpringApplicationRunner {
* @param args input arguments
*/
public SpringApplicationRunner(
final SpringApplicationRunnerConfiguration configuration, File[] files,
final SpringApplicationRunnerConfiguration configuration, String[] files,
String... args) {
this.configuration = configuration;
this.files = files.clone();
@ -176,10 +176,13 @@ public class SpringApplicationRunner {
public FileWatchThread() {
super("filewatcher-" + (watcherCounter++));
this.previous = 0;
for (File file : SpringApplicationRunner.this.files) {
long current = file.lastModified();
if (current > this.previous) {
this.previous = current;
for (String path : SpringApplicationRunner.this.files) {
File file = new File(path);
if (file.exists()) {
long current = file.lastModified();
if (current > this.previous) {
this.previous = current;
}
}
}
setDaemon(false);
@ -190,11 +193,14 @@ public class SpringApplicationRunner {
while (true) {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
for (File file : SpringApplicationRunner.this.files) {
long current = file.lastModified();
if (this.previous < current) {
this.previous = current;
compileAndRun();
for (String path : SpringApplicationRunner.this.files) {
File file = new File(path);
if (file.exists()) {
long current = file.lastModified();
if (this.previous < current) {
this.previous = current;
compileAndRun();
}
}
}
}

View File

@ -16,7 +16,6 @@
package org.springframework.boot.cli.testrunner;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
@ -34,7 +33,7 @@ public class TestRunner {
private static final String JUNIT_TEST_ANNOTATION = "org.junit.Test";
private final File[] files;
private final String[] files;
private final GroovyCompiler compiler;
@ -44,7 +43,7 @@ public class TestRunner {
* @param files
* @param args
*/
public TestRunner(TestRunnerConfiguration configuration, File[] files, String[] args) {
public TestRunner(TestRunnerConfiguration configuration, String[] files, String[] args) {
this.files = files.clone();
this.compiler = new GroovyCompiler(configuration);
}

View File

@ -0,0 +1,166 @@
/*
* 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.util;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Utilities for manipulating resource paths and URLs.
*
* @author Dave Syer
*/
public abstract class ResourceUtils {
/** Pseudo URL prefix for loading from the class path: "classpath:" */
public static final String CLASSPATH_URL_PREFIX = "classpath:";
/** Pseudo URL prefix for loading all resources from the class path: "classpath*:" */
public static final String ALL_CLASSPATH_URL_PREFIX = "classpath*:";
/** URL prefix for loading from the file system: "file:" */
public static final String FILE_URL_PREFIX = "file:";
/** Wildcard character in source path */
public static final CharSequence WILDCARD = "*";
public static List<String> getUrls(String path, ClassLoader classLoader) {
if (classLoader == null) {
classLoader = ClassUtils.getDefaultClassLoader();
}
path = StringUtils.cleanPath(path);
if (path.contains(WILDCARD)) {
if (path.contains(":")) {
try {
Resource[] resources = new PathMatchingResourcePatternResolver(
classLoader).getResources(path);
List<String> result = new ArrayList<String>();
for (Resource resource : resources) {
result.add(resource.getURL().toExternalForm());
}
return result;
}
catch (IOException e) {
throw new IllegalArgumentException("Cannot resolve paths at [" + path
+ "]", e);
}
}
else {
try {
return getUrls(FILE_URL_PREFIX + path, classLoader);
}
catch (IllegalArgumentException e) {
// ignore
}
return getUrls(ALL_CLASSPATH_URL_PREFIX + path, classLoader);
}
}
if (path.contains(":")) {
if (path.startsWith(CLASSPATH_URL_PREFIX)) {
path = path.substring(CLASSPATH_URL_PREFIX.length());
}
else {
return getFilePath(path);
}
}
else {
try {
return getFilePath(path);
}
catch (IllegalArgumentException e) {
// ignore
}
}
while (path.startsWith("/")) {
path = path.substring(1);
}
List<String> result = new ArrayList<String>();
if (classLoader != null) {
Enumeration<URL> urls;
try {
urls = classLoader.getResources(path);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
result.add(url.toExternalForm());
}
}
catch (IOException e) {
// Ignore
}
}
return result;
}
private static List<String> getFilePath(String path) {
FileSystemResource resource = new FileSystemResource(path);
if (resource.exists()) {
try {
if (resource.getFile().isDirectory()) {
Resource[] resources = new PathMatchingResourcePatternResolver()
.getResources(resource.getURL() + "/**");
List<String> result = new ArrayList<String>();
for (Resource sub : resources) {
if (!sub.getFile().isDirectory()) {
result.add(sub.getURL().toExternalForm());
}
}
return result;
}
return Collections.singletonList(resource.getURL().toExternalForm());
}
catch (IOException e) {
throw new IllegalArgumentException("Cannot create URL from path [" + path
+ "]", e);
}
}
try {
UrlResource url = new UrlResource(path);
if (url.exists()) {
try {
return Collections.singletonList(url.getURL().toExternalForm());
}
catch (IOException e) {
throw new IllegalArgumentException("Cannot create URL from path ["
+ path + "]", e);
}
}
}
catch (MalformedURLException ex) {
throw new IllegalArgumentException("Cannot create URL from path [" + path
+ "]", ex);
}
return Collections.emptyList();
}
}

View File

@ -17,6 +17,7 @@
package org.springframework.boot.cli;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
@ -104,8 +105,13 @@ public class CliTester implements TestRule {
final String[] sources = new String[args.length];
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.startsWith("-")) {
sources[i] = arg;
if (!arg.endsWith(".groovy") && !arg.endsWith(".xml")) {
if (new File(this.prefix + arg).isDirectory()) {
sources[i] = this.prefix + arg;
}
else {
sources[i] = arg;
}
}
else {
sources[i] = this.prefix + arg;

View File

@ -0,0 +1,52 @@
/*
* 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 org.junit.Rule;
import org.junit.Test;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
/**
* Integration tests for code in directories.
*
* @author Dave Syer
*/
public class DirectorySourcesIntegrationTests {
@Rule
public CliTester cli = new CliTester("src/test/resources/dir-sample/");
@Test
public void runDirectory() throws Exception {
this.cli.run("code");
assertThat(this.cli.getOutput(), containsString("Hello World"));
}
@Test
public void runDirectoryRecursive() throws Exception {
this.cli.run("");
assertThat(this.cli.getOutput(), containsString("Hello World"));
}
@Test
public void runPathPattern() throws Exception {
this.cli.run("**/*.groovy");
assertThat(this.cli.getOutput(), containsString("Hello World"));
}
}

View File

@ -18,7 +18,6 @@ package org.springframework.boot.cli.command;
import groovy.lang.Closure;
import java.io.File;
import java.util.List;
import java.util.Map;
@ -55,8 +54,8 @@ public class ScriptCompilationCustomizerTests {
@Test
public void simpleCompile() throws Exception {
Class<?>[] types = this.compiler.compile(new File(
"src/test/resources/scripts/command.groovy"));
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));
@ -64,24 +63,21 @@ public class ScriptCompilationCustomizerTests {
@Test
public void addsOptionHandler() throws Exception {
Class<?>[] types = this.compiler.compile(new File(
"src/test/resources/scripts/handler.groovy"));
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(new File(
"src/test/resources/scripts/commands.groovy"));
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(new File(
"src/test/resources/scripts/commands.groovy"));
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());
@ -93,8 +89,8 @@ public class ScriptCompilationCustomizerTests {
@Test
public void closureWithEmptyArgs() throws Exception {
Class<?>[] types = this.compiler.compile(new File(
"src/test/resources/scripts/commands.groovy"));
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());
@ -106,8 +102,8 @@ public class ScriptCompilationCustomizerTests {
@Test
public void closureAndOptionsDefined() throws Exception {
Class<?>[] types = this.compiler.compile(new File(
"src/test/resources/scripts/options.groovy"));
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();

View File

@ -0,0 +1,135 @@
/*
* 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.util;
import java.util.List;
import org.junit.Test;
import org.springframework.util.ClassUtils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Dave Syer
*/
public class ResourceUtilsTests {
@Test
public void explicitClasspathResource() {
List<String> urls = ResourceUtils.getUrls("classpath:init.groovy",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void explicitClasspathResourceWithSlash() {
List<String> urls = ResourceUtils.getUrls("classpath:/init.groovy",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void implicitClasspathResource() {
List<String> urls = ResourceUtils.getUrls("init.groovy",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void implicitClasspathResourceWithSlash() {
List<String> urls = ResourceUtils.getUrls("/init.groovy",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void nonexistentClasspathResource() {
List<String> urls = ResourceUtils.getUrls("classpath:nonexistent.groovy", null);
assertEquals(0, urls.size());
}
@Test
public void explicitFile() {
List<String> urls = ResourceUtils.getUrls("file:src/test/resources/init.groovy",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void implicitFile() {
List<String> urls = ResourceUtils.getUrls("src/test/resources/init.groovy",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void nonexistentFile() {
List<String> urls = ResourceUtils.getUrls("file:nonexistent.groovy", null);
assertEquals(0, urls.size());
}
@Test
public void recursiveFiles() {
List<String> urls = ResourceUtils.getUrls("src/test/resources/dir-sample",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void recursiveFilesByPatternWithPrefix() {
List<String> urls = ResourceUtils.getUrls(
"file:src/test/resources/dir-sample/**/*.groovy",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void recursiveFilesByPattern() {
List<String> urls = ResourceUtils.getUrls(
"src/test/resources/dir-sample/**/*.groovy",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void directoryOfFilesWithPrefix() {
List<String> urls = ResourceUtils.getUrls(
"file:src/test/resources/dir-sample/code/*",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
@Test
public void directoryOfFiles() {
List<String> urls = ResourceUtils.getUrls("src/test/resources/dir-sample/code/*",
ClassUtils.getDefaultClassLoader());
assertEquals(1, urls.size());
assertTrue(urls.get(0).startsWith("file:"));
}
}

View File

@ -0,0 +1,23 @@
package org.test
@Component
class Example implements CommandLineRunner {
@Autowired
private MyService myService
void run(String... args) {
println "Hello ${this.myService.sayWorld()} From ${getClass().getClassLoader().getResource('samples/app.groovy')}"
}
}
@Service
class MyService {
String sayWorld() {
return "World!"
}
}