001/*
002 * Copyright 2012-2016 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.compiler.autoconfigure;
018
019import groovy.lang.GroovyClassLoader;
020import org.codehaus.groovy.ast.AnnotationNode;
021import org.codehaus.groovy.ast.ClassHelper;
022import org.codehaus.groovy.ast.ClassNode;
023import org.codehaus.groovy.classgen.GeneratorContext;
024import org.codehaus.groovy.control.CompilationFailedException;
025import org.codehaus.groovy.control.SourceUnit;
026import org.codehaus.groovy.control.customizers.ImportCustomizer;
027
028import org.springframework.boot.cli.compiler.CompilerAutoConfiguration;
029import org.springframework.boot.cli.compiler.DependencyCustomizer;
030import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration;
031
032/**
033 * {@link CompilerAutoConfiguration} for Spring.
034 *
035 * @author Dave Syer
036 * @author Phillip Webb
037 */
038public class SpringBootCompilerAutoConfiguration extends CompilerAutoConfiguration {
039
040        @Override
041        public void applyDependencies(DependencyCustomizer dependencies) {
042                dependencies.ifAnyMissingClasses("org.springframework.boot.SpringApplication")
043                                .add("spring-boot-starter");
044        }
045
046        @Override
047        public void applyImports(ImportCustomizer imports) {
048                imports.addImports("javax.annotation.PostConstruct",
049                                "javax.annotation.PreDestroy", "groovy.util.logging.Log",
050                                "org.springframework.stereotype.Controller",
051                                "org.springframework.stereotype.Service",
052                                "org.springframework.stereotype.Component",
053                                "org.springframework.beans.factory.annotation.Autowired",
054                                "org.springframework.beans.factory.annotation.Value",
055                                "org.springframework.context.annotation.Import",
056                                "org.springframework.context.annotation.ImportResource",
057                                "org.springframework.context.annotation.Profile",
058                                "org.springframework.context.annotation.Scope",
059                                "org.springframework.context.annotation.Configuration",
060                                "org.springframework.context.annotation.ComponentScan",
061                                "org.springframework.context.annotation.Bean",
062                                "org.springframework.context.ApplicationContext",
063                                "org.springframework.context.MessageSource",
064                                "org.springframework.core.annotation.Order",
065                                "org.springframework.core.io.ResourceLoader",
066                                "org.springframework.boot.ApplicationRunner",
067                                "org.springframework.boot.ApplicationArguments",
068                                "org.springframework.boot.CommandLineRunner",
069                                "org.springframework.boot.context.properties.ConfigurationProperties",
070                                "org.springframework.boot.context.properties.EnableConfigurationProperties",
071                                "org.springframework.boot.autoconfigure.EnableAutoConfiguration",
072                                "org.springframework.boot.autoconfigure.SpringBootApplication",
073                                "org.springframework.boot.context.properties.ConfigurationProperties",
074                                "org.springframework.boot.context.properties.EnableConfigurationProperties");
075                imports.addStarImports("org.springframework.stereotype",
076                                "org.springframework.scheduling.annotation");
077        }
078
079        @Override
080        public void applyToMainClass(GroovyClassLoader loader,
081                        GroovyCompilerConfiguration configuration, GeneratorContext generatorContext,
082                        SourceUnit source, ClassNode classNode) throws CompilationFailedException {
083                addEnableAutoConfigurationAnnotation(source, classNode);
084        }
085
086        private void addEnableAutoConfigurationAnnotation(SourceUnit source,
087                        ClassNode classNode) {
088                if (!hasEnableAutoConfigureAnnotation(classNode)) {
089                        AnnotationNode annotationNode = new AnnotationNode(
090                                        ClassHelper.make("EnableAutoConfiguration"));
091                        classNode.addAnnotation(annotationNode);
092                }
093        }
094
095        private boolean hasEnableAutoConfigureAnnotation(ClassNode classNode) {
096                for (AnnotationNode node : classNode.getAnnotations()) {
097                        String name = node.getClassNode().getNameWithoutPackage();
098                        if ("EnableAutoConfiguration".equals(name)
099                                        || "SpringBootApplication".equals(name)) {
100                                return true;
101                        }
102                }
103                return false;
104        }
105
106}