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