001/*
002 * Copyright 2012-2017 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.command.run;
018
019import java.io.File;
020import java.util.Arrays;
021import java.util.List;
022import java.util.logging.Level;
023
024import joptsimple.OptionSet;
025import joptsimple.OptionSpec;
026
027import org.springframework.boot.cli.command.Command;
028import org.springframework.boot.cli.command.OptionParsingCommand;
029import org.springframework.boot.cli.command.options.CompilerOptionHandler;
030import org.springframework.boot.cli.command.options.OptionSetGroovyCompilerConfiguration;
031import org.springframework.boot.cli.command.options.SourceOptions;
032import org.springframework.boot.cli.command.status.ExitStatus;
033import org.springframework.boot.cli.compiler.GroovyCompilerScope;
034import org.springframework.boot.cli.compiler.RepositoryConfigurationFactory;
035import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration;
036
037/**
038 * {@link Command} to 'run' a groovy script or scripts.
039 *
040 * @author Phillip Webb
041 * @author Dave Syer
042 * @author Andy Wilkinson
043 * @see SpringApplicationRunner
044 */
045public class RunCommand extends OptionParsingCommand {
046
047        public RunCommand() {
048                super("run", "Run a spring groovy script", new RunOptionHandler());
049        }
050
051        @Override
052        public String getUsageHelp() {
053                return "[options] <files> [--] [args]";
054        }
055
056        public void stop() {
057                if (this.getHandler() != null) {
058                        ((RunOptionHandler) this.getHandler()).stop();
059                }
060        }
061
062        private static class RunOptionHandler extends CompilerOptionHandler {
063
064                private final Object monitor = new Object();
065
066                private OptionSpec<Void> watchOption;
067
068                private OptionSpec<Void> verboseOption;
069
070                private OptionSpec<Void> quietOption;
071
072                private SpringApplicationRunner runner;
073
074                @Override
075                protected void doOptions() {
076                        this.watchOption = option("watch", "Watch the specified file for changes");
077                        this.verboseOption = option(Arrays.asList("verbose", "v"),
078                                        "Verbose logging of dependency resolution");
079                        this.quietOption = option(Arrays.asList("quiet", "q"), "Quiet logging");
080                }
081
082                public void stop() {
083                        synchronized (this.monitor) {
084                                if (this.runner != null) {
085                                        this.runner.stop();
086                                }
087                                this.runner = null;
088                        }
089                }
090
091                @Override
092                protected synchronized ExitStatus run(OptionSet options) throws Exception {
093                        synchronized (this.monitor) {
094                                if (this.runner != null) {
095                                        throw new RuntimeException(
096                                                        "Already running. Please stop the current application before running another (use the 'stop' command).");
097                                }
098
099                                SourceOptions sourceOptions = new SourceOptions(options);
100
101                                List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
102                                                .createDefaultRepositoryConfiguration();
103                                repositoryConfiguration.add(0, new RepositoryConfiguration("local",
104                                                new File("repository").toURI(), true));
105
106                                SpringApplicationRunnerConfiguration configuration = new SpringApplicationRunnerConfigurationAdapter(
107                                                options, this, repositoryConfiguration);
108
109                                this.runner = new SpringApplicationRunner(configuration,
110                                                sourceOptions.getSourcesArray(), sourceOptions.getArgsArray());
111                                this.runner.compileAndRun();
112
113                                return ExitStatus.OK;
114                        }
115                }
116
117                /**
118                 * Simple adapter class to present the {@link OptionSet} as a
119                 * {@link SpringApplicationRunnerConfiguration}.
120                 */
121                private class SpringApplicationRunnerConfigurationAdapter
122                                extends OptionSetGroovyCompilerConfiguration
123                                implements SpringApplicationRunnerConfiguration {
124
125                        SpringApplicationRunnerConfigurationAdapter(OptionSet options,
126                                        CompilerOptionHandler optionHandler,
127                                        List<RepositoryConfiguration> repositoryConfiguration) {
128                                super(options, optionHandler, repositoryConfiguration);
129                        }
130
131                        @Override
132                        public GroovyCompilerScope getScope() {
133                                return GroovyCompilerScope.DEFAULT;
134                        }
135
136                        @Override
137                        public boolean isWatchForFileChanges() {
138                                return getOptions().has(RunOptionHandler.this.watchOption);
139                        }
140
141                        @Override
142                        public Level getLogLevel() {
143                                if (isQuiet()) {
144                                        return Level.OFF;
145                                }
146                                if (getOptions().has(RunOptionHandler.this.verboseOption)) {
147                                        return Level.FINEST;
148                                }
149                                return Level.INFO;
150                        }
151
152                        @Override
153                        public boolean isQuiet() {
154                                return getOptions().has(RunOptionHandler.this.quietOption);
155                        }
156
157                }
158
159        }
160
161}