Merge pull request #4168 from d10xa/gh-925

* gh-4168:
  Add `spring war` command
pull/4137/merge
Phillip Webb 9 years ago
commit bbee66bac9

@ -122,6 +122,21 @@
<artifactId>groovy-templates</artifactId> <artifactId>groovy-templates</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>

@ -44,7 +44,7 @@ public class CommandLineIT {
assertThat(cli.await(), equalTo(0)); assertThat(cli.await(), equalTo(0));
assertThat("Unexpected error: \n" + cli.getErrorOutput(), assertThat("Unexpected error: \n" + cli.getErrorOutput(),
cli.getErrorOutput().length(), equalTo(0)); cli.getErrorOutput().length(), equalTo(0));
assertThat(cli.getStandardOutputLines().size(), equalTo(10)); assertThat(cli.getStandardOutputLines().size(), equalTo(11));
} }
@Test @Test

@ -19,7 +19,7 @@ package org.springframework.boot.cli;
import java.io.File; import java.io.File;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.cli.command.jar.JarCommand; import org.springframework.boot.cli.command.archive.JarCommand;
import org.springframework.boot.cli.infrastructure.CommandLineInvoker; import org.springframework.boot.cli.infrastructure.CommandLineInvoker;
import org.springframework.boot.cli.infrastructure.CommandLineInvoker.Invocation; import org.springframework.boot.cli.infrastructure.CommandLineInvoker.Invocation;
import org.springframework.boot.loader.tools.JavaExecutable; import org.springframework.boot.loader.tools.JavaExecutable;

@ -0,0 +1,64 @@
/*
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.cli;
import java.io.File;
import org.junit.Test;
import org.springframework.boot.cli.command.archive.WarCommand;
import org.springframework.boot.cli.infrastructure.CommandLineInvoker;
import org.springframework.boot.cli.infrastructure.CommandLineInvoker.Invocation;
import org.springframework.boot.loader.tools.JavaExecutable;
import org.springframework.util.SocketUtils;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Integration test for {@link WarCommand}.
*
* @author Andrey Stolyarov
*/
public class WarCommandIT {
private final CommandLineInvoker cli = new CommandLineInvoker(
new File("src/it/resources/war-command"));
@Test
public void warCreation() throws Exception {
int port = SocketUtils.findAvailableTcpPort();
File war = new File("target/test-app.war");
Invocation invocation = this.cli.invoke("war", war.getAbsolutePath(),
"war.groovy");
invocation.await();
assertTrue(war.exists());
Process process = new JavaExecutable()
.processBuilder("-jar", war.getAbsolutePath(), "--server.port=" + port)
.start();
invocation = new Invocation(process);
invocation.await();
assertThat(invocation.getErrorOutput(), containsString("onStart error"));
assertThat(invocation.getStandardOutput(), containsString("Tomcat started"));
assertThat(invocation.getStandardOutput(),
containsString("/WEB-INF/lib-provided/tomcat-embed-core"));
assertThat(invocation.getStandardOutput(),
containsString("/WEB-INF/lib-provided/tomcat-embed-core"));
process.destroy();
}
}

@ -0,0 +1,16 @@
package org.test
@RestController
class WarExample implements CommandLineRunner {
@RequestMapping("/")
public String hello() {
return "Hello"
}
void run(String... args) {
println getClass().getResource('/org/apache/tomcat/InstanceManager.class')
throw new RuntimeException("onStart error")
}
}

