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