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