@ -22,12 +22,13 @@ import java.util.List;
import org.springframework.boot.cli.command.Command; import org.springframework.boot.cli.command.Command;
import org.springframework.boot.cli.command.CommandFactory; import org.springframework.boot.cli.command.CommandFactory;
import org.springframework.boot.cli.command.archive.JarCommand;
import org.springframework.boot.cli.command.archive.WarCommand;
import org.springframework.boot.cli.command.core.VersionCommand; import org.springframework.boot.cli.command.core.VersionCommand;
import org.springframework.boot.cli.command.grab.GrabCommand; import org.springframework.boot.cli.command.grab.GrabCommand;
import org.springframework.boot.cli.command.init.InitCommand; import org.springframework.boot.cli.command.init.InitCommand;
import org.springframework.boot.cli.command.install.InstallCommand; import org.springframework.boot.cli.command.install.InstallCommand;
import org.springframework.boot.cli.command.install.UninstallCommand; import org.springframework.boot.cli.command.install.UninstallCommand;
import org.springframework.boot.cli.command.jar.JarCommand;
import org.springframework.boot.cli.command.run.RunCommand; import org.springframework.boot.cli.command.run.RunCommand;
import org.springframework.boot.cli.command.test.TestCommand; import org.springframework.boot.cli.command.test.TestCommand;
@ -40,7 +41,7 @@ public class DefaultCommandFactory implements CommandFactory {
private static final List<Command> DEFAULT_COMMANDS = Arrays.<Command>asList( private static final List<Command> DEFAULT_COMMANDS = Arrays.<Command>asList(
new VersionCommand(), new RunCommand(), new TestCommand(), new GrabCommand(), new VersionCommand(), new RunCommand(), new TestCommand(), new GrabCommand(),
new JarCommand(), new InstallCommand(), new UninstallCommand(), new JarCommand(), new WarCommand(), new InstallCommand(), new UninstallCommand(),
new InitCommand()); new InitCommand());
@Override @Override

@ -0,0 +1,87 @@
/*
* Copyright 2012-2015 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.app;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.Manifest;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
/**
* {@link SpringBootServletInitializer} for CLI packaged WAR files.
*
* @author Phillip Webb
* @since 1.3.0
*/
public class SpringApplicationWebApplicationInitializer
extends SpringBootServletInitializer {
/**
* The entry containing the source class.
*/
public static final String SOURCE_ENTRY = "Spring-Application-Source-Classes";
private String[] sources;
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
try {
this.sources = getSources(servletContext);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
super.onStartup(servletContext);
}
private String[] getSources(ServletContext servletContext) throws IOException {
Manifest manifest = getManifest(servletContext);
if (manifest == null) {
throw new IllegalStateException("Unable to read manifest");
}
String sources = manifest.getMainAttributes().getValue(SOURCE_ENTRY);
return sources.split(",");
}
private Manifest getManifest(ServletContext servletContext) throws IOException {
InputStream stream = servletContext.getResourceAsStream("/META-INF/MANIFEST.MF");
Manifest manifest = (stream == null ? null : new Manifest(stream));
return manifest;
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?>[] sourceClasses = new Class<?>[this.sources.length];
for (int i = 0; i < this.sources.length; i++) {
sourceClasses[i] = classLoader.loadClass(this.sources[i]);
}
return builder.sources(sourceClasses)
.properties("spring.groovy.template.check-template-location=false");
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
}

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.cli.jar; package org.springframework.boot.cli.archive;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;

@ -16,6 +16,6 @@
/** /**
* Class that are packaged as part of CLI generated JARs. * Class that are packaged as part of CLI generated JARs.
* @see org.springframework.boot.cli.command.jar.JarCommand * @see org.springframework.boot.cli.command.archive.JarCommand
*/ */
package org.springframework.boot.cli.jar; package org.springframework.boot.cli.archive;

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.cli.command.jar; package org.springframework.boot.cli.command.archive;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -38,10 +38,12 @@ import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.transform.ASTTransformation; import org.codehaus.groovy.transform.ASTTransformation;
import org.springframework.boot.cli.app.SpringApplicationLauncher; import org.springframework.boot.cli.app.SpringApplicationLauncher;
import org.springframework.boot.cli.archive.PackagedSpringApplicationLauncher;
import org.springframework.boot.cli.command.Command; import org.springframework.boot.cli.command.Command;
import org.springframework.boot.cli.command.OptionParsingCommand; import org.springframework.boot.cli.command.OptionParsingCommand;
import org.springframework.boot.cli.command.jar.ResourceMatcher.MatchedResource; import org.springframework.boot.cli.command.archive.ResourceMatcher.MatchedResource;
import org.springframework.boot.cli.command.options.CompilerOptionHandler; import org.springframework.boot.cli.command.options.CompilerOptionHandler;
import org.springframework.boot.cli.command.options.OptionHandler;
import org.springframework.boot.cli.command.options.OptionSetGroovyCompilerConfiguration; import org.springframework.boot.cli.command.options.OptionSetGroovyCompilerConfiguration;
import org.springframework.boot.cli.command.options.SourceOptions; import org.springframework.boot.cli.command.options.SourceOptions;
import org.springframework.boot.cli.command.status.ExitStatus; import org.springframework.boot.cli.command.status.ExitStatus;
@ -49,8 +51,8 @@ import org.springframework.boot.cli.compiler.GroovyCompiler;
import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration; import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration;
import org.springframework.boot.cli.compiler.RepositoryConfigurationFactory; import org.springframework.boot.cli.compiler.RepositoryConfigurationFactory;
import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration;
import org.springframework.boot.cli.jar.PackagedSpringApplicationLauncher;
import org.springframework.boot.loader.tools.JarWriter; import org.springframework.boot.loader.tools.JarWriter;
import org.springframework.boot.loader.tools.Layout;
import org.springframework.boot.loader.tools.Libraries; import org.springframework.boot.loader.tools.Libraries;
import org.springframework.boot.loader.tools.Library; import org.springframework.boot.loader.tools.Library;
import org.springframework.boot.loader.tools.LibraryCallback; import org.springframework.boot.loader.tools.LibraryCallback;
@ -65,51 +67,66 @@ import joptsimple.OptionSet;
import joptsimple.OptionSpec; import joptsimple.OptionSpec;
/** /**
* {@link Command} to create a self-contained executable jar file from a CLI application. * Abstract {@link Command} to create a self-contained executable archive file from a CLI
* application.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Phillip Webb * @author Phillip Webb
* @author Andrey Stolyarov
*/ */
public class JarCommand extends OptionParsingCommand { abstract class ArchiveCommand extends OptionParsingCommand {
public JarCommand() { protected ArchiveCommand(String name, String description,
super("jar", OptionHandler optionHandler) {
"Create a self-contained " super(name, description, optionHandler);
+ "executable jar file from a Spring Groovy script",
new JarOptionHandler());
} }
@Override @Override
public String getUsageHelp() { public String getUsageHelp() {
return "[options] <jar-name> <files>"; return "[options] <" + getName() + "-name> <files>";
} }
private static final class JarOptionHandler extends CompilerOptionHandler { /**
* Abstract base {@link CompilerOptionHandler} for archive commands.
*/
protected abstract static class ArchiveOptionHandler extends CompilerOptionHandler {
private final String type;
private final Layout layout;
private OptionSpec<String> includeOption; private OptionSpec<String> includeOption;
private OptionSpec<String> excludeOption; private OptionSpec<String> excludeOption;
public ArchiveOptionHandler(String type, Layout layout) {
this.type = type;
this.layout = layout;
}
@Override @Override
protected void doOptions() { protected void doOptions() {
this.includeOption = option("include", this.includeOption = option("include",
"Pattern applied to directories on the classpath to find files to include in the resulting jar") "Pattern applied to directories on the classpath to find files to "
.withRequiredArg().withValuesSeparatedBy(",").defaultsTo(""); + "include in the resulting ").withRequiredArg()
.withValuesSeparatedBy(",").defaultsTo("");
this.excludeOption = option("exclude", this.excludeOption = option("exclude",
"Pattern applied to directories on the classpath to find files to exclude from the resulting jar") "Pattern applied to directories on the classpath to find files to "
.withRequiredArg().withValuesSeparatedBy(",").defaultsTo(""); + "exclude from the resulting " + this.type).withRequiredArg()
.withValuesSeparatedBy(",").defaultsTo("");
} }
@Override @Override
protected ExitStatus run(OptionSet options) throws Exception { protected ExitStatus run(OptionSet options) throws Exception {
List<?> nonOptionArguments = new ArrayList<Object>( List<?> nonOptionArguments = new ArrayList<Object>(
options.nonOptionArguments()); options.nonOptionArguments());
Assert.isTrue(nonOptionArguments.size() >= 2, Assert.isTrue(nonOptionArguments.size() >= 2, "The name of the resulting "
"The name of the resulting jar and at least one source file must be specified"); + this.type + " and at least one source file must be specified");
File output = new File((String) nonOptionArguments.remove(0)); File output = new File((String) nonOptionArguments.remove(0));
Assert.isTrue(output.getName().toLowerCase().endsWith(".jar"), Assert.isTrue(output.getName().toLowerCase().endsWith("." + this.type),
"The output '" + output + "' is not a JAR file."); "The output '" + output + "' is not a " + this.type.toUpperCase()
+ " file.");
deleteIfExists(output); deleteIfExists(output);
GroovyCompiler compiler = createCompiler(options); GroovyCompiler compiler = createCompiler(options);
@ -196,7 +213,7 @@ public class JarCommand extends OptionParsingCommand {
List<Library> libraries = new ArrayList<Library>(); List<Library> libraries = new ArrayList<Library>();
for (URL dependency : dependencies) { for (URL dependency : dependencies) {
File file = new File(dependency.toURI()); File file = new File(dependency.toURI());
libraries.add(new Library(file, LibraryScope.COMPILE)); libraries.add(new Library(file, getLibraryScope(file)));
} }
return libraries; return libraries;
} }
@ -220,7 +237,7 @@ public class JarCommand extends OptionParsingCommand {
return builder.toString(); return builder.toString();
} }
private void addCliClasses(JarWriter writer) throws IOException { protected void addCliClasses(JarWriter writer) throws IOException {
addClass(writer, PackagedSpringApplicationLauncher.class); addClass(writer, PackagedSpringApplicationLauncher.class);
addClass(writer, SpringApplicationLauncher.class); addClass(writer, SpringApplicationLauncher.class);
Resource[] resources = new PathMatchingResourcePatternResolver() Resource[] resources = new PathMatchingResourcePatternResolver()
@ -232,10 +249,19 @@ public class JarCommand extends OptionParsingCommand {
} }
} }
private void addClass(JarWriter writer, Class<?> sourceClass) throws IOException { protected final void addClass(JarWriter writer, Class<?> sourceClass)
String name = sourceClass.getName().replace(".", "/") + ".class"; throws IOException {
InputStream stream = sourceClass.getResourceAsStream("/" + name); addClass(writer, sourceClass.getClassLoader(), sourceClass.getName());
writer.writeEntry(name, stream); }
protected final void addClass(JarWriter writer, ClassLoader classLoader,
String sourceClass) throws IOException {
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
String name = sourceClass.replace(".", "/") + ".class";
InputStream stream = classLoader.getResourceAsStream(name);
writer.writeEntry(this.layout.getClassesLocation() + name, stream);
} }
private void addResource(JarWriter writer, Resource resource, String name) private void addResource(JarWriter writer, Resource resource, String name)
@ -259,6 +285,8 @@ public class JarCommand extends OptionParsingCommand {
return libraries; return libraries;
} }
protected abstract LibraryScope getLibraryScope(File file);
} }
/** /**

@ -0,0 +1,51 @@
/*
* Copyright 2012-2015 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.archive;
import java.io.File;
import org.springframework.boot.cli.command.Command;
import org.springframework.boot.loader.tools.Layouts;
import org.springframework.boot.loader.tools.LibraryScope;
/**
* {@link Command} to create a self-contained executable jar file from a CLI application.
*
* @author Andy Wilkinson
* @author Phillip Webb
*/
public class JarCommand extends ArchiveCommand {
public JarCommand() {
super("jar", "Create a self-contained executable jar "
+ "file from a Spring Groovy script", new JarOptionHandler());
}
private static final class JarOptionHandler extends ArchiveOptionHandler {
JarOptionHandler() {
super("jar", new Layouts.Jar());
}
@Override
protected LibraryScope getLibraryScope(File file) {
return LibraryScope.COMPILE;
}
}
}

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.cli.command.jar; package org.springframework.boot.cli.command.archive;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;

@ -0,0 +1,66 @@
/*
* Copyright 2012-2015 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.archive;
import java.io.File;
import java.io.IOException;
import org.springframework.boot.cli.command.Command;
import org.springframework.boot.loader.tools.JarWriter;
import org.springframework.boot.loader.tools.Layouts;
import org.springframework.boot.loader.tools.LibraryScope;
/**
* {@link Command} to create a self-contained executable jar file from a CLI application.
*
* @author Andrey Stolyarov
* @author Phillip Webb
* @since 1.3.0
*/
public class WarCommand extends ArchiveCommand {
public WarCommand() {
super("war", "Create a self-contained executable war "
+ "file from a Spring Groovy script", new WarOptionHandler());
}
private static final class WarOptionHandler extends ArchiveOptionHandler {
WarOptionHandler() {
super("war", new Layouts.War());
}
@Override
protected LibraryScope getLibraryScope(File file) {
String fileName = file.getName();
if (fileName.contains("tomcat-embed")
|| fileName.contains("spring-boot-starter-tomcat")) {
return LibraryScope.PROVIDED;
}
return LibraryScope.COMPILE;
}
@Override
protected void addCliClasses(JarWriter writer) throws IOException {
addClass(writer, null, "org.springframework.boot."
+ "cli.app.SpringApplicationWebApplicationInitializer");
super.addCliClasses(writer);
}
}
}

@ -36,8 +36,8 @@ import org.junit.runner.Description;
import org.junit.runners.model.Statement; import org.junit.runners.model.Statement;
import org.springframework.boot.cli.command.AbstractCommand; import org.springframework.boot.cli.command.AbstractCommand;
import org.springframework.boot.cli.command.OptionParsingCommand; import org.springframework.boot.cli.command.OptionParsingCommand;
import org.springframework.boot.cli.command.archive.JarCommand;
import org.springframework.boot.cli.command.grab.GrabCommand; import org.springframework.boot.cli.command.grab.GrabCommand;
import org.springframework.boot.cli.command.jar.JarCommand;
import org.springframework.boot.cli.command.run.RunCommand; import org.springframework.boot.cli.command.run.RunCommand;
import org.springframework.boot.cli.command.test.TestCommand; import org.springframework.boot.cli.command.test.TestCommand;
import org.springframework.boot.cli.util.OutputCapture; import org.springframework.boot.cli.util.OutputCapture;

@ -16,10 +16,10 @@
package org.springframework.boot.cli.app; package org.springframework.boot.cli.app;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.junit.After; import org.junit.After;
import org.junit.Test; import org.junit.Test;
@ -90,27 +90,34 @@ public class SpringApplicationLauncherTests {
equalTo("false")); equalTo("false"));
} }
private List<String> launch() { private Set<String> launch() {
TestClassLoader classLoader = new TestClassLoader(getClass().getClassLoader()); TestClassLoader classLoader = new TestClassLoader(getClass().getClassLoader());
try { try {
new TestSpringApplicationLauncher(classLoader).launch(new Object[0], new TestSpringApplicationLauncher(classLoader).launch(new Object[0],
new String[0]); new String[0]);
} }
catch (Exception e) { catch (Exception ex) {
// SpringApplication isn't on the classpath, but we can still check that // Launch will fail, but we can still check that the launcher tried to use
// the launcher tried to use the right class // the right class
} }
return classLoader.classes; return classLoader.classes;
} }
private static class TestClassLoader extends ClassLoader { private static class TestClassLoader extends ClassLoader {
private List<String> classes = new ArrayList<String>(); private Set<String> classes = new HashSet<String>();
TestClassLoader(ClassLoader parent) { TestClassLoader(ClassLoader parent) {
super(parent); super(parent);
} }
@Override
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
this.classes.add(name);
return super.loadClass(name, resolve);
}
@Override @Override
protected Class<?> findClass(String name) throws ClassNotFoundException { protected Class<?> findClass(String name) throws ClassNotFoundException {
this.classes.add(name); this.classes.add(name);

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.cli.command.jar; package org.springframework.boot.cli.command.archive;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -26,7 +26,7 @@ import java.util.List;
import org.hamcrest.Description; import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher; import org.hamcrest.TypeSafeMatcher;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.cli.command.jar.ResourceMatcher.MatchedResource; import org.springframework.boot.cli.command.archive.ResourceMatcher.MatchedResource;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
Loading…
Cancel
Save