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.classrealm.ClassRealmManager;
40 import org.apache.maven.model.Build;
41 import org.apache.maven.model.Extension;
42 import org.apache.maven.model.Model;
43 import org.apache.maven.model.Plugin;
44 import org.apache.maven.model.Repository;
45 import org.apache.maven.plugin.ExtensionRealmCache;
46 import org.apache.maven.plugin.MavenPluginManager;
47 import org.apache.maven.plugin.PluginManagerException;
48 import org.apache.maven.plugin.PluginResolutionException;
49 import org.apache.maven.plugin.version.PluginVersionResolutionException;
50 import org.apache.maven.repository.RepositorySystem;
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
65 @Named
66 @Singleton
67 public class DefaultProjectBuildingHelper implements ProjectBuildingHelper {
68 private final Logger logger = LoggerFactory.getLogger(getClass());
69 private final PlexusContainer container;
70 private final ClassRealmManager classRealmManager;
71 private final ProjectRealmCache projectRealmCache;
72 private final RepositorySystem repositorySystem;
73 private final MavenPluginManager pluginManager;
74
75 @Inject
76 public DefaultProjectBuildingHelper(
77 PlexusContainer container,
78 ClassRealmManager classRealmManager,
79 ProjectRealmCache projectRealmCache,
80 RepositorySystem repositorySystem,
81 MavenPluginManager pluginManager) {
82 this.container = container;
83 this.classRealmManager = classRealmManager;
84 this.projectRealmCache = projectRealmCache;
85 this.repositorySystem = repositorySystem;
86 this.pluginManager = pluginManager;
87 }
88
89 public List<ArtifactRepository> createArtifactRepositories(
90 List<Repository> pomRepositories,
91 List<ArtifactRepository> externalRepositories,
92 ProjectBuildingRequest request)
93 throws InvalidRepositoryException {
94 List<ArtifactRepository> internalRepositories = new ArrayList<>();
95
96 for (Repository repository : pomRepositories) {
97 internalRepositories.add(repositorySystem.buildArtifactRepository(repository));
98 }
99
100 repositorySystem.injectMirror(request.getRepositorySession(), internalRepositories);
101
102 repositorySystem.injectProxy(request.getRepositorySession(), internalRepositories);
103
104 repositorySystem.injectAuthentication(request.getRepositorySession(), internalRepositories);
105
106 List<ArtifactRepository> dominantRepositories;
107 List<ArtifactRepository> recessiveRepositories;
108
109 if (ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT.equals(request.getRepositoryMerging())) {
110 dominantRepositories = externalRepositories;
111 recessiveRepositories = internalRepositories;
112 } else {
113 dominantRepositories = internalRepositories;
114 recessiveRepositories = externalRepositories;
115 }
116
117 List<ArtifactRepository> artifactRepositories = new ArrayList<>();
118 Collection<String> repoIds = new HashSet<>();
119
120 if (dominantRepositories != null) {
121 for (ArtifactRepository repository : dominantRepositories) {
122 repoIds.add(repository.getId());
123 artifactRepositories.add(repository);
124 }
125 }
126
127 if (recessiveRepositories != null) {
128 for (ArtifactRepository repository : recessiveRepositories) {
129 if (repoIds.add(repository.getId())) {
130 artifactRepositories.add(repository);
131 }
132 }
133 }
134
135 artifactRepositories = repositorySystem.getEffectiveRepositories(artifactRepositories);
136
137 return artifactRepositories;
138 }
139
140 public synchronized ProjectRealmCache.CacheRecord createProjectRealm(
141 MavenProject project, Model model, ProjectBuildingRequest request)
142 throws PluginResolutionException, PluginVersionResolutionException, PluginManagerException {
143 ClassRealm projectRealm;
144
145 List<Plugin> extensionPlugins = new ArrayList<>();
146
147 Build build = model.getBuild();
148
149 if (build != null) {
150 for (Extension extension : build.getExtensions()) {
151 Plugin plugin = new Plugin();
152 plugin.setGroupId(extension.getGroupId());
153 plugin.setArtifactId(extension.getArtifactId());
154 plugin.setVersion(extension.getVersion());
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 }