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