1 package org
.argeo
.slc
.maven
;
4 * Copyright 2001-2005 The Apache Software Foundation.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 import java
.io
.FileNotFoundException
;
21 import java
.io
.FileReader
;
22 import java
.io
.IOException
;
23 import java
.io
.InputStream
;
24 import java
.io
.InputStreamReader
;
25 import java
.io
.Writer
;
26 import java
.util
.ArrayList
;
27 import java
.util
.Collections
;
28 import java
.util
.Date
;
29 import java
.util
.Iterator
;
30 import java
.util
.List
;
31 import java
.util
.Properties
;
33 import org
.apache
.maven
.BuildFailureException
;
34 import org
.apache
.maven
.artifact
.Artifact
;
35 import org
.apache
.maven
.artifact
.factory
.ArtifactFactory
;
36 import org
.apache
.maven
.artifact
.manager
.WagonManager
;
37 import org
.apache
.maven
.artifact
.repository
.ArtifactRepository
;
38 import org
.apache
.maven
.artifact
.repository
.ArtifactRepositoryFactory
;
39 import org
.apache
.maven
.artifact
.repository
.ArtifactRepositoryPolicy
;
40 import org
.apache
.maven
.artifact
.repository
.layout
.ArtifactRepositoryLayout
;
41 import org
.apache
.maven
.artifact
.resolver
.ArtifactNotFoundException
;
42 import org
.apache
.maven
.artifact
.resolver
.ArtifactResolutionException
;
43 import org
.apache
.maven
.artifact
.resolver
.ArtifactResolver
;
44 import org
.apache
.maven
.embedder
.MavenEmbedderException
;
45 import org
.apache
.maven
.embedder
.MavenEmbedderLogger
;
46 import org
.apache
.maven
.embedder
.MavenEmbedderLoggerManager
;
47 import org
.apache
.maven
.embedder
.PlexusLoggerAdapter
;
48 import org
.apache
.maven
.embedder
.SummaryPluginDescriptor
;
49 import org
.apache
.maven
.execution
.MavenSession
;
50 import org
.apache
.maven
.execution
.ReactorManager
;
51 import org
.apache
.maven
.lifecycle
.LifecycleExecutionException
;
52 import org
.apache
.maven
.lifecycle
.LifecycleExecutor
;
53 import org
.apache
.maven
.model
.Model
;
54 import org
.apache
.maven
.model
.io
.xpp3
.MavenXpp3Reader
;
55 import org
.apache
.maven
.model
.io
.xpp3
.MavenXpp3Writer
;
56 import org
.apache
.maven
.monitor
.event
.DefaultEventDispatcher
;
57 import org
.apache
.maven
.monitor
.event
.EventDispatcher
;
58 import org
.apache
.maven
.monitor
.event
.EventMonitor
;
59 import org
.apache
.maven
.plugin
.MojoExecutionException
;
60 import org
.apache
.maven
.plugin
.descriptor
.PluginDescriptor
;
61 import org
.apache
.maven
.plugin
.descriptor
.PluginDescriptorBuilder
;
62 import org
.apache
.maven
.profiles
.DefaultProfileManager
;
63 import org
.apache
.maven
.profiles
.ProfileManager
;
64 import org
.apache
.maven
.project
.DuplicateProjectException
;
65 import org
.apache
.maven
.project
.MavenProject
;
66 import org
.apache
.maven
.project
.MavenProjectBuilder
;
67 import org
.apache
.maven
.project
.ProjectBuildingException
;
68 import org
.apache
.maven
.settings
.MavenSettingsBuilder
;
69 import org
.apache
.maven
.settings
.RuntimeInfo
;
70 import org
.apache
.maven
.settings
.Settings
;
71 import org
.apache
.maven
.wagon
.events
.TransferListener
;
72 import org
.codehaus
.classworlds
.ClassWorld
;
73 import org
.codehaus
.classworlds
.DuplicateRealmException
;
74 import org
.codehaus
.plexus
.PlexusContainerException
;
75 import org
.codehaus
.plexus
.component
.repository
.ComponentDescriptor
;
76 import org
.codehaus
.plexus
.component
.repository
.exception
.ComponentLifecycleException
;
77 import org
.codehaus
.plexus
.component
.repository
.exception
.ComponentLookupException
;
78 import org
.codehaus
.plexus
.configuration
.PlexusConfiguration
;
79 import org
.codehaus
.plexus
.configuration
.PlexusConfigurationException
;
80 import org
.codehaus
.plexus
.embed
.Embedder
;
81 import org
.codehaus
.plexus
.util
.DirectoryScanner
;
82 import org
.codehaus
.plexus
.util
.dag
.CycleDetectedException
;
83 import org
.codehaus
.plexus
.util
.xml
.pull
.XmlPullParserException
;
86 * Class intended to be used by clients who wish to embed Maven into their
89 * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
91 public class SlcMavenEmbedder
{
92 public static final String userHome
= System
.getProperty("user.home");
94 // ----------------------------------------------------------------------
96 // ----------------------------------------------------------------------
98 private Embedder embedder
;
100 // ----------------------------------------------------------------------
102 // ----------------------------------------------------------------------
104 private MavenProjectBuilder mavenProjectBuilder
;
106 private ArtifactRepositoryFactory artifactRepositoryFactory
;
108 private MavenSettingsBuilder settingsBuilder
;
110 private LifecycleExecutor lifecycleExecutor
;
112 private WagonManager wagonManager
;
114 private MavenXpp3Reader modelReader
;
116 private MavenXpp3Writer modelWriter
;
118 private ProfileManager profileManager
;
120 private PluginDescriptorBuilder pluginDescriptorBuilder
;
122 private ArtifactFactory artifactFactory
;
124 private ArtifactResolver artifactResolver
;
126 private ArtifactRepositoryLayout defaultArtifactRepositoryLayout
;
128 // ----------------------------------------------------------------------
130 // ----------------------------------------------------------------------
132 private Settings settings
;
134 private ArtifactRepository localRepository
;
136 private File localRepositoryDirectory
;
138 private ClassLoader classLoader
;
140 private MavenEmbedderLogger logger
;
142 // ----------------------------------------------------------------------
144 // ----------------------------------------------------------------------
146 // release plugin uses this but in IDE there will probably always be some
147 // form of interaction.
148 private boolean interactiveMode
;
150 private boolean offline
;
152 private String globalChecksumPolicy
;
155 * This option determines whether the embedder is to be aligned to the user
158 private boolean alignWithUserInstallation
;
160 // ----------------------------------------------------------------------
162 // ----------------------------------------------------------------------
164 public void setInteractiveMode(boolean interactiveMode
) {
165 this.interactiveMode
= interactiveMode
;
168 public boolean isInteractiveMode() {
169 return interactiveMode
;
172 public void setOffline(boolean offline
) {
173 this.offline
= offline
;
176 public boolean isOffline() {
180 public void setGlobalChecksumPolicy(String globalChecksumPolicy
) {
181 this.globalChecksumPolicy
= globalChecksumPolicy
;
184 public String
getGlobalChecksumPolicy() {
185 return globalChecksumPolicy
;
188 public boolean isAlignWithUserInstallation() {
189 return alignWithUserInstallation
;
192 public void setAlignWithUserInstallation(boolean alignWithUserInstallation
) {
193 this.alignWithUserInstallation
= alignWithUserInstallation
;
197 * Set the classloader to use with the maven embedder.
201 public void setClassLoader(ClassLoader classLoader
) {
202 this.classLoader
= classLoader
;
205 public ClassLoader
getClassLoader() {
209 public void setLocalRepositoryDirectory(File localRepositoryDirectory
) {
210 this.localRepositoryDirectory
= localRepositoryDirectory
;
213 public File
getLocalRepositoryDirectory() {
214 return localRepositoryDirectory
;
217 public ArtifactRepository
getLocalRepository() {
218 return localRepository
;
221 public MavenEmbedderLogger
getLogger() {
225 public void setLogger(MavenEmbedderLogger logger
) {
226 this.logger
= logger
;
229 // ----------------------------------------------------------------------
230 // Embedder Client Contract
231 // ----------------------------------------------------------------------
233 // ----------------------------------------------------------------------
235 // ----------------------------------------------------------------------
237 public Model
readModel(File model
) throws XmlPullParserException
,
238 FileNotFoundException
, IOException
{
239 return modelReader
.read(new FileReader(model
));
242 public void writeModel(Writer writer
, Model model
) throws IOException
{
243 modelWriter
.write(writer
, model
);
246 // ----------------------------------------------------------------------
248 // ----------------------------------------------------------------------
250 public MavenProject
readProject(File mavenProject
)
251 throws ProjectBuildingException
{
252 return mavenProjectBuilder
.build(mavenProject
, localRepository
,
256 public MavenProject
readProjectWithDependencies(File mavenProject
,
257 TransferListener transferListener
) throws ProjectBuildingException
,
258 ArtifactResolutionException
, ArtifactNotFoundException
{
259 return mavenProjectBuilder
.buildWithDependencies(mavenProject
,
260 localRepository
, profileManager
, transferListener
);
263 public MavenProject
readProjectWithDependencies(File mavenProject
)
264 throws ProjectBuildingException
, ArtifactResolutionException
,
265 ArtifactNotFoundException
{
266 return mavenProjectBuilder
.buildWithDependencies(mavenProject
,
267 localRepository
, profileManager
);
270 public List
collectProjects(File basedir
, String
[] includes
,
271 String
[] excludes
) throws MojoExecutionException
{
272 List projects
= new ArrayList();
274 List poms
= getPomFiles(basedir
, includes
, excludes
);
276 for (Iterator i
= poms
.iterator(); i
.hasNext();) {
277 File pom
= (File
) i
.next();
280 MavenProject p
= readProject(pom
);
284 } catch (ProjectBuildingException e
) {
285 throw new MojoExecutionException("Error loading " + pom
, e
);
292 // ----------------------------------------------------------------------
294 // ----------------------------------------------------------------------
296 public Artifact
createArtifact(String groupId
, String artifactId
,
297 String version
, String scope
, String type
) {
298 return artifactFactory
.createArtifact(groupId
, artifactId
, version
,
302 public Artifact
createArtifactWithClassifier(String groupId
,
303 String artifactId
, String version
, String type
, String classifier
) {
304 return artifactFactory
.createArtifactWithClassifier(groupId
,
305 artifactId
, version
, type
, classifier
);
308 public void resolve(Artifact artifact
, List remoteRepositories
,
309 ArtifactRepository localRepository
)
310 throws ArtifactResolutionException
, ArtifactNotFoundException
{
311 artifactResolver
.resolve(artifact
, remoteRepositories
, localRepository
);
314 // ----------------------------------------------------------------------
316 // ----------------------------------------------------------------------
318 public List
getAvailablePlugins() {
319 List plugins
= new ArrayList();
321 plugins
.add(makeMockPlugin("org.apache.maven.plugins",
322 "maven-jar-plugin", "Maven Jar Plug-in"));
324 plugins
.add(makeMockPlugin("org.apache.maven.plugins",
325 "maven-compiler-plugin", "Maven Compiler Plug-in"));
330 public PluginDescriptor
getPluginDescriptor(
331 SummaryPluginDescriptor summaryPluginDescriptor
)
332 throws MavenEmbedderException
{
333 PluginDescriptor pluginDescriptor
;
336 InputStream is
= classLoader
.getResourceAsStream("/plugins/"
337 + summaryPluginDescriptor
.getArtifactId() + ".xml");
339 pluginDescriptor
= pluginDescriptorBuilder
340 .build(new InputStreamReader(is
));
341 } catch (PlexusConfigurationException e
) {
342 throw new MavenEmbedderException(
343 "Error retrieving plugin descriptor.", e
);
346 return pluginDescriptor
;
349 private SummaryPluginDescriptor
makeMockPlugin(String groupId
,
350 String artifactId
, String name
) {
351 return new SummaryPluginDescriptor(groupId
, artifactId
, name
);
354 // ----------------------------------------------------------------------
355 // Execution of phases/goals
356 // ----------------------------------------------------------------------
358 // TODO: should we allow the passing in of a settings object so that
359 // everything can be taken from the client env
360 // TODO: transfer listener
363 public void execute(MavenProject project
, List goals
,
364 EventMonitor eventMonitor
, TransferListener transferListener
,
365 Properties properties
, File executionRootDirectory
)
366 throws CycleDetectedException
, LifecycleExecutionException
,
367 BuildFailureException
, DuplicateProjectException
{
368 execute(Collections
.singletonList(project
), goals
, eventMonitor
,
369 transferListener
, properties
, executionRootDirectory
);
372 public void execute(List projects
, List goals
, EventMonitor eventMonitor
,
373 TransferListener transferListener
, Properties properties
,
374 File executionRootDirectory
) throws CycleDetectedException
,
375 LifecycleExecutionException
, BuildFailureException
,
376 DuplicateProjectException
{
377 ReactorManager rm
= new ReactorManager(projects
);
379 EventDispatcher eventDispatcher
= new DefaultEventDispatcher();
381 eventDispatcher
.addEventMonitor(eventMonitor
);
383 // If this option is set the exception seems to be hidden ...
385 // rm.setFailureBehavior( ReactorManager.FAIL_AT_END );
387 rm
.setFailureBehavior(ReactorManager
.FAIL_FAST
);
389 MavenSession session
= new MavenSession(embedder
.getContainer(),
390 settings
, localRepository
, eventDispatcher
, rm
, goals
,
391 executionRootDirectory
.getAbsolutePath(), properties
,
394 session
.setUsingPOMsFromFilesystem(true);
396 if (transferListener
!= null) {
397 wagonManager
.setDownloadMonitor(transferListener
);
400 // ----------------------------------------------------------------------
401 // Maven should not be using system properties internally but because
402 // it does for now I'll just take properties that are handed to me
403 // and set them so that the plugin expression evaluator will work
405 // ----------------------------------------------------------------------
407 if (properties
!= null) {
408 for (Iterator i
= properties
.keySet().iterator(); i
.hasNext();) {
409 String key
= (String
) i
.next();
411 String value
= properties
.getProperty(key
);
413 System
.setProperty(key
, value
);
417 lifecycleExecutor
.execute(session
, rm
, session
.getEventDispatcher());
420 // ----------------------------------------------------------------------
421 // Lifecycle information
422 // ----------------------------------------------------------------------
424 public List
getLifecyclePhases() throws MavenEmbedderException
{
425 List phases
= new ArrayList();
427 ComponentDescriptor descriptor
= embedder
.getContainer()
428 .getComponentDescriptor(LifecycleExecutor
.ROLE
);
430 PlexusConfiguration configuration
= descriptor
.getConfiguration();
432 PlexusConfiguration
[] phasesConfigurations
= configuration
.getChild(
433 "lifecycles").getChild(0).getChild("phases").getChildren(
437 for (int i
= 0; i
< phasesConfigurations
.length
; i
++) {
438 phases
.add(phasesConfigurations
[i
].getValue());
440 } catch (PlexusConfigurationException e
) {
441 throw new MavenEmbedderException(
442 "Cannot retrieve default lifecycle phasesConfigurations.",
449 // ----------------------------------------------------------------------
451 // ----------------------------------------------------------------------
453 // ----------------------------------------------------------------------
455 // ----------------------------------------------------------------------
457 public static final String DEFAULT_LOCAL_REPO_ID
= "local";
459 public static final String DEFAULT_LAYOUT_ID
= "default";
461 public ArtifactRepository
createLocalRepository(File localRepository
)
462 throws ComponentLookupException
{
463 return createLocalRepository(localRepository
.getAbsolutePath(),
464 DEFAULT_LOCAL_REPO_ID
);
467 public ArtifactRepository
createLocalRepository(Settings settings
)
468 throws ComponentLookupException
{
469 return createLocalRepository(settings
.getLocalRepository(),
470 DEFAULT_LOCAL_REPO_ID
);
473 public ArtifactRepository
createLocalRepository(String url
,
474 String repositoryId
) throws ComponentLookupException
{
475 if (!url
.startsWith("file:")) {
476 url
= "file://" + url
;
479 return createRepository(url
, repositoryId
);
482 public ArtifactRepository
createRepository(String url
, String repositoryId
)
483 throws ComponentLookupException
{
484 // snapshots vs releases
485 // offline = to turning the update policy off
487 // TODO: we'll need to allow finer grained creation of repositories but
488 // this will do for now
490 String updatePolicyFlag
= ArtifactRepositoryPolicy
.UPDATE_POLICY_ALWAYS
;
492 String checksumPolicyFlag
= ArtifactRepositoryPolicy
.CHECKSUM_POLICY_WARN
;
494 ArtifactRepositoryPolicy snapshotsPolicy
= new ArtifactRepositoryPolicy(
495 true, updatePolicyFlag
, checksumPolicyFlag
);
497 ArtifactRepositoryPolicy releasesPolicy
= new ArtifactRepositoryPolicy(
498 true, updatePolicyFlag
, checksumPolicyFlag
);
500 return artifactRepositoryFactory
.createArtifactRepository(repositoryId
,
501 url
, defaultArtifactRepositoryLayout
, snapshotsPolicy
,
505 // ----------------------------------------------------------------------
506 // Internal utility code
507 // ----------------------------------------------------------------------
509 private RuntimeInfo
createRuntimeInfo(Settings settings
) {
510 RuntimeInfo runtimeInfo
= new RuntimeInfo(settings
);
512 runtimeInfo
.setPluginUpdateOverride(Boolean
.FALSE
);
517 private List
getPomFiles(File basedir
, String
[] includes
, String
[] excludes
) {
518 DirectoryScanner scanner
= new DirectoryScanner();
520 scanner
.setBasedir(basedir
);
522 scanner
.setIncludes(includes
);
524 scanner
.setExcludes(excludes
);
528 List poms
= new ArrayList();
530 for (int i
= 0; i
< scanner
.getIncludedFiles().length
; i
++) {
531 poms
.add(new File(basedir
, scanner
.getIncludedFiles()[i
]));
537 // ----------------------------------------------------------------------
539 // ----------------------------------------------------------------------
541 public void start() throws MavenEmbedderException
{
542 detectUserInstallation();
544 // ----------------------------------------------------------------------
545 // Set the maven.home system property which is need by components like
546 // the plugin registry builder.
547 // ----------------------------------------------------------------------
549 if (classLoader
== null) {
550 throw new IllegalStateException(
551 "A classloader must be specified using setClassLoader(ClassLoader).");
554 embedder
= new Embedder();
556 if (logger
!= null) {
557 embedder
.setLoggerManager(new MavenEmbedderLoggerManager(
558 new PlexusLoggerAdapter(logger
)));
562 ClassWorld classWorld
= new ClassWorld();
564 classWorld
.newRealm("plexus.core", classLoader
);
566 embedder
.start(classWorld
);
568 // ----------------------------------------------------------------------
569 // Lookup each of the components we need to provide the desired
571 // ----------------------------------------------------------------------
573 modelReader
= new MavenXpp3Reader();
575 modelWriter
= new MavenXpp3Writer();
577 pluginDescriptorBuilder
= new PluginDescriptorBuilder();
579 profileManager
= new DefaultProfileManager(embedder
.getContainer());
581 mavenProjectBuilder
= (MavenProjectBuilder
) embedder
582 .lookup(MavenProjectBuilder
.ROLE
);
584 // ----------------------------------------------------------------------
585 // Artifact related components
586 // ----------------------------------------------------------------------
588 artifactRepositoryFactory
= (ArtifactRepositoryFactory
) embedder
589 .lookup(ArtifactRepositoryFactory
.ROLE
);
591 artifactFactory
= (ArtifactFactory
) embedder
592 .lookup(ArtifactFactory
.ROLE
);
594 artifactResolver
= (ArtifactResolver
) embedder
595 .lookup(ArtifactResolver
.ROLE
);
597 defaultArtifactRepositoryLayout
= (ArtifactRepositoryLayout
) embedder
598 .lookup(ArtifactRepositoryLayout
.ROLE
, DEFAULT_LAYOUT_ID
);
600 lifecycleExecutor
= (LifecycleExecutor
) embedder
601 .lookup(LifecycleExecutor
.ROLE
);
603 wagonManager
= (WagonManager
) embedder
.lookup(WagonManager
.ROLE
);
605 createMavenSettings();
607 profileManager
.loadSettingsProfiles(settings
);
609 localRepository
= createLocalRepository(settings
);
610 } catch (PlexusContainerException e
) {
611 throw new MavenEmbedderException("Cannot start Plexus embedder.", e
);
612 } catch (DuplicateRealmException e
) {
613 throw new MavenEmbedderException(
614 "Cannot create Classworld realm for the embedder.", e
);
615 } catch (ComponentLookupException e
) {
616 throw new MavenEmbedderException(
617 "Cannot lookup required component.", e
);
621 // ----------------------------------------------------------------------
623 // ----------------------------------------------------------------------
625 private void detectUserInstallation() {
626 if (new File(userHome
, ".m2").exists()) {
627 alignWithUserInstallation
= true;
632 * Create the Settings that will be used with the embedder. If we are
633 * aligning with the user installation then we lookup the standard settings
634 * builder and use that to create our settings. Otherwise we constructs a
635 * settings object and populate the information ourselves.
637 * @throws MavenEmbedderException
638 * @throws ComponentLookupException
640 private void createMavenSettings() throws MavenEmbedderException
,
641 ComponentLookupException
{
642 if (alignWithUserInstallation
) {
643 // ----------------------------------------------------------------------
644 // We will use the standard method for creating the settings. This
645 // method reproduces the method of building the settings from the
647 // mode of operation.
648 // ----------------------------------------------------------------------
650 settingsBuilder
= (MavenSettingsBuilder
) embedder
651 .lookup(MavenSettingsBuilder
.ROLE
);
654 settings
= settingsBuilder
.buildSettings();
655 } catch (IOException e
) {
656 throw new MavenEmbedderException("Error creating settings.", e
);
657 } catch (XmlPullParserException e
) {
658 throw new MavenEmbedderException("Error creating settings.", e
);
661 if (localRepository
== null) {
662 throw new IllegalArgumentException(
663 "When not aligning with a user install you must specify a local repository location using the setLocalRepositoryDirectory( File ) method.");
666 settings
= new Settings();
668 settings
.setLocalRepository(localRepositoryDirectory
671 settings
.setRuntimeInfo(createRuntimeInfo(settings
));
673 settings
.setOffline(offline
);
675 settings
.setInteractiveMode(interactiveMode
);
679 // ----------------------------------------------------------------------
681 // ----------------------------------------------------------------------
683 public void stop() throws MavenEmbedderException
{
685 embedder
.release(mavenProjectBuilder
);
687 embedder
.release(artifactRepositoryFactory
);
689 embedder
.release(settingsBuilder
);
691 embedder
.release(lifecycleExecutor
);
692 } catch (ComponentLifecycleException e
) {
693 throw new MavenEmbedderException("Cannot stop the embedder.", e
);
697 public Embedder
getEmbedder() {