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.devtools;
018
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.List;
022
023import org.springframework.boot.Banner;
024import org.springframework.boot.ResourceBanner;
025import org.springframework.boot.SpringApplication;
026import org.springframework.boot.WebApplicationType;
027import org.springframework.boot.context.config.AnsiOutputApplicationListener;
028import org.springframework.boot.context.config.ConfigFileApplicationListener;
029import org.springframework.boot.context.logging.ClasspathLoggingApplicationListener;
030import org.springframework.boot.context.logging.LoggingApplicationListener;
031import org.springframework.boot.devtools.remote.client.RemoteClientConfiguration;
032import org.springframework.boot.devtools.restart.RestartInitializer;
033import org.springframework.boot.devtools.restart.RestartScopeInitializer;
034import org.springframework.boot.devtools.restart.Restarter;
035import org.springframework.context.ApplicationContextInitializer;
036import org.springframework.context.ApplicationListener;
037import org.springframework.core.io.ClassPathResource;
038
039/**
040 * Application that can be used to establish a link to remotely running Spring Boot code.
041 * Allows remote updates (if enabled). This class should be launched from within your IDE
042 * and should have the same classpath configuration as the locally developed application.
043 * The remote URL of the application should be provided as a non-option argument.
044 *
045 * @author Phillip Webb
046 * @since 1.3.0
047 * @see RemoteClientConfiguration
048 */
049public final class RemoteSpringApplication {
050
051        private RemoteSpringApplication() {
052        }
053
054        private void run(String[] args) {
055                Restarter.initialize(args, RestartInitializer.NONE);
056                SpringApplication application = new SpringApplication(
057                                RemoteClientConfiguration.class);
058                application.setWebApplicationType(WebApplicationType.NONE);
059                application.setBanner(getBanner());
060                application.setInitializers(getInitializers());
061                application.setListeners(getListeners());
062                application.run(args);
063                waitIndefinitely();
064        }
065
066        private Collection<ApplicationContextInitializer<?>> getInitializers() {
067                List<ApplicationContextInitializer<?>> initializers = new ArrayList<>();
068                initializers.add(new RestartScopeInitializer());
069                return initializers;
070        }
071
072        private Collection<ApplicationListener<?>> getListeners() {
073                List<ApplicationListener<?>> listeners = new ArrayList<>();
074                listeners.add(new AnsiOutputApplicationListener());
075                listeners.add(new ConfigFileApplicationListener());
076                listeners.add(new ClasspathLoggingApplicationListener());
077                listeners.add(new LoggingApplicationListener());
078                listeners.add(new RemoteUrlPropertyExtractor());
079                return listeners;
080        }
081
082        private Banner getBanner() {
083                ClassPathResource banner = new ClassPathResource("remote-banner.txt",
084                                RemoteSpringApplication.class);
085                return new ResourceBanner(banner);
086        }
087
088        private void waitIndefinitely() {
089                while (true) {
090                        try {
091                                Thread.sleep(1000);
092                        }
093                        catch (InterruptedException ex) {
094                                Thread.currentThread().interrupt();
095                        }
096                }
097        }
098
099        /**
100         * Run the {@link RemoteSpringApplication}.
101         * @param args the program arguments (including the remote URL as a non-option
102         * argument)
103         */
104        public static void main(String[] args) {
105                new RemoteSpringApplication().run(args);
106        }
107
108}