001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.cli; 018 019import java.io.File; 020import java.net.MalformedURLException; 021import java.net.URL; 022import java.net.URLClassLoader; 023import java.util.ArrayList; 024import java.util.List; 025import java.util.ServiceLoader; 026 027import org.springframework.boot.cli.command.CommandFactory; 028import org.springframework.boot.cli.command.CommandRunner; 029import org.springframework.boot.cli.command.core.HelpCommand; 030import org.springframework.boot.cli.command.core.HintCommand; 031import org.springframework.boot.cli.command.core.VersionCommand; 032import org.springframework.boot.cli.command.shell.ShellCommand; 033import org.springframework.boot.loader.tools.LogbackInitializer; 034import org.springframework.util.ClassUtils; 035import org.springframework.util.SystemPropertyUtils; 036 037/** 038 * Spring Command Line Interface. This is the main entry-point for the Spring command line 039 * application. 040 * 041 * @author Phillip Webb 042 * @see #main(String...) 043 * @see CommandRunner 044 */ 045public final class SpringCli { 046 047 private SpringCli() { 048 } 049 050 public static void main(String... args) { 051 System.setProperty("java.awt.headless", Boolean.toString(true)); 052 LogbackInitializer.initialize(); 053 054 CommandRunner runner = new CommandRunner("spring"); 055 ClassUtils.overrideThreadContextClassLoader(createExtendedClassLoader(runner)); 056 runner.addCommand(new HelpCommand(runner)); 057 addServiceLoaderCommands(runner); 058 runner.addCommand(new ShellCommand()); 059 runner.addCommand(new HintCommand(runner)); 060 runner.setOptionCommands(HelpCommand.class, VersionCommand.class); 061 runner.setHiddenCommands(HintCommand.class); 062 063 int exitCode = runner.runAndHandleErrors(args); 064 if (exitCode != 0) { 065 // If successful, leave it to run in case it's a server app 066 System.exit(exitCode); 067 } 068 } 069 070 private static void addServiceLoaderCommands(CommandRunner runner) { 071 ServiceLoader<CommandFactory> factories = ServiceLoader 072 .load(CommandFactory.class); 073 for (CommandFactory factory : factories) { 074 runner.addCommands(factory.getCommands()); 075 } 076 } 077 078 private static URLClassLoader createExtendedClassLoader(CommandRunner runner) { 079 return new URLClassLoader(getExtensionURLs(), runner.getClass().getClassLoader()); 080 } 081 082 private static URL[] getExtensionURLs() { 083 List<URL> urls = new ArrayList<>(); 084 String home = SystemPropertyUtils 085 .resolvePlaceholders("${spring.home:${SPRING_HOME:.}}"); 086 File extDirectory = new File(new File(home, "lib"), "ext"); 087 if (extDirectory.isDirectory()) { 088 for (File file : extDirectory.listFiles()) { 089 if (file.getName().endsWith(".jar")) { 090 try { 091 urls.add(file.toURI().toURL()); 092 } 093 catch (MalformedURLException ex) { 094 throw new IllegalStateException(ex); 095 } 096 } 097 } 098 } 099 return urls.toArray(new URL[0]); 100 } 101 102}