Extract inner-classes from GroovyCompiler
Extract and refactor inner-classes from the GroovyCompiler to improve code readability.
This commit is contained in:
parent
8d186945e7
commit
a6a1929274
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.cli.compiler;
|
||||||
|
|
||||||
|
import groovy.lang.GroovyClassLoader;
|
||||||
|
|
||||||
|
import org.codehaus.groovy.ast.ASTNode;
|
||||||
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
|
import org.codehaus.groovy.ast.ModuleNode;
|
||||||
|
import org.codehaus.groovy.control.SourceUnit;
|
||||||
|
import org.codehaus.groovy.transform.ASTTransformation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ASTTransformation} to apply
|
||||||
|
* {@link CompilerAutoConfiguration#applyDependencies(DependencyCustomizer) dependency
|
||||||
|
* auto-configuration}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Dave Syer
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
class DependencyAutoConfigurationTransformation implements ASTTransformation {
|
||||||
|
|
||||||
|
private final GroovyClassLoader loader;
|
||||||
|
|
||||||
|
private final ArtifactCoordinatesResolver coordinatesResolver;
|
||||||
|
|
||||||
|
private final Iterable<CompilerAutoConfiguration> compilerAutoConfigurations;
|
||||||
|
|
||||||
|
DependencyAutoConfigurationTransformation(GroovyClassLoader loader,
|
||||||
|
ArtifactCoordinatesResolver coordinatesResolver,
|
||||||
|
Iterable<CompilerAutoConfiguration> compilerAutoConfigurations) {
|
||||||
|
this.loader = loader;
|
||||||
|
this.coordinatesResolver = coordinatesResolver;
|
||||||
|
this.compilerAutoConfigurations = compilerAutoConfigurations;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ASTNode[] nodes, SourceUnit source) {
|
||||||
|
for (ASTNode astNode : nodes) {
|
||||||
|
if (astNode instanceof ModuleNode) {
|
||||||
|
visitModule((ModuleNode) astNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitModule(ModuleNode module) {
|
||||||
|
DependencyCustomizer dependencies = new DependencyCustomizer(this.loader, module,
|
||||||
|
this.coordinatesResolver);
|
||||||
|
for (ClassNode classNode : module.getClasses()) {
|
||||||
|
for (CompilerAutoConfiguration autoConfiguration : this.compilerAutoConfigurations) {
|
||||||
|
if (autoConfiguration.matches(classNode)) {
|
||||||
|
autoConfiguration.applyDependencies(dependencies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,17 +41,17 @@ public class DependencyCustomizer {
|
||||||
|
|
||||||
private final ClassNode classNode;
|
private final ClassNode classNode;
|
||||||
|
|
||||||
private final ArtifactCoordinatesResolver artifactCoordinatesResolver;
|
private final ArtifactCoordinatesResolver coordinatesResolver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link DependencyCustomizer} instance.
|
* Create a new {@link DependencyCustomizer} instance.
|
||||||
* @param loader
|
* @param loader
|
||||||
*/
|
*/
|
||||||
public DependencyCustomizer(GroovyClassLoader loader, ModuleNode moduleNode,
|
public DependencyCustomizer(GroovyClassLoader loader, ModuleNode moduleNode,
|
||||||
ArtifactCoordinatesResolver artifactCoordinatesResolver) {
|
ArtifactCoordinatesResolver coordinatesResolver) {
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
this.classNode = moduleNode.getClasses().get(0);
|
this.classNode = moduleNode.getClasses().get(0);
|
||||||
this.artifactCoordinatesResolver = artifactCoordinatesResolver;
|
this.coordinatesResolver = coordinatesResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,7 +61,7 @@ public class DependencyCustomizer {
|
||||||
protected DependencyCustomizer(DependencyCustomizer parent) {
|
protected DependencyCustomizer(DependencyCustomizer parent) {
|
||||||
this.loader = parent.loader;
|
this.loader = parent.loader;
|
||||||
this.classNode = parent.classNode;
|
this.classNode = parent.classNode;
|
||||||
this.artifactCoordinatesResolver = parent.artifactCoordinatesResolver;
|
this.coordinatesResolver = parent.coordinatesResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVersion(String artifactId) {
|
public String getVersion(String artifactId) {
|
||||||
|
@ -70,7 +70,7 @@ public class DependencyCustomizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVersion(String artifactId, String defaultVersion) {
|
public String getVersion(String artifactId, String defaultVersion) {
|
||||||
String version = this.artifactCoordinatesResolver.getVersion(artifactId);
|
String version = this.coordinatesResolver.getVersion(artifactId);
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
version = defaultVersion;
|
version = defaultVersion;
|
||||||
}
|
}
|
||||||
|
@ -184,8 +184,8 @@ public class DependencyCustomizer {
|
||||||
* @return this {@link DependencyCustomizer} for continued use
|
* @return this {@link DependencyCustomizer} for continued use
|
||||||
*/
|
*/
|
||||||
public DependencyCustomizer add(String module) {
|
public DependencyCustomizer add(String module) {
|
||||||
return this.add(this.artifactCoordinatesResolver.getGroupId(module), module,
|
return this.add(this.coordinatesResolver.getGroupId(module), module,
|
||||||
this.artifactCoordinatesResolver.getVersion(module), true);
|
this.coordinatesResolver.getVersion(module), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,8 +198,8 @@ public class DependencyCustomizer {
|
||||||
* @return this {@link DependencyCustomizer} for continued use
|
* @return this {@link DependencyCustomizer} for continued use
|
||||||
*/
|
*/
|
||||||
public DependencyCustomizer add(String module, boolean transitive) {
|
public DependencyCustomizer add(String module, boolean transitive) {
|
||||||
return this.add(this.artifactCoordinatesResolver.getGroupId(module), module,
|
return this.add(this.coordinatesResolver.getGroupId(module), module,
|
||||||
this.artifactCoordinatesResolver.getVersion(module), transitive);
|
this.coordinatesResolver.getVersion(module), transitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DependencyCustomizer add(String group, String module, String version,
|
private DependencyCustomizer add(String group, String module, String version,
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package org.springframework.boot.cli.compiler;
|
package org.springframework.boot.cli.compiler;
|
||||||
|
|
||||||
import groovy.grape.GrapeEngine;
|
import groovy.grape.GrapeEngine;
|
||||||
import groovy.lang.Grab;
|
|
||||||
import groovy.lang.GroovyClassLoader;
|
import groovy.lang.GroovyClassLoader;
|
||||||
import groovy.lang.GroovyClassLoader.ClassCollector;
|
import groovy.lang.GroovyClassLoader.ClassCollector;
|
||||||
|
|
||||||
|
@ -34,14 +33,7 @@ import java.util.List;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
import org.codehaus.groovy.ast.ASTNode;
|
import org.codehaus.groovy.ast.ASTNode;
|
||||||
import org.codehaus.groovy.ast.AnnotatedNode;
|
|
||||||
import org.codehaus.groovy.ast.AnnotationNode;
|
|
||||||
import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
|
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
import org.codehaus.groovy.ast.ImportNode;
|
|
||||||
import org.codehaus.groovy.ast.ModuleNode;
|
|
||||||
import org.codehaus.groovy.ast.expr.ConstantExpression;
|
|
||||||
import org.codehaus.groovy.ast.expr.Expression;
|
|
||||||
import org.codehaus.groovy.classgen.GeneratorContext;
|
import org.codehaus.groovy.classgen.GeneratorContext;
|
||||||
import org.codehaus.groovy.control.CompilationFailedException;
|
import org.codehaus.groovy.control.CompilationFailedException;
|
||||||
import org.codehaus.groovy.control.CompilationUnit;
|
import org.codehaus.groovy.control.CompilationUnit;
|
||||||
|
@ -66,6 +58,7 @@ import org.codehaus.groovy.transform.ASTTransformationVisitor;
|
||||||
*
|
*
|
||||||
* <li>Generated class files can also be loaded using
|
* <li>Generated class files can also be loaded using
|
||||||
* {@link ClassLoader#getResource(String)}</li>
|
* {@link ClassLoader#getResource(String)}</li>
|
||||||
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
|
@ -77,32 +70,45 @@ public class GroovyCompiler {
|
||||||
private static final ClassLoader AETHER_CLASS_LOADER = new URLClassLoader(
|
private static final ClassLoader AETHER_CLASS_LOADER = new URLClassLoader(
|
||||||
new URL[] { GroovyCompiler.class.getResource("/internal/") });
|
new URL[] { GroovyCompiler.class.getResource("/internal/") });
|
||||||
|
|
||||||
private GroovyCompilerConfiguration configuration;
|
private final GroovyCompilerConfiguration configuration;
|
||||||
|
|
||||||
private ExtendedGroovyClassLoader loader;
|
private final ExtendedGroovyClassLoader loader;
|
||||||
|
|
||||||
private ArtifactCoordinatesResolver artifactCoordinatesResolver;
|
private final ArtifactCoordinatesResolver coordinatesResolver;
|
||||||
|
|
||||||
private final ASTTransformation dependencyCustomizerTransformation = new DependencyCustomizerAstTransformation();
|
private final ServiceLoader<CompilerAutoConfiguration> compilerAutoConfigurations;
|
||||||
|
|
||||||
private final ASTTransformation dependencyCoordinatesTransformation = new DefaultDependencyCoordinatesAstTransformation();
|
private final List<ASTTransformation> transformations;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link GroovyCompiler} instance.
|
* Create a new {@link GroovyCompiler} instance.
|
||||||
* @param configuration the compiler configuration
|
* @param configuration the compiler configuration
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public GroovyCompiler(final GroovyCompilerConfiguration configuration) {
|
public GroovyCompiler(final GroovyCompilerConfiguration configuration) {
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
|
|
||||||
this.loader = new ExtendedGroovyClassLoader(getClass().getClassLoader(),
|
this.loader = new ExtendedGroovyClassLoader(getClass().getClassLoader(),
|
||||||
compilerConfiguration);
|
new CompilerConfiguration());
|
||||||
if (configuration.getClasspath().length() > 0) {
|
if (configuration.getClasspath().length() > 0) {
|
||||||
this.loader.addClasspath(configuration.getClasspath());
|
this.loader.addClasspath(configuration.getClasspath());
|
||||||
}
|
}
|
||||||
this.artifactCoordinatesResolver = new PropertiesArtifactCoordinatesResolver(
|
this.coordinatesResolver = new PropertiesArtifactCoordinatesResolver(this.loader);
|
||||||
this.loader);
|
installGrapeEngine();
|
||||||
|
this.loader.getConfiguration().addCompilationCustomizers(
|
||||||
|
new CompilerAutoConfigureCustomizer());
|
||||||
|
this.compilerAutoConfigurations = ServiceLoader.load(
|
||||||
|
CompilerAutoConfiguration.class, GroovyCompiler.class.getClassLoader());
|
||||||
|
|
||||||
|
this.transformations = new ArrayList<ASTTransformation>();
|
||||||
|
this.transformations.add(new DependencyAutoConfigurationTransformation(this.loader,
|
||||||
|
this.coordinatesResolver, this.compilerAutoConfigurations));
|
||||||
|
if (this.configuration.isGuessDependencies()) {
|
||||||
|
this.transformations.add(new ResolveDependencyCoordinatesTransformation(
|
||||||
|
this.coordinatesResolver));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void installGrapeEngine() {
|
||||||
try {
|
try {
|
||||||
Class<GrapeEngine> grapeEngineClass = (Class<GrapeEngine>) AETHER_CLASS_LOADER
|
Class<GrapeEngine> grapeEngineClass = (Class<GrapeEngine>) AETHER_CLASS_LOADER
|
||||||
.loadClass("org.springframework.boot.cli.compiler.AetherGrapeEngine");
|
.loadClass("org.springframework.boot.cli.compiler.AetherGrapeEngine");
|
||||||
|
@ -110,16 +116,13 @@ public class GroovyCompiler {
|
||||||
GroovyClassLoader.class, String.class, String.class, String.class);
|
GroovyClassLoader.class, String.class, String.class, String.class);
|
||||||
GrapeEngine grapeEngine = constructor.newInstance(this.loader,
|
GrapeEngine grapeEngine = constructor.newInstance(this.loader,
|
||||||
"org.springframework.boot", "spring-boot-starter-parent",
|
"org.springframework.boot", "spring-boot-starter-parent",
|
||||||
this.artifactCoordinatesResolver.getVersion("spring-boot"));
|
this.coordinatesResolver.getVersion("spring-boot"));
|
||||||
|
|
||||||
new GrapeEngineInstaller(grapeEngine).install();
|
new GrapeEngineInstaller(grapeEngine).install();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new IllegalStateException("Failed to install custom GrapeEngine", ex);
|
throw new IllegalStateException("Failed to install custom GrapeEngine", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
compilerConfiguration
|
|
||||||
.addCompilationCustomizers(new CompilerAutoConfigureCustomizer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCompilationCustomizers(CompilationCustomizer... customizers) {
|
public void addCompilationCustomizers(CompilationCustomizer... customizers) {
|
||||||
|
@ -157,12 +160,12 @@ public class GroovyCompiler {
|
||||||
this.loader.clearCache();
|
this.loader.clearCache();
|
||||||
List<Class<?>> classes = new ArrayList<Class<?>>();
|
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||||
|
|
||||||
CompilerConfiguration compilerConfiguration = this.loader.getConfiguration();
|
CompilerConfiguration configuration = this.loader.getConfiguration();
|
||||||
|
|
||||||
final CompilationUnit compilationUnit = new CompilationUnit(
|
CompilationUnit compilationUnit = new CompilationUnit(configuration, null,
|
||||||
compilerConfiguration, null, this.loader);
|
this.loader);
|
||||||
SourceUnit sourceUnit = new SourceUnit(file[0], compilerConfiguration,
|
SourceUnit sourceUnit = new SourceUnit(file[0], configuration, this.loader,
|
||||||
this.loader, compilationUnit.getErrorCollector());
|
compilationUnit.getErrorCollector());
|
||||||
ClassCollector collector = this.loader.createCollector(compilationUnit,
|
ClassCollector collector = this.loader.createCollector(compilationUnit,
|
||||||
sourceUnit);
|
sourceUnit);
|
||||||
compilationUnit.setClassgenCallback(collector);
|
compilationUnit.setClassgenCallback(collector);
|
||||||
|
@ -189,18 +192,23 @@ public class GroovyCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
return classes.toArray(new Class<?>[classes.size()]);
|
return classes.toArray(new Class<?>[classes.size()]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
private void addAstTransformations(final CompilationUnit compilationUnit) {
|
private void addAstTransformations(CompilationUnit compilationUnit) {
|
||||||
|
LinkedList[] phaseOperations = getPhaseOperations(compilationUnit);
|
||||||
|
processConversionOperations(phaseOperations[Phases.CONVERSION]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private LinkedList[] getPhaseOperations(final CompilationUnit compilationUnit) {
|
||||||
try {
|
try {
|
||||||
Field field = CompilationUnit.class.getDeclaredField("phaseOperations");
|
Field field = CompilationUnit.class.getDeclaredField("phaseOperations");
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
LinkedList[] phaseOperations = (LinkedList[]) field.get(compilationUnit);
|
LinkedList[] phaseOperations = (LinkedList[]) field.get(compilationUnit);
|
||||||
processConversionOperations(phaseOperations[Phases.CONVERSION]);
|
return phaseOperations;
|
||||||
}
|
}
|
||||||
catch (Exception npe) {
|
catch (Exception ex) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Phase operations not available from compilation unit");
|
"Phase operations not available from compilation unit");
|
||||||
}
|
}
|
||||||
|
@ -208,24 +216,26 @@ public class GroovyCompiler {
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
private void processConversionOperations(LinkedList conversionOperations) {
|
private void processConversionOperations(LinkedList conversionOperations) {
|
||||||
for (int i = 0; i < conversionOperations.size(); i++) {
|
int index = getIndexOfASTTransformationVisitor(conversionOperations);
|
||||||
Object operation = conversionOperations.get(i);
|
conversionOperations.add(index, new CompilationUnit.SourceUnitOperation() {
|
||||||
|
|
||||||
if (operation.getClass().getName()
|
|
||||||
.startsWith(ASTTransformationVisitor.class.getName())) {
|
|
||||||
conversionOperations.add(i, new CompilationUnit.SourceUnitOperation() {
|
|
||||||
@Override
|
@Override
|
||||||
public void call(SourceUnit source) throws CompilationFailedException {
|
public void call(SourceUnit source) throws CompilationFailedException {
|
||||||
ASTNode[] astNodes = new ASTNode[] { source.getAST() };
|
ASTNode[] nodes = new ASTNode[] { source.getAST() };
|
||||||
GroovyCompiler.this.dependencyCustomizerTransformation.visit(
|
for (ASTTransformation transformation : GroovyCompiler.this.transformations) {
|
||||||
astNodes, source);
|
transformation.visit(nodes, source);
|
||||||
GroovyCompiler.this.dependencyCoordinatesTransformation.visit(
|
}
|
||||||
astNodes, source);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
private int getIndexOfASTTransformationVisitor(LinkedList<?> conversionOperations) {
|
||||||
|
for (int index = 0; index < conversionOperations.size(); index++) {
|
||||||
|
if (conversionOperations.get(index).getClass().getName()
|
||||||
|
.startsWith(ASTTransformationVisitor.class.getName())) {
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return conversionOperations.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -243,12 +253,8 @@ public class GroovyCompiler {
|
||||||
|
|
||||||
ImportCustomizer importCustomizer = new ImportCustomizer();
|
ImportCustomizer importCustomizer = new ImportCustomizer();
|
||||||
|
|
||||||
ServiceLoader<CompilerAutoConfiguration> customizers = ServiceLoader.load(
|
|
||||||
CompilerAutoConfiguration.class,
|
|
||||||
GroovyCompiler.class.getClassLoader());
|
|
||||||
|
|
||||||
// Additional auto configuration
|
// Additional auto configuration
|
||||||
for (CompilerAutoConfiguration autoConfiguration : customizers) {
|
for (CompilerAutoConfiguration autoConfiguration : GroovyCompiler.this.compilerAutoConfigurations) {
|
||||||
if (autoConfiguration.matches(classNode)) {
|
if (autoConfiguration.matches(classNode)) {
|
||||||
if (GroovyCompiler.this.configuration.isGuessImports()) {
|
if (GroovyCompiler.this.configuration.isGuessImports()) {
|
||||||
autoConfiguration.applyImports(importCustomizer);
|
autoConfiguration.applyImports(importCustomizer);
|
||||||
|
@ -270,134 +276,4 @@ public class GroovyCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DependencyCustomizerAstTransformation implements ASTTransformation {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(ASTNode[] nodes, SourceUnit source) {
|
|
||||||
|
|
||||||
ServiceLoader<CompilerAutoConfiguration> customizers = ServiceLoader.load(
|
|
||||||
CompilerAutoConfiguration.class,
|
|
||||||
GroovyCompiler.class.getClassLoader());
|
|
||||||
|
|
||||||
for (ASTNode astNode : nodes) {
|
|
||||||
if (astNode instanceof ModuleNode) {
|
|
||||||
ModuleNode module = (ModuleNode) astNode;
|
|
||||||
|
|
||||||
DependencyCustomizer dependencyCustomizer = new DependencyCustomizer(
|
|
||||||
GroovyCompiler.this.loader, module,
|
|
||||||
GroovyCompiler.this.artifactCoordinatesResolver);
|
|
||||||
|
|
||||||
ClassNode firstClass = null;
|
|
||||||
|
|
||||||
for (ClassNode classNode : module.getClasses()) {
|
|
||||||
if (firstClass == null) {
|
|
||||||
firstClass = classNode;
|
|
||||||
}
|
|
||||||
for (CompilerAutoConfiguration autoConfiguration : customizers) {
|
|
||||||
if (autoConfiguration.matches(classNode)) {
|
|
||||||
if (GroovyCompiler.this.configuration
|
|
||||||
.isGuessDependencies()) {
|
|
||||||
autoConfiguration
|
|
||||||
.applyDependencies(dependencyCustomizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DefaultDependencyCoordinatesAstTransformation implements
|
|
||||||
ASTTransformation {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(ASTNode[] nodes, final SourceUnit source) {
|
|
||||||
for (ASTNode node : nodes) {
|
|
||||||
if (node instanceof ModuleNode) {
|
|
||||||
ModuleNode module = (ModuleNode) node;
|
|
||||||
for (ImportNode importNode : module.getImports()) {
|
|
||||||
visitAnnotatedNode(importNode);
|
|
||||||
}
|
|
||||||
for (ClassNode classNode : module.getClasses()) {
|
|
||||||
visitAnnotatedNode(classNode);
|
|
||||||
classNode.visitContents(new ClassCodeVisitorSupport() {
|
|
||||||
@Override
|
|
||||||
protected SourceUnit getSourceUnit() {
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitAnnotations(AnnotatedNode node) {
|
|
||||||
visitAnnotatedNode(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void visitAnnotatedNode(AnnotatedNode annotatedNode) {
|
|
||||||
for (AnnotationNode annotationNode : annotatedNode.getAnnotations()) {
|
|
||||||
if (isGrabAnnotation(annotationNode)) {
|
|
||||||
transformGrabAnnotation(annotationNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isGrabAnnotation(AnnotationNode annotationNode) {
|
|
||||||
String annotationClassName = annotationNode.getClassNode().getName();
|
|
||||||
return annotationClassName.equals(Grab.class.getName())
|
|
||||||
|| annotationClassName.equals(Grab.class.getSimpleName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void transformGrabAnnotation(AnnotationNode grabAnnotation) {
|
|
||||||
grabAnnotation.setMember("initClass", new ConstantExpression(false));
|
|
||||||
|
|
||||||
Expression valueExpression = grabAnnotation.getMember("value");
|
|
||||||
String value = null;
|
|
||||||
if (valueExpression instanceof ConstantExpression) {
|
|
||||||
ConstantExpression constantExpression = (ConstantExpression) valueExpression;
|
|
||||||
Object valueObject = constantExpression.getValue();
|
|
||||||
if (valueObject instanceof String) {
|
|
||||||
value = (String) valueObject;
|
|
||||||
if (isConvenienceForm(value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyGroupAndVersion(grabAnnotation, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isConvenienceForm(String value) {
|
|
||||||
return value.contains(":") || value.contains("#");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyGroupAndVersion(AnnotationNode grabAnnotation, String module) {
|
|
||||||
|
|
||||||
if (module != null) {
|
|
||||||
grabAnnotation.setMember("module", new ConstantExpression(module));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
module = (String) ((ConstantExpression) grabAnnotation.getMembers().get(
|
|
||||||
"module")).getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabAnnotation.getMember("group") == null) {
|
|
||||||
ConstantExpression groupIdExpression = new ConstantExpression(
|
|
||||||
GroovyCompiler.this.artifactCoordinatesResolver
|
|
||||||
.getGroupId(module));
|
|
||||||
grabAnnotation.setMember("group", groupIdExpression);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabAnnotation.getMember("version") == null) {
|
|
||||||
ConstantExpression versionExpression = new ConstantExpression(
|
|
||||||
GroovyCompiler.this.artifactCoordinatesResolver
|
|
||||||
.getVersion(module));
|
|
||||||
grabAnnotation.setMember("version", versionExpression);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.cli.compiler;
|
||||||
|
|
||||||
|
import groovy.lang.Grab;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.codehaus.groovy.ast.ASTNode;
|
||||||
|
import org.codehaus.groovy.ast.AnnotatedNode;
|
||||||
|
import org.codehaus.groovy.ast.AnnotationNode;
|
||||||
|
import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
|
||||||
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
|
import org.codehaus.groovy.ast.ImportNode;
|
||||||
|
import org.codehaus.groovy.ast.ModuleNode;
|
||||||
|
import org.codehaus.groovy.ast.expr.ConstantExpression;
|
||||||
|
import org.codehaus.groovy.ast.expr.Expression;
|
||||||
|
import org.codehaus.groovy.control.SourceUnit;
|
||||||
|
import org.codehaus.groovy.transform.ASTTransformation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ASTTransformation} to resolve {@link Grab} artifact coordinates.
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class ResolveDependencyCoordinatesTransformation implements ASTTransformation {
|
||||||
|
|
||||||
|
private static final Set<String> GRAB_ANNOTATION_NAMES = Collections
|
||||||
|
.unmodifiableSet(new HashSet<String>(Arrays.asList(Grab.class.getName(),
|
||||||
|
Grab.class.getSimpleName())));
|
||||||
|
|
||||||
|
private final ArtifactCoordinatesResolver coordinatesResolver;
|
||||||
|
|
||||||
|
ResolveDependencyCoordinatesTransformation(
|
||||||
|
ArtifactCoordinatesResolver coordinatesResolver) {
|
||||||
|
this.coordinatesResolver = coordinatesResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ASTNode[] nodes, SourceUnit source) {
|
||||||
|
ClassVisitor classVisitor = new ClassVisitor(source);
|
||||||
|
for (ASTNode node : nodes) {
|
||||||
|
if (node instanceof ModuleNode) {
|
||||||
|
ModuleNode module = (ModuleNode) node;
|
||||||
|
for (ImportNode importNode : module.getImports()) {
|
||||||
|
visitAnnotatedNode(importNode);
|
||||||
|
}
|
||||||
|
for (ClassNode classNode : module.getClasses()) {
|
||||||
|
visitAnnotatedNode(classNode);
|
||||||
|
classNode.visitContents(classVisitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitAnnotatedNode(AnnotatedNode annotatedNode) {
|
||||||
|
for (AnnotationNode annotationNode : annotatedNode.getAnnotations()) {
|
||||||
|
if (GRAB_ANNOTATION_NAMES.contains(annotationNode.getClassNode().getName())) {
|
||||||
|
transformGrabAnnotation(annotationNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transformGrabAnnotation(AnnotationNode grabAnnotation) {
|
||||||
|
grabAnnotation.setMember("initClass", new ConstantExpression(false));
|
||||||
|
String value = getValue(grabAnnotation);
|
||||||
|
if (value != null && !isConvenienceForm(value)) {
|
||||||
|
applyGroupAndVersion(grabAnnotation, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getValue(AnnotationNode annotation) {
|
||||||
|
Expression expression = annotation.getMember("value");
|
||||||
|
if (expression instanceof ConstantExpression) {
|
||||||
|
Object value = ((ConstantExpression) expression).getValue();
|
||||||
|
return (value instanceof String ? (String) value : null);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isConvenienceForm(String value) {
|
||||||
|
return value.contains(":") || value.contains("#");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyGroupAndVersion(AnnotationNode annotation, String module) {
|
||||||
|
if (module != null) {
|
||||||
|
setMember(annotation, "module", module);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Expression expression = annotation.getMembers().get("module");
|
||||||
|
module = (String) ((ConstantExpression) expression).getValue();
|
||||||
|
}
|
||||||
|
if (annotation.getMember("group") == null) {
|
||||||
|
setMember(annotation, "group", this.coordinatesResolver.getGroupId(module));
|
||||||
|
}
|
||||||
|
if (annotation.getMember("version") == null) {
|
||||||
|
setMember(annotation, "version", this.coordinatesResolver.getVersion(module));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMember(AnnotationNode annotation, String name, String value) {
|
||||||
|
ConstantExpression expression = new ConstantExpression(value);
|
||||||
|
annotation.setMember(name, expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClassVisitor extends ClassCodeVisitorSupport {
|
||||||
|
|
||||||
|
private final SourceUnit source;
|
||||||
|
|
||||||
|
public ClassVisitor(SourceUnit source) {
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SourceUnit getSourceUnit() {
|
||||||
|
return this.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitAnnotations(AnnotatedNode node) {
|
||||||
|
visitAnnotatedNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue