mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Support @Grab when app has multiple groovy scripts
The AST transformation that processes @Grab annotations is driven once per source file. Previously, this meant that if an app consisted of multiple source files then multiple, discrete dependency resolutions would be performed. This commit updates AetherGrapeEngine to cache a previous resolution's outcome and use its dependency to influence the outcome of subsequent resolutions. For example if a one resolution results in spring-core 4.0.0.RELEASE being added to the classpath, subsequent resolutions that depend upon spring-core will always get the 4.0.0.RELEASE version. This is achieved by using the dependencies found by earlier resolutions as dependency management configuration of the current resolution. This removes the possibility of multiple versions of the same dependency ending up on the classpath. In addition to using the results of earlier resolutions to provide dependency management configuration, default dependency management configuration is also provided. This configuration is specified by the springcli.properties file and ensures that, where Boot prescribes certain versions of a dependency, that is the version that will be resolved. For example, this ensures that spring-data-redis, which depends upon Spring 3.1.4, pulls in the version of Spring that Boot requires instead. Fixes #224
This commit is contained in:
parent
b45683f103
commit
5fb42c3c33
@ -58,6 +58,8 @@ public class AetherGrapeEngine implements GrapeEngine {
|
||||
private static final Collection<Exclusion> WILDCARD_EXCLUSION = Arrays
|
||||
.asList(new Exclusion("*", "*", "*", "*"));
|
||||
|
||||
private final List<Dependency> managedDependencies = new ArrayList<Dependency>();
|
||||
|
||||
private final ProgressReporter progressReporter;
|
||||
|
||||
private final GroovyClassLoader classLoader;
|
||||
@ -71,10 +73,12 @@ public class AetherGrapeEngine implements GrapeEngine {
|
||||
public AetherGrapeEngine(GroovyClassLoader classLoader,
|
||||
RepositorySystem repositorySystem,
|
||||
DefaultRepositorySystemSession repositorySystemSession,
|
||||
List<RemoteRepository> remoteRepositories) {
|
||||
List<RemoteRepository> remoteRepositories,
|
||||
List<Dependency> managedDependencies) {
|
||||
this.classLoader = classLoader;
|
||||
this.repositorySystem = repositorySystem;
|
||||
this.session = repositorySystemSession;
|
||||
this.managedDependencies.addAll(managedDependencies);
|
||||
|
||||
this.repositories = new ArrayList<RemoteRepository>();
|
||||
List<RemoteRepository> remotes = new ArrayList<RemoteRepository>(
|
||||
@ -174,13 +178,20 @@ public class AetherGrapeEngine implements GrapeEngine {
|
||||
|
||||
private List<File> resolve(List<Dependency> dependencies)
|
||||
throws ArtifactResolutionException {
|
||||
|
||||
try {
|
||||
CollectRequest collectRequest = new CollectRequest((Dependency) null,
|
||||
dependencies, new ArrayList<RemoteRepository>(this.repositories));
|
||||
collectRequest.setManagedDependencies(this.managedDependencies);
|
||||
|
||||
DependencyRequest dependencyRequest = new DependencyRequest(collectRequest,
|
||||
DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE));
|
||||
|
||||
DependencyResult dependencyResult = this.repositorySystem
|
||||
.resolveDependencies(this.session, dependencyRequest);
|
||||
|
||||
this.managedDependencies.addAll(getDependencies(dependencyResult));
|
||||
|
||||
return getFiles(dependencyResult);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
@ -191,6 +202,15 @@ public class AetherGrapeEngine implements GrapeEngine {
|
||||
}
|
||||
}
|
||||
|
||||
private List<Dependency> getDependencies(DependencyResult dependencyResult) {
|
||||
List<Dependency> dependencies = new ArrayList<Dependency>();
|
||||
for (ArtifactResult artifactResult : dependencyResult.getArtifactResults()) {
|
||||
dependencies.add(new Dependency(artifactResult.getArtifact(),
|
||||
JavaScopes.COMPILE));
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
private List<File> getFiles(DependencyResult dependencyResult) {
|
||||
List<File> files = new ArrayList<File>();
|
||||
for (ArtifactResult result : dependencyResult.getArtifactResults()) {
|
||||
|
@ -26,6 +26,7 @@ import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
|
||||
import org.eclipse.aether.graph.Dependency;
|
||||
import org.eclipse.aether.impl.DefaultServiceLocator;
|
||||
import org.eclipse.aether.internal.impl.DefaultRepositorySystem;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
@ -62,8 +63,12 @@ public abstract class AetherGrapeEngineFactory {
|
||||
new DefaultRepositorySystemSessionAutoConfiguration().apply(
|
||||
repositorySystemSession, repositorySystem);
|
||||
|
||||
List<Dependency> managedDependencies = new PropertiesManagedDependenciesFactory()
|
||||
.getManagedDependencies();
|
||||
|
||||
return new AetherGrapeEngine(classLoader, repositorySystem,
|
||||
repositorySystemSession, createRepositories(repositoryConfigurations));
|
||||
repositorySystemSession, createRepositories(repositoryConfigurations),
|
||||
managedDependencies);
|
||||
}
|
||||
|
||||
private static ServiceLocator createServiceLocator() {
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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.grape;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.aether.graph.Dependency;
|
||||
|
||||
/**
|
||||
* An abstraction for accessing the managed dependencies that should be used to influence
|
||||
* the outcome of dependency resolution performed by Aether.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public interface ManagedDependenciesFactory {
|
||||
|
||||
List<Dependency> getManagedDependencies();
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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.grape;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.eclipse.aether.artifact.DefaultArtifact;
|
||||
import org.eclipse.aether.graph.Dependency;
|
||||
import org.eclipse.aether.util.artifact.JavaScopes;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link ManagedDependenciesFactory} that uses a properties file to configure the list
|
||||
* of managed dependencies that it returns.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class PropertiesManagedDependenciesFactory implements ManagedDependenciesFactory {
|
||||
|
||||
private static final String PROPERTY_SUFFIX_GROUP_ID = ".groupId";
|
||||
|
||||
private static final String PROPERTY_SUFFIX_VERSION = ".version";
|
||||
|
||||
private final List<Dependency> managedDependencies;
|
||||
|
||||
public PropertiesManagedDependenciesFactory() {
|
||||
Properties properties = loadProperties();
|
||||
this.managedDependencies = getManagedDependencies(properties);
|
||||
}
|
||||
|
||||
private static Properties loadProperties() {
|
||||
Properties properties = new Properties();
|
||||
InputStream inputStream = PropertiesManagedDependenciesFactory.class
|
||||
.getClassLoader().getResourceAsStream("META-INF/springcli.properties");
|
||||
Assert.state(inputStream != null, "Unable to load springcli properties");
|
||||
try {
|
||||
properties.load(inputStream);
|
||||
return properties;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Unable to load springcli properties", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Dependency> getManagedDependencies(Properties properties) {
|
||||
List<Dependency> dependencies = new ArrayList<Dependency>();
|
||||
|
||||
for (Entry<Object, Object> entry : properties.entrySet()) {
|
||||
String propertyName = (String) entry.getKey();
|
||||
if (propertyName.endsWith(PROPERTY_SUFFIX_GROUP_ID)) {
|
||||
String artifactId = propertyName.substring(0, propertyName.length()
|
||||
- PROPERTY_SUFFIX_GROUP_ID.length());
|
||||
String groupId = (String) entry.getValue();
|
||||
String version = properties.getProperty(artifactId
|
||||
+ PROPERTY_SUFFIX_VERSION);
|
||||
|
||||
if (version != null) {
|
||||
Artifact artifact = new DefaultArtifact(groupId, artifactId, "jar",
|
||||
version);
|
||||
dependencies.add(new Dependency(artifact, JavaScopes.COMPILE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Dependency> getManagedDependencies() {
|
||||
return new ArrayList<Dependency>(this.managedDependencies);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user