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