mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
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:
parent
62e02d3d81
commit
bd73705393
@ -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()]);
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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()]);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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"));
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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:"));
|
||||
}
|
||||
|
||||
}
|
@ -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!"
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user