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