@ -19,18 +19,15 @@ import java.io.File;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.OutputStreamWriter ;
import java.nio.file.FileVisitResult ;
import java.nio.file.FileVisitor ;
import java.nio.file.Files ;
import java.nio.file.Path ;
import java.nio.file.SimpleFileVisitor ;
import java.nio.file.attribute.BasicFileAttributes ;
import java.net.URISyntaxException ;
import java.net.URL ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.List ;
import joptsimple.OptionSet ;
import joptsimple.OptionSpec ;
import org.codehaus.plexus.util.FileUtils ;
import org.springframework.boot.cli.command.Command ;
import org.springframework.boot.cli.command.OptionParsingCommand ;
import org.springframework.boot.cli.command.options.CompilerOptionHandler ;
@ -41,36 +38,38 @@ import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration;
import org.springframework.boot.cli.compiler.RepositoryConfigurationFactory ;
import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration ;
import org.springframework.boot.cli.util.Log ;
import org.springframework.util.FileCopyUtils ;
import org.springframework.util.SystemPropertyUtils ;
/ * *
* { @link Command } to install additional dependencies into the CLI .
*
* @author Dave Syer
* @author Andy Wilkinson
* /
public class InstallCommand extends OptionParsingCommand {
public static Command install ( ) {
return new InstallCommand ( "install" , "Install dependencies to lib directory" ,
new InstallFile Visit orFactory( ) ) ;
new InstallFile Process orFactory( ) ) ;
}
public static Command uninstall ( ) {
return new InstallCommand ( "uninstall" ,
"Uninstall dependencies from a lib directory" ,
new UninstallFile Visit orFactory( ) ) ;
new UninstallFile Process orFactory( ) ) ;
}
private InstallCommand ( String name , String description , File Visit orFactory visitor ) {
private InstallCommand ( String name , String description , File Process orFactory visitor ) {
super ( name , description , new InstallOptionHandler ( visitor ) ) ;
}
private static final class InstallOptionHandler extends CompilerOptionHandler {
private File Visit orFactory factory ;
private File Process orFactory factory ;
private OptionSpec < Void > allOption ;
public InstallOptionHandler ( File Visit orFactory factory ) {
public InstallOptionHandler ( File Process orFactory factory ) {
this . factory = factory ;
}
@ -111,43 +110,60 @@ public class InstallCommand extends OptionParsingCommand {
}
} ;
Path tmpdir = Files . createTempDirectory ( "SpringInstallCommand" )
. toAbsolutePath ( ) ;
String grapeRoot = System . getProperty ( "grape.root" ) ;
System . setProperty ( "grape.root" , tmpdir . toString ( ) ) ;
GroovyCompiler groovyCompiler = new GroovyCompiler ( configuration ) ;
try {
if ( ! args . isEmpty ( ) ) {
List < URL > initialUrls = getClassPathUrls ( groovyCompiler ) ;
groovyCompiler . compile ( createSources ( args ) ) ;
installJars ( tmpdir ) ;
List < URL > urlsToProcessor = getClassPathUrls ( groovyCompiler ) ;
urlsToProcessor . removeAll ( initialUrls ) ;
processJars ( urlsToProcessor ) ;
}
FileUtils . deleteDirectory ( tmpdir . toFile ( ) ) ;
}
catch ( Exception ex ) {
String message = ex . getMessage ( ) ;
Log . error ( message ! = null ? message : ex . getClass ( ) . toString ( ) ) ;
}
finally {
if ( grapeRoot ! = null ) {
System . setProperty ( "grape.root" , grapeRoot ) ;
}
else {
System . clearProperty ( "grape.root" ) ;
}
}
return ExitStatus . OK ;
}
private void installJars ( Path tmpdir ) throws IOException {
private List < URL > getClassPathUrls ( GroovyCompiler compiler ) {
return new ArrayList < URL > ( Arrays . asList ( compiler . getLoader ( ) . getURLs ( ) ) ) ;
}
private void processJars ( List < URL > urlsToProcess ) throws IOException {
File lib = getDefaultLibDirectory ( ) ;
Files . walkFileTree ( tmpdir , this . factory . visitor ( lib ) ) ;
FileProcessor processor = this . factory . processor ( lib ) ;
for ( URL url : urlsToProcess ) {
File file = toFile ( url ) ;
if ( file . getName ( ) . endsWith ( ".jar" ) ) {
processor . processFile ( file ) ;
}
}
}
private File toFile ( URL url ) {
try {
return new File ( url . toURI ( ) ) ;
}
catch ( URISyntaxException ex ) {
return new File ( url . getPath ( ) ) ;
}
}
private void uninstallAllJars ( ) throws IOException {
File lib = getDefaultLibDirectory ( ) ;
Files . walkFileTree ( lib . toPath ( ) , new DeleteNotTheCliVisitor ( ) ) ;
File [ ] filesInLib = lib . listFiles ( ) ;
if ( filesInLib ! = null ) {
FileProcessor processor = new DeleteNotTheCliProcessor ( ) ;
for ( File file : filesInLib ) {
processor . processFile ( file ) ;
}
}
}
private String createSources ( List < String > args ) throws IOException {
@ -177,71 +193,52 @@ public class InstallCommand extends OptionParsingCommand {
}
private interface File Visit orFactory {
File Visitor< Path > visit or( File lib ) ;
private interface File Process orFactory {
File Processor process or( File lib ) ;
}
private static class DeleteNotTheCliVisitor extends SimpleFileVisitor < Path > {
private interface FileProcessor {
void processFile ( File file ) throws IOException ;
}
private static class DeleteNotTheCliProcessor implements FileProcessor {
@Override
public FileVisitResult visitFile ( Path file , BasicFileAttributes attrs )
throws IOException {
String name = file . getFileName ( ) . toString ( ) ;
if ( name . endsWith ( ".jar" ) & & ! name . startsWith ( "spring-boot-cli" ) ) {
file . toFile ( ) . delete ( ) ;
public void processFile ( File file ) throws IOException {
if ( ! file . getName ( ) . startsWith ( "spring-boot-cli" ) ) {
file . delete ( ) ;
}
return FileVisitResult . CONTINUE ;
}
}
private static class InstallFile VisitorFactory implements FileVisit orFactory {
private static class InstallFile ProcessorFactory implements FileProcess orFactory {
@Override
public SimpleFileVisitor< Path > visit or( final File lib ) {
public FileProcessor process or( final File lib ) {
Log . info ( "Installing into: " + lib ) ;
lib . mkdirs ( ) ;
return new SimpleFileVisitor< Path > ( ) {
return new FileProcessor ( ) {
@Override
public FileVisitResult visitFile ( Path file , BasicFileAttributes attrs )
throws IOException {
if ( file . getFileName ( ) . toString ( ) . endsWith ( ".jar" ) ) {
Files . copy ( file , new FileOutputStream ( new File ( lib , file
. getFileName ( ) . toString ( ) ) ) ) ;
return FileVisitResult . SKIP_SIBLINGS ;
}
return FileVisitResult . CONTINUE ;
public void processFile ( File file ) throws IOException {
FileCopyUtils . copy ( file , new File ( lib , file . getName ( ) ) ) ;
}
} ;
}
}
private static class UninstallFile VisitorFactory implements FileVisit orFactory {
private static class UninstallFile ProcessorFactory implements FileProcess orFactory {
@Override
public SimpleFileVisitor< Path > visit or( final File lib ) {
public FileProcessor process or( final File lib ) {
Log . info ( "Uninstalling from: " + lib ) ;
if ( ! lib . exists ( ) ) {
return new SimpleFileVisitor < Path > ( ) {
return new FileProcessor ( ) {
@Override
public FileVisitResult visitFile ( Path file , BasicFileAttributes attrs )
throws IOException {
return FileVisitResult . TERMINATE ;
public void processFile ( File file ) throws IOException {
new File ( lib , file . getName ( ) ) . delete ( ) ;
}
} ;
}
return new SimpleFileVisitor < Path > ( ) {
@Override
public FileVisitResult visitFile ( Path file , BasicFileAttributes attrs )
throws IOException {
if ( file . getFileName ( ) . toString ( ) . endsWith ( ".jar" ) ) {
new File ( lib , file . getFileName ( ) . toString ( ) ) . delete ( ) ;
return FileVisitResult . SKIP_SIBLINGS ;
}
return FileVisitResult . CONTINUE ;
}
} ;
}
}