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.app; 018 019import java.lang.reflect.Constructor; 020import java.lang.reflect.Method; 021import java.util.HashMap; 022import java.util.Map; 023 024/** 025 * A launcher for {@code SpringApplication} or a {@code SpringApplication} subclass. The 026 * class that is used can be configured using the System property 027 * {@code spring.application.class.name} or the {@code SPRING_APPLICATION_CLASS_NAME} 028 * environment variable. Uses reflection to allow the launching code to exist in a 029 * separate ClassLoader from the application code. 030 * 031 * @author Andy Wilkinson 032 * @since 1.2.0 033 * @see System#getProperty(String) 034 * @see System#getenv(String) 035 */ 036public class SpringApplicationLauncher { 037 038 private static final String DEFAULT_SPRING_APPLICATION_CLASS = "org.springframework.boot.SpringApplication"; 039 040 private final ClassLoader classLoader; 041 042 /** 043 * Creates a new launcher that will use the given {@code classLoader} to load the 044 * configured {@code SpringApplication} class. 045 * @param classLoader the {@code ClassLoader} to use 046 */ 047 public SpringApplicationLauncher(ClassLoader classLoader) { 048 this.classLoader = classLoader; 049 } 050 051 /** 052 * Launches the application created using the given {@code sources}. The application 053 * is launched with the given {@code args}. 054 * @param sources the sources for the application 055 * @param args the args for the application 056 * @return the application's {@code ApplicationContext} 057 * @throws Exception if the launch fails 058 */ 059 public Object launch(Class<?>[] sources, String[] args) throws Exception { 060 Map<String, Object> defaultProperties = new HashMap<>(); 061 defaultProperties.put("spring.groovy.template.check-template-location", "false"); 062 Class<?> applicationClass = this.classLoader 063 .loadClass(getSpringApplicationClassName()); 064 Constructor<?> constructor = applicationClass.getConstructor(Class[].class); 065 Object application = constructor.newInstance((Object) sources); 066 applicationClass.getMethod("setDefaultProperties", Map.class).invoke(application, 067 defaultProperties); 068 Method method = applicationClass.getMethod("run", String[].class); 069 return method.invoke(application, (Object) args); 070 } 071 072 private String getSpringApplicationClassName() { 073 String className = System.getProperty("spring.application.class.name"); 074 if (className == null) { 075 className = getEnvironmentVariable("SPRING_APPLICATION_CLASS_NAME"); 076 } 077 if (className == null) { 078 className = DEFAULT_SPRING_APPLICATION_CLASS; 079 } 080 return className; 081 } 082 083 protected String getEnvironmentVariable(String name) { 084 return System.getenv(name); 085 } 086 087}