1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.project;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.LinkedHashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34
35 import org.apache.maven.RepositoryUtils;
36 import org.apache.maven.artifact.Artifact;
37 import org.apache.maven.artifact.InvalidRepositoryException;
38 import org.apache.maven.artifact.repository.ArtifactRepository;
39 import org.apache.maven.bridge.MavenRepositorySystem;
40 import org.apache.maven.classrealm.ClassRealmManager;
41 import org.apache.maven.model.Build;
42 import org.apache.maven.model.Extension;
43 import org.apache.maven.model.Model;
44 import org.apache.maven.model.Plugin;
45 import org.apache.maven.model.Repository;
46 import org.apache.maven.plugin.ExtensionRealmCache;
47 import org.apache.maven.plugin.MavenPluginManager;
48 import org.apache.maven.plugin.PluginManagerException;
49 import org.apache.maven.plugin.PluginResolutionException;
50 import org.apache.maven.plugin.version.PluginVersionResolutionException;
51 import org.codehaus.plexus.PlexusContainer;
52 import org.codehaus.plexus.classworlds.realm.ClassRealm;
53 import org.eclipse.aether.graph.DependencyFilter;
54 import org.eclipse.aether.util.filter.ExclusionsDependencyFilter;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58
59
60
61
62
63
64 @Named
65 @Singleton
66 public class DefaultProjectBuildingHelper implements ProjectBuildingHelper {
67 private final Logger logger = LoggerFactory.getLogger(getClass());
68 private final PlexusContainer container;
69 private final ClassRealmManager classRealmManager;
70 private final ProjectRealmCache projectRealmCache;
71 private final MavenRepositorySystem repositorySystem;
72 private final MavenPluginManager pluginManager;
73
74 @Inject
75 public DefaultProjectBuildingHelper(
76 PlexusContainer container,
77 ClassRealmManager classRealmManager,
78 ProjectRealmCache projectRealmCache,
79 MavenRepositorySystem repositorySystem,
80 MavenPluginManager pluginManager) {
81 this.container = container;
82 this.classRealmManager = classRealmManager;
83 this.projectRealmCache = projectRealmCache;
84 this.repositorySystem = repositorySystem;
85 this.pluginManager = pluginManager;
86 }
87
88 public List<ArtifactRepository> createArtifactRepositories(
89 List<Repository> pomRepositories,
90 List<ArtifactRepository> externalRepositories,
91 ProjectBuildingRequest request)
92 throws InvalidRepositoryException {
93 List<ArtifactRepository> internalRepositories = new ArrayList<>();
94
95 for (Repository repository : pomRepositories) {
96 internalRepositories.add(MavenRepositorySystem.buildArtifactRepository(repository));
97 }
98
99 repositorySystem.injectMirror(request.getRepositorySession(), internalRepositories);
100
101 repositorySystem.injectProxy(request.getRepositorySession(), internalRepositories);
102
103 repositorySystem.injectAuthentication(request.getRepositorySession(), internalRepositories);
104
105 List<ArtifactRepository> dominantRepositories;
106 List<ArtifactRepository> recessiveRepositories;
107
108 if (ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT.equals(request.getRepositoryMerging())) {
109 dominantRepositories = externalRepositories;
110 recessiveRepositories = internalRepositories;
111 } else {
112 dominantRepositories = internalRepositories;
113 recessiveRepositories = externalRepositories;
114 }
115
116 List<ArtifactRepository> artifactRepositories = new ArrayList<>();
117 Collection<String> repoIds = new HashSet<>();
118
119 if (dominantRepositories != null) {
120 for (ArtifactRepository repository : dominantRepositories) {
121 repoIds.add(repository.getId());
122 artifactRepositories.add(repository);
123 }
124 }
125
126 if (recessiveRepositories != null) {
127 for (ArtifactRepository repository : recessiveRepositories) {
128 if (repoIds.add(repository.getId())) {
129 artifactRepositories.add(repository);
130 }
131 }
132 }
133
134 artifactRepositories = repositorySystem.getEffectiveRepositories(artifactRepositories);
135
136 return artifactRepositories;
137 }
138
139 public synchronized ProjectRealmCache.CacheRecord createProjectRealm(
140 MavenProject project, Model model, ProjectBuildingRequest request)
141 throws PluginResolutionException, PluginVersionResolutionException, PluginManagerException {
142 ClassRealm projectRealm;
143
144 List<Plugin> extensionPlugins = new ArrayList<>();
145
146 Build build = model.getBuild();
147
148 if (build != null) {
149 for (Extension extension : build.getExtensions()) {
150 Plugin plugin = new Plugin();
151 plugin.setGroupId(extension.getGroupId());
152 plugin.setArtifactId(extension.getArtifactId());
153 plugin.setVersion(extension.getVersion());
154 plugin.setConfiguration(extension.getConfiguration());
155 extensionPlugins.add(plugin);
156 }
157
158 for (Plugin plugin : build.getPlugins()) {
159 if (plugin.isExtensions()) {
160 extensionPlugins.add(plugin);
161 }
162 }
163 }
164
165 if (extensionPlugins.isEmpty()) {
166 if (logger.isDebugEnabled()) {
167 logger.debug("Extension realms for project " + model.getId() + ": (none)");
168 }
169
170 return new ProjectRealmCache.CacheRecord(null, null);
171 }
172
173 List<ClassRealm> extensionRealms = new ArrayList<>();
174
175 Map<ClassRealm, List<String>> exportedPackages = new HashMap<>();
176
177 Map<ClassRealm, List<String>> exportedArtifacts = new HashMap<>();
178
179 List<Artifact> publicArtifacts = new ArrayList<>();
180
181 for (Plugin plugin : extensionPlugins) {
182 ExtensionRealmCache.CacheRecord recordRealm =
183 pluginManager.setupExtensionsRealm(project, plugin, request.getRepositorySession());
184
185 final ClassRealm extensionRealm = recordRealm.getRealm();
186 final ExtensionDescriptor extensionDescriptor = recordRealm.getDescriptor();
187 final List<Artifact> artifacts = recordRealm.getArtifacts();
188
189 extensionRealms.add(extensionRealm);
190 if (extensionDescriptor != null) {
191 exportedPackages.put(extensionRealm, extensionDescriptor.getExportedPackages());
192 exportedArtifacts.put(extensionRealm, extensionDescriptor.getExportedArtifacts());
193 }
194
195 if (!plugin.isExtensions()
196 && artifacts.size() == 1
197 && artifacts.get(0).getFile() != null) {
198
199
200
201
202
203 publicArtifacts.addAll(artifacts);
204 }
205 }
206
207 if (logger.isDebugEnabled()) {
208 logger.debug("Extension realms for project " + model.getId() + ": " + extensionRealms);
209 }
210
211 ProjectRealmCache.Key projectRealmKey = projectRealmCache.createKey(extensionRealms);
212
213 ProjectRealmCache.CacheRecord record = projectRealmCache.get(projectRealmKey);
214
215 if (record == null) {
216 projectRealm = classRealmManager.createProjectRealm(model, toAetherArtifacts(publicArtifacts));
217
218 Set<String> exclusions = new LinkedHashSet<>();
219
220 for (ClassRealm extensionRealm : extensionRealms) {
221 List<String> excludes = exportedArtifacts.get(extensionRealm);
222
223 if (excludes != null) {
224 exclusions.addAll(excludes);
225 }
226
227 List<String> exports = exportedPackages.get(extensionRealm);
228
229 if (exports == null || exports.isEmpty()) {
230
231
232
233
234
235 exports = Arrays.asList(extensionRealm.getId());
236 }
237
238 for (String export : exports) {
239 projectRealm.importFrom(extensionRealm, export);
240 }
241 }
242
243 DependencyFilter extensionArtifactFilter = null;
244 if (!exclusions.isEmpty()) {
245 extensionArtifactFilter = new ExclusionsDependencyFilter(exclusions);
246 }
247
248 record = projectRealmCache.put(projectRealmKey, projectRealm, extensionArtifactFilter);
249 }
250
251 projectRealmCache.register(project, projectRealmKey, record);
252
253 return record;
254 }
255
256 public void selectProjectRealm(MavenProject project) {
257 ClassLoader projectRealm = project.getClassRealm();
258
259 if (projectRealm == null) {
260 projectRealm = classRealmManager.getCoreRealm();
261 }
262
263 Thread.currentThread().setContextClassLoader(projectRealm);
264 }
265
266 private List<org.eclipse.aether.artifact.Artifact> toAetherArtifacts(final List<Artifact> pluginArtifacts) {
267 return new ArrayList<>(RepositoryUtils.toArtifacts(pluginArtifacts));
268 }
269 }