Commit bd737053 authored by Dave Syer's avatar Dave Syer

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
parent 62e02d3d
...@@ -43,7 +43,7 @@ public class GrabCommand extends OptionParsingCommand { ...@@ -43,7 +43,7 @@ public class GrabCommand extends OptionParsingCommand {
@Override @Override
protected void run(OptionSet options) throws Exception { protected void run(OptionSet options) throws Exception {
FileOptions fileOptions = new FileOptions(options); SourceOptions fileOptions = new SourceOptions(options);
List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
.createDefaultRepositoryConfiguration(); .createDefaultRepositoryConfiguration();
...@@ -56,7 +56,7 @@ public class GrabCommand extends OptionParsingCommand { ...@@ -56,7 +56,7 @@ public class GrabCommand extends OptionParsingCommand {
} }
GroovyCompiler groovyCompiler = new GroovyCompiler(configuration); GroovyCompiler groovyCompiler = new GroovyCompiler(configuration);
groovyCompiler.compile(fileOptions.getFilesArray()); groovyCompiler.compile(fileOptions.getSourcesArray());
} }
} }
......
...@@ -20,7 +20,6 @@ import groovy.lang.Closure; ...@@ -20,7 +20,6 @@ import groovy.lang.Closure;
import groovy.lang.GroovyClassLoader; import groovy.lang.GroovyClassLoader;
import groovy.lang.Script; import groovy.lang.Script;
import java.io.File;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
...@@ -76,9 +75,9 @@ public class InitCommand extends OptionParsingCommand { ...@@ -76,9 +75,9 @@ public class InitCommand extends OptionParsingCommand {
ClassLoader loader = Thread.currentThread().getContextClassLoader(); ClassLoader loader = Thread.currentThread().getContextClassLoader();
boolean enhanced = false; boolean enhanced = false;
FileOptions fileOptions = new FileOptions(options, loader, "init.groovy", SourceOptions fileOptions = new SourceOptions(options, loader, "init.groovy",
"spring.groovy"); "spring.groovy");
File[] files = fileOptions.getFilesArray(); String[] files = fileOptions.getSourcesArray();
if (!(loader instanceof GroovyClassLoader)) { if (!(loader instanceof GroovyClassLoader)) {
......
...@@ -36,7 +36,7 @@ import static java.util.Arrays.asList; ...@@ -36,7 +36,7 @@ import static java.util.Arrays.asList;
/** /**
* {@link Command} to 'run' a groovy script or scripts. * {@link Command} to 'run' a groovy script or scripts.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Andy Wilkinson * @author Andy Wilkinson
...@@ -95,22 +95,22 @@ public class RunCommand extends OptionParsingCommand { ...@@ -95,22 +95,22 @@ public class RunCommand extends OptionParsingCommand {
"Already running. Please stop the current application before running another."); "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)) { 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 List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
.createDefaultRepositoryConfiguration(); .createDefaultRepositoryConfiguration();
repositoryConfiguration.add(0, new RepositoryConfiguration("local", new File( repositoryConfiguration.add(0, new RepositoryConfiguration("local", new File(
"repository").toURI(), true)); "repository").toURI(), true));
SpringApplicationRunnerConfiguration configuration = new SpringApplicationRunnerConfigurationAdapter( SpringApplicationRunnerConfiguration configuration = new SpringApplicationRunnerConfigurationAdapter(
options, this, repositoryConfiguration); options, this, repositoryConfiguration);
this.runner = new SpringApplicationRunner(configuration, this.runner = new SpringApplicationRunner(configuration,
fileOptions.getFilesArray(), fileOptions.getArgsArray()); fileOptions.getSourcesArray(), fileOptions.getArgsArray());
this.runner.compileAndRun(); this.runner.compileAndRun();
} }
......
...@@ -16,44 +16,41 @@ ...@@ -16,44 +16,41 @@
package org.springframework.boot.cli.command; 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.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import joptsimple.OptionSet; import joptsimple.OptionSet;
import org.springframework.boot.cli.util.ResourceUtils;
/** /**
* Extract file options (anything following '--' in an {@link OptionSet}). * Extract source file options (anything following '--' in an {@link OptionSet}).
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Greg Turnquist * @author Greg Turnquist
*/ */
public class FileOptions { public class SourceOptions {
private List<File> files; private List<String> sources;
private List<?> args; private List<?> args;
/** /**
* Create a new {@link FileOptions} instance. * Create a new {@link SourceOptions} instance.
* @param options the source option set * @param options the source option set
*/ */
public FileOptions(OptionSet options) { public SourceOptions(OptionSet options) {
this(options, null); this(options, null);
} }
/** /**
* Create a new {@link FileOptions} instance. If it is an error to pass options that * Create a new {@link SourceOptions} instance. If it is an error to pass options that
* specify non-existent files, but the default paths are allowed not to exist (the * 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 * 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 * contains no source file arguments it is not an error even if none of the default
* exist). * paths exist).
* *
* @param optionSet the source option set * @param optionSet the source option set
* @param classLoader an optional classloader used to try and load files that are not * @param classLoader an optional classloader used to try and load files that are not
...@@ -61,64 +58,40 @@ public class FileOptions { ...@@ -61,64 +58,40 @@ public class FileOptions {
* @param defaultPaths the default paths to use if no files are provided in the option * @param defaultPaths the default paths to use if no files are provided in the option
* set * set
*/ */
public FileOptions(OptionSet optionSet, ClassLoader classLoader, public SourceOptions(OptionSet optionSet, ClassLoader classLoader,
String... defaultPaths) { String... defaultPaths) {
List<?> nonOptionArguments = optionSet.nonOptionArguments(); List<?> nonOptionArguments = optionSet.nonOptionArguments();
List<File> files = new ArrayList<File>(); List<String> sources = new ArrayList<String>();
for (Object option : nonOptionArguments) { for (Object option : nonOptionArguments) {
if (option instanceof String) { if (option instanceof String) {
String filename = (String) option; String filename = (String) option;
if ("--".equals(filename)) { if ("--".equals(filename)) {
break; break;
} }
if (filename.endsWith(".groovy") || filename.endsWith(".java")) { List<String> urls = ResourceUtils.getUrls(filename, classLoader);
List<File> file = getFiles(filename, classLoader); for (String url : urls) {
if (file.isEmpty()) { if (url.endsWith(".groovy") || url.endsWith(".java")) {
throw new IllegalArgumentException("Can't find " + filename); sources.add(url);
} }
files.addAll(file); }
if ((filename.endsWith(".groovy") || filename.endsWith(".java"))
&& urls.isEmpty()) {
throw new IllegalArgumentException("Can't find " + filename);
} }
} }
} }
this.args = Collections.unmodifiableList(nonOptionArguments.subList(files.size(), this.args = Collections.unmodifiableList(nonOptionArguments.subList(
nonOptionArguments.size())); sources.size(), nonOptionArguments.size()));
if (files.size() == 0) { if (sources.size() == 0) {
if (defaultPaths.length == 0) { if (defaultPaths.length == 0) {
throw new RuntimeException("Please specify at least one file to run"); throw new IllegalArgumentException(
"Please specify at least one file to run");
} }
for (String path : defaultPaths) { for (String path : defaultPaths) {
for (File file : getFiles(path, classLoader)) { sources.addAll(ResourceUtils.getUrls(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; this.sources = Collections.unmodifiableList(sources);
} }
public List<?> getArgs() { public List<?> getArgs() {
...@@ -129,12 +102,12 @@ public class FileOptions { ...@@ -129,12 +102,12 @@ public class FileOptions {
return this.args.toArray(new String[this.args.size()]); return this.args.toArray(new String[this.args.size()]);
} }
public List<File> getFiles() { public List<String> getSources() {
return this.files; return this.sources;
} }
public File[] getFilesArray() { public String[] getSourcesArray() {
return this.files.toArray(new File[this.files.size()]); return this.sources.toArray(new String[this.sources.size()]);
} }
} }
...@@ -46,10 +46,10 @@ public class TestCommand extends OptionParsingCommand { ...@@ -46,10 +46,10 @@ public class TestCommand extends OptionParsingCommand {
@Override @Override
protected void run(OptionSet options) throws Exception { protected void run(OptionSet options) throws Exception {
FileOptions fileOptions = new FileOptions(options); SourceOptions fileOptions = new SourceOptions(options);
TestRunnerConfiguration configuration = new TestRunnerConfigurationAdapter( TestRunnerConfiguration configuration = new TestRunnerConfigurationAdapter(
options, this); options, this);
this.runner = new TestRunner(configuration, fileOptions.getFilesArray(), this.runner = new TestRunner(configuration, fileOptions.getSourcesArray(),
fileOptions.getArgsArray()); fileOptions.getArgsArray());
this.runner.compileAndRunTests(); this.runner.compileAndRunTests();
} }
......
...@@ -18,8 +18,8 @@ package org.springframework.boot.cli.compiler; ...@@ -18,8 +18,8 @@ package org.springframework.boot.cli.compiler;
import groovy.lang.GroovyClassLoader; import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyClassLoader.ClassCollector; import groovy.lang.GroovyClassLoader.ClassCollector;
import groovy.lang.GroovyCodeSource;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.net.URL; import java.net.URL;
...@@ -49,10 +49,12 @@ import org.springframework.boot.cli.compiler.grape.GrapeEngineInstaller; ...@@ -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.DependencyAutoConfigurationTransformation;
import org.springframework.boot.cli.compiler.transformation.GroovyBeansTransformation; import org.springframework.boot.cli.compiler.transformation.GroovyBeansTransformation;
import org.springframework.boot.cli.compiler.transformation.ResolveDependencyCoordinatesTransformation; 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 * Compiler for Groovy sources. Primarily a simple Facade for
* {@link GroovyClassLoader#parseClass(File)} with the following additional features: * {@link GroovyClassLoader#parseClass(GroovyCodeSource)} with the following additional
* features:
* <ul> * <ul>
* <li>{@link CompilerAutoConfiguration} strategies will be read from * <li>{@link CompilerAutoConfiguration} strategies will be read from
* <code>META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration</code> * <code>META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration</code>
...@@ -152,32 +154,33 @@ public class GroovyCompiler { ...@@ -152,32 +154,33 @@ public class GroovyCompiler {
this.loader.getConfiguration().addCompilationCustomizers(customizers); this.loader.getConfiguration().addCompilationCustomizers(customizers);
} }
public Object[] sources(File... files) throws CompilationFailedException, IOException { public Object[] sources(String... sources) throws CompilationFailedException,
List<File> compilables = new ArrayList<File>(); IOException {
List<String> compilables = new ArrayList<String>();
List<Object> others = new ArrayList<Object>(); List<Object> others = new ArrayList<Object>();
for (File file : files) { for (String source : sources) {
if (file.getName().endsWith(".groovy") || file.getName().endsWith(".java")) { if (source.endsWith(".groovy") || source.endsWith(".java")) {
compilables.add(file); compilables.add(source);
} }
else { 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)); others.addAll(0, Arrays.asList(compiled));
return others.toArray(new Object[others.size()]); return others.toArray(new Object[others.size()]);
} }
/** /**
* Compile the specified Groovy source files, applying any * Compile the specified Groovy sources, applying any
* {@link CompilerAutoConfiguration}s. All classes defined in the files will be * {@link CompilerAutoConfiguration}s. All classes defined in the sources will be
* returned from this method. * returned from this method.
* @param file the file to compile * @param sources the sources to compile
* @return compiled classes * @return compiled classes
* @throws CompilationFailedException * @throws CompilationFailedException
* @throws IOException * @throws IOException
*/ */
public Class<?>[] compile(File... file) throws CompilationFailedException, public Class<?>[] compile(String... sources) throws CompilationFailedException,
IOException { IOException {
this.loader.clearCache(); this.loader.clearCache();
...@@ -187,13 +190,15 @@ public class GroovyCompiler { ...@@ -187,13 +190,15 @@ public class GroovyCompiler {
CompilationUnit compilationUnit = new CompilationUnit(configuration, null, CompilationUnit compilationUnit = new CompilationUnit(configuration, null,
this.loader); this.loader);
SourceUnit sourceUnit = new SourceUnit(file[0], configuration, this.loader, ClassCollector collector = this.loader.createCollector(compilationUnit, null);
compilationUnit.getErrorCollector());
ClassCollector collector = this.loader.createCollector(compilationUnit,
sourceUnit);
compilationUnit.setClassgenCallback(collector); 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); addAstTransformations(compilationUnit);
......
...@@ -39,7 +39,7 @@ public class SpringApplicationRunner { ...@@ -39,7 +39,7 @@ public class SpringApplicationRunner {
private final SpringApplicationRunnerConfiguration configuration; private final SpringApplicationRunnerConfiguration configuration;
private final File[] files; private final String[] files;
private final String[] args; private final String[] args;
...@@ -56,7 +56,7 @@ public class SpringApplicationRunner { ...@@ -56,7 +56,7 @@ public class SpringApplicationRunner {
* @param args input arguments * @param args input arguments
*/ */
public SpringApplicationRunner( public SpringApplicationRunner(
final SpringApplicationRunnerConfiguration configuration, File[] files, final SpringApplicationRunnerConfiguration configuration, String[] files,
String... args) { String... args) {
this.configuration = configuration; this.configuration = configuration;
this.files = files.clone(); this.files = files.clone();
...@@ -176,10 +176,13 @@ public class SpringApplicationRunner { ...@@ -176,10 +176,13 @@ public class SpringApplicationRunner {
public FileWatchThread() { public FileWatchThread() {
super("filewatcher-" + (watcherCounter++)); super("filewatcher-" + (watcherCounter++));
this.previous = 0; this.previous = 0;
for (File file : SpringApplicationRunner.this.files) { for (String path : SpringApplicationRunner.this.files) {
long current = file.lastModified(); File file = new File(path);
if (current > this.previous) { if (file.exists()) {
this.previous = current; long current = file.lastModified();
if (current > this.previous) {
this.previous = current;
}
} }
} }
setDaemon(false); setDaemon(false);
...@@ -190,11 +193,14 @@ public class SpringApplicationRunner { ...@@ -190,11 +193,14 @@ public class SpringApplicationRunner {
while (true) { while (true) {
try { try {
Thread.sleep(TimeUnit.SECONDS.toMillis(1)); Thread.sleep(TimeUnit.SECONDS.toMillis(1));
for (File file : SpringApplicationRunner.this.files) { for (String path : SpringApplicationRunner.this.files) {
long current = file.lastModified(); File file = new File(path);
if (this.previous < current) { if (file.exists()) {
this.previous = current; long current = file.lastModified();
compileAndRun(); if (this.previous < current) {
this.previous = current;
compileAndRun();
}
} }
} }
} }
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
package org.springframework.boot.cli.testrunner; package org.springframework.boot.cli.testrunner;
import java.io.File;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -34,7 +33,7 @@ public class TestRunner { ...@@ -34,7 +33,7 @@ public class TestRunner {
private static final String JUNIT_TEST_ANNOTATION = "org.junit.Test"; private static final String JUNIT_TEST_ANNOTATION = "org.junit.Test";
private final File[] files; private final String[] files;
private final GroovyCompiler compiler; private final GroovyCompiler compiler;
...@@ -44,7 +43,7 @@ public class TestRunner { ...@@ -44,7 +43,7 @@ public class TestRunner {
* @param files * @param files
* @param args * @param args
*/ */
public TestRunner(TestRunnerConfiguration configuration, File[] files, String[] args) { public TestRunner(TestRunnerConfiguration configuration, String[] files, String[] args) {
this.files = files.clone(); this.files = files.clone();
this.compiler = new GroovyCompiler(configuration); this.compiler = new GroovyCompiler(configuration);
} }
......
/*
* 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();
}
}
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.cli; package org.springframework.boot.cli;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URI; import java.net.URI;
...@@ -104,8 +105,13 @@ public class CliTester implements TestRule { ...@@ -104,8 +105,13 @@ public class CliTester implements TestRule {
final String[] sources = new String[args.length]; final String[] sources = new String[args.length];
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
String arg = args[i]; String arg = args[i];
if (arg.startsWith("-")) { if (!arg.endsWith(".groovy") && !arg.endsWith(".xml")) {
sources[i] = arg; if (new File(this.prefix + arg).isDirectory()) {
sources[i] = this.prefix + arg;
}
else {
sources[i] = arg;
}
} }
else { else {
sources[i] = this.prefix + arg; sources[i] = this.prefix + arg;
......
/*
* 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"));
}
}
...@@ -18,7 +18,6 @@ package org.springframework.boot.cli.command; ...@@ -18,7 +18,6 @@ package org.springframework.boot.cli.command;
import groovy.lang.Closure; import groovy.lang.Closure;
import java.io.File;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -55,8 +54,8 @@ public class ScriptCompilationCustomizerTests { ...@@ -55,8 +54,8 @@ public class ScriptCompilationCustomizerTests {
@Test @Test
public void simpleCompile() throws Exception { public void simpleCompile() throws Exception {
Class<?>[] types = this.compiler.compile(new File( Class<?>[] types = this.compiler
"src/test/resources/scripts/command.groovy")); .compile("src/test/resources/scripts/command.groovy");
Class<?> main = types[0]; Class<?> main = types[0];
assertEquals("org.test.command.TestCommand", main.getName()); assertEquals("org.test.command.TestCommand", main.getName());
assertTrue(Command.class.isAssignableFrom(main)); assertTrue(Command.class.isAssignableFrom(main));
...@@ -64,24 +63,21 @@ public class ScriptCompilationCustomizerTests { ...@@ -64,24 +63,21 @@ public class ScriptCompilationCustomizerTests {
@Test @Test
public void addsOptionHandler() throws Exception { public void addsOptionHandler() throws Exception {
Class<?>[] types = this.compiler.compile(new File( Class<?>[] types = this.compiler.compile("classpath:/scripts/handler.groovy");
"src/test/resources/scripts/handler.groovy"));
Class<?> main = types[0]; Class<?> main = types[0];
assertTrue(OptionHandler.class.isAssignableFrom(main)); assertTrue(OptionHandler.class.isAssignableFrom(main));
} }
@Test @Test
public void addsCommands() throws Exception { public void addsCommands() throws Exception {
Class<?>[] types = this.compiler.compile(new File( Class<?>[] types = this.compiler.compile("classpath:scripts/commands.groovy");
"src/test/resources/scripts/commands.groovy"));
Class<?> main = types[0]; Class<?> main = types[0];
assertTrue(Commands.class.isAssignableFrom(main)); assertTrue(Commands.class.isAssignableFrom(main));
} }
@Test @Test
public void closureWithStringArgs() throws Exception { public void closureWithStringArgs() throws Exception {
Class<?>[] types = this.compiler.compile(new File( Class<?>[] types = this.compiler.compile("classpath:scripts/commands.groovy");
"src/test/resources/scripts/commands.groovy"));
Class<?> main = types[0]; Class<?> main = types[0];
Map<String, Closure<?>> commands = ((Commands) main.newInstance()).getCommands(); Map<String, Closure<?>> commands = ((Commands) main.newInstance()).getCommands();
assertEquals(1, commands.size()); assertEquals(1, commands.size());
...@@ -93,8 +89,8 @@ public class ScriptCompilationCustomizerTests { ...@@ -93,8 +89,8 @@ public class ScriptCompilationCustomizerTests {
@Test @Test
public void closureWithEmptyArgs() throws Exception { public void closureWithEmptyArgs() throws Exception {
Class<?>[] types = this.compiler.compile(new File( Class<?>[] types = this.compiler
"src/test/resources/scripts/commands.groovy")); .compile("src/test/resources/scripts/commands.groovy");
Class<?> main = types[0]; Class<?> main = types[0];
Map<String, Closure<?>> commands = ((Commands) main.newInstance()).getCommands(); Map<String, Closure<?>> commands = ((Commands) main.newInstance()).getCommands();
assertEquals(1, commands.size()); assertEquals(1, commands.size());
...@@ -106,8 +102,8 @@ public class ScriptCompilationCustomizerTests { ...@@ -106,8 +102,8 @@ public class ScriptCompilationCustomizerTests {
@Test @Test
public void closureAndOptionsDefined() throws Exception { public void closureAndOptionsDefined() throws Exception {
Class<?>[] types = this.compiler.compile(new File( Class<?>[] types = this.compiler
"src/test/resources/scripts/options.groovy")); .compile("src/test/resources/scripts/options.groovy");
Class<?> main = types[0]; Class<?> main = types[0];
Commands commands = (Commands) main.newInstance(); Commands commands = (Commands) main.newInstance();
Map<String, Closure<?>> closures = commands.getCommands(); Map<String, Closure<?>> closures = commands.getCommands();
......
/*
* 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:"));
}
}
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!"
}
}
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