You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@maven.apache.org by gevaudan <ca...@gmail.com> on 2012/05/05 21:07:04 UTC

Inject maven dependencies programatically through plug-in

Is there a way to inject dependencies programatically in a maven plugin as if
they were declared in the POM itself?  I only found one post discussing this
and it did not help.

Why do I want to do this?

Assume I have a fruit pom which imports a bom-pom which declares version
numbers for fruits, vegetables and other artifacts.  Example:

fruit pom:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com</groupId>
      <artifactId>foods</artifactId>
      <version>10.0-SNAPSHOT</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependencies>
  <dependency>
    <groupid>com</groupId>
    <artifactId>apple</artifactId>
    <classifier>fruit</classifier>
  </dependency>
  <dependency>
    <groupid>com</groupId>
    <artifactId>orange</artifactId>
    <classifier>fruit</classifier>
  </dependency>
</dependencies>

food pom:

<dependencies>
  <dependency>
    <groupid>com</groupId>
    <artifactId>apple</artifactId>
    <version>1.0-SNAPSHOT</version>
    <classifier>fruit</classifier>
  </dependency>
  <dependency>
    <groupid>com</groupId>
    <artifactId>orange</artifactId>
    <version>2.0-SNAPSHOT</version>
    <classifier>fruit</classifier>
  </dependency>
  <dependency>
    <groupid>com</groupId>
    <artifactId>artichoke</artifactId>
    <version>3.0-SNAPSHOT</version>
    <classifier>vegetable</classifier>
  </dependency>
  <dependency>
    <groupid>com</groupId>
    <artifactId>asparagus</artifactId>
    <version>4.0-SNAPSHOT</version>
    <classifier>vegetable</classifier>
  </dependency>  
</dependencies>

The fruit pom only needs to inject dependencies that have a classifier of
type fruit.  The goal is to do this programatically so user's do not have to
edit multiple pom files when adding a new dependency.

The real use case is more complicated than this but I hope the above example
gets at the heart of the question.

I understand I can use the maven model api to read and write poms but that
seems to require an intermediate step and perhaps a second instance of maven
to be spawned in order to consume the intermediate pom.  Ideally I would
like to avoid this step and inject dependencies programatically into the pom
which declares the plugin-in itself.  Is this even possible or is the pom
immutable?

--
View this message in context: http://maven.40175.n5.nabble.com/Inject-maven-dependencies-programatically-through-plug-in-tp5688342.html
Sent from the Maven - Users mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


Re: Inject maven dependencies programatically through plug-in

Posted by Jörg Schaible <Jo...@scalaris.com>.
Hi,

I realize now that your use case is somewhat different. The code snippet 
below relies on the fact that you have already declares an artifact with 
same G:A:V and you like to add an artifact with a different classifier. The 
depMgmgt stuff is already resolved at that time. It does *not* cover adding 
a dependency with a new G:A:V. As Wayne said in the reply to your other 
mail, that would be a bad idea, because Maven reactor could no longer 
calculate the correct build order.

- Jörg

Jörg Schaible wrote:

> Hi
> 
> gevaudan wrote:
> 
>> Is there a way to inject dependencies programatically in a maven plugin
>> as if
>> they were declared in the POM itself?  I only found one post discussing
>> this and it did not help.
>> 
>> Why do I want to do this?
>> 
>> Assume I have a fruit pom which imports a bom-pom which declares version
>> numbers for fruits, vegetables and other artifacts.  Example:
>> 
>> fruit pom:
>> 
>> <dependencyManagement>
>>   <dependencies>
>>     <dependency>
>>       <groupId>com</groupId>
>>       <artifactId>foods</artifactId>
>>       <version>10.0-SNAPSHOT</version>
>>       <type>pom</type>
>>       <scope>import</scope>
>>     </dependency>
>>   </dependencies>
>> </dependencyManagement>
>> <dependencies>
>>   <dependency>
>>     <groupid>com</groupId>
>>     <artifactId>apple</artifactId>
>>     <classifier>fruit</classifier>
>>   </dependency>
>>   <dependency>
>>     <groupid>com</groupId>
>>     <artifactId>orange</artifactId>
>>     <classifier>fruit</classifier>
>>   </dependency>
>> </dependencies>
>> 
>> food pom:
>> 
>> <dependencies>
>>   <dependency>
>>     <groupid>com</groupId>
>>     <artifactId>apple</artifactId>
>>     <version>1.0-SNAPSHOT</version>
>>     <classifier>fruit</classifier>
>>   </dependency>
>>   <dependency>
>>     <groupid>com</groupId>
>>     <artifactId>orange</artifactId>
>>     <version>2.0-SNAPSHOT</version>
>>     <classifier>fruit</classifier>
>>   </dependency>
>>   <dependency>
>>     <groupid>com</groupId>
>>     <artifactId>artichoke</artifactId>
>>     <version>3.0-SNAPSHOT</version>
>>     <classifier>vegetable</classifier>
>>   </dependency>
>>   <dependency>
>>     <groupid>com</groupId>
>>     <artifactId>asparagus</artifactId>
>>     <version>4.0-SNAPSHOT</version>
>>     <classifier>vegetable</classifier>
>>   </dependency>
>> </dependencies>
>> 
>> The fruit pom only needs to inject dependencies that have a classifier of
>> type fruit.  The goal is to do this programatically so user's do not have
>> to edit multiple pom files when adding a new dependency.
>> 
>> The real use case is more complicated than this but I hope the above
>> example gets at the heart of the question.
>> 
>> I understand I can use the maven model api to read and write poms but
>> that seems to require an intermediate step and perhaps a second instance
>> of maven
>> to be spawned in order to consume the intermediate pom.  Ideally I would
>> like to avoid this step and inject dependencies programatically into the
>> pom
>> which declares the plugin-in itself.  Is this even possible or is the pom
>> immutable?
> 
> Look at the following code snippet, it should give you the idea:
> 
> ================== %< =================
> /**
>  * The maven project.
>  *
>  * @parameter   expression="${project}"
>  * @required
>  * @readonly
>  * @description "the maven project to use"
>  */
> private MavenProject project;
> 
> /**
>  * Used to look up Artifacts in the remote repository.
>  *
>  * @component role="org.apache.maven.artifact.factory.ArtifactFactory"
>  * @required
>  * @readonly
>  */
> protected ArtifactFactory factory;
> 
> /**
>  * Used to look up Artifacts in the remote repository.
>  *
>  * @component role="org.apache.maven.artifact.resolver.ArtifactResolver"
>  * @required
>  * @readonly
>  */
> protected ArtifactResolver resolver;
> 
> /**
>  * Location of the local repository.
>  *
>  * @parameter expression="${localRepository}"
>  * @readonly
>  * @required
>  */
> protected ArtifactRepository local;
> 
> /**
>  * List of Remote Repositories used by the resolver
>  *
>  * @parameter expression="${project.remoteArtifactRepositories}"
>  * @readonly
>  * @required
>  */
> protected List<?> remoteRepos;
> 
> 
> public void execute() throws MojoExecutionException, MojoFailureException
> {
>   List<Artifact> vegetables = new ArrayList<Artifact>();
>   @SuppressWarnings("unchecked")
>   final Set<Artifact> dependencies = project.getArtifacts();
>   if (dependencies != null && !dependencies.isEmpty()) {
>     for (final Artifact artifact : dependencies) {
>       if (artifact.getClassifier().equals("vegetable") {
>         vegetables.add(artifact);
>         break;
>       }
>     }
>   }
>   if (vegetables.isEmpty()) {
>     throw new MojoFailureException("There is no vegetable dependency");
>   }
>   for(final Artifact vegetable : vegetables) {
>     final File vegetable = serviceEjb.getFile();
>     final Artifact descriptors =
>       factory.createArtifactWithClassifier(
>         vegetable.getGroupId(), vegetable.getArtifactId(),
>         vegetable.getVersion(), "jar", "fruit");
>     descriptors.setScope(Artifact.SCOPE_PROVIDED);
>     final String descriptorFileName =
>       vegetable.getName().substring(0, vegetable.getName().length()
>         - vegetable.getArtifactHandler().getExtension().length() - 1)
>       + "-fruit." + descriptors.getArtifactHandler().getExtension();
>     final File descriptorsFile = new File(vegetable.getParentFile(),
>       descriptorFileName);
>     if (descriptorsFile.isFile()) { // file in current build ?
>       descriptors.setFile(descriptorsFile);
>       descriptors.setResolved(true);
>     } else {
>       try {
>         resolver.resolve(descriptors, remoteRepos, local);
>       } catch (final ArtifactResolutionException e) {
>         throw new MojoExecutionException("Unable to resolve artifact.",
>         e);
>       } catch (final ArtifactNotFoundException e) {
>         throw new MojoExecutionException("Unable to find artifact.", e);
>       }
>     }
> 
>     final File file = descriptors.getFile();
>     if (!file.isFile()) {
>       throw new MojoFailureException("Fruit is missing: "
>         + file.getAbsolutePath());
>     }
>     // do what you have to do
>   }
> }
> ================== %< =================
> 
> Hope this helps,
> Jörg



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


Re: Inject maven dependencies programatically through plug-in

Posted by Jörg Schaible <Jo...@scalaris.com>.
Hi

gevaudan wrote:

> Is there a way to inject dependencies programatically in a maven plugin as
> if
> they were declared in the POM itself?  I only found one post discussing
> this and it did not help.
> 
> Why do I want to do this?
> 
> Assume I have a fruit pom which imports a bom-pom which declares version
> numbers for fruits, vegetables and other artifacts.  Example:
> 
> fruit pom:
> 
> <dependencyManagement>
>   <dependencies>
>     <dependency>
>       <groupId>com</groupId>
>       <artifactId>foods</artifactId>
>       <version>10.0-SNAPSHOT</version>
>       <type>pom</type>
>       <scope>import</scope>
>     </dependency>
>   </dependencies>
> </dependencyManagement>
> <dependencies>
>   <dependency>
>     <groupid>com</groupId>
>     <artifactId>apple</artifactId>
>     <classifier>fruit</classifier>
>   </dependency>
>   <dependency>
>     <groupid>com</groupId>
>     <artifactId>orange</artifactId>
>     <classifier>fruit</classifier>
>   </dependency>
> </dependencies>
> 
> food pom:
> 
> <dependencies>
>   <dependency>
>     <groupid>com</groupId>
>     <artifactId>apple</artifactId>
>     <version>1.0-SNAPSHOT</version>
>     <classifier>fruit</classifier>
>   </dependency>
>   <dependency>
>     <groupid>com</groupId>
>     <artifactId>orange</artifactId>
>     <version>2.0-SNAPSHOT</version>
>     <classifier>fruit</classifier>
>   </dependency>
>   <dependency>
>     <groupid>com</groupId>
>     <artifactId>artichoke</artifactId>
>     <version>3.0-SNAPSHOT</version>
>     <classifier>vegetable</classifier>
>   </dependency>
>   <dependency>
>     <groupid>com</groupId>
>     <artifactId>asparagus</artifactId>
>     <version>4.0-SNAPSHOT</version>
>     <classifier>vegetable</classifier>
>   </dependency>
> </dependencies>
> 
> The fruit pom only needs to inject dependencies that have a classifier of
> type fruit.  The goal is to do this programatically so user's do not have
> to edit multiple pom files when adding a new dependency.
> 
> The real use case is more complicated than this but I hope the above
> example gets at the heart of the question.
> 
> I understand I can use the maven model api to read and write poms but that
> seems to require an intermediate step and perhaps a second instance of
> maven
> to be spawned in order to consume the intermediate pom.  Ideally I would
> like to avoid this step and inject dependencies programatically into the
> pom
> which declares the plugin-in itself.  Is this even possible or is the pom
> immutable?

Look at the following code snippet, it should give you the idea:

================== %< =================
/**
 * The maven project.
 *
 * @parameter   expression="${project}"
 * @required
 * @readonly
 * @description "the maven project to use"
 */
private MavenProject project;

/**
 * Used to look up Artifacts in the remote repository.
 *
 * @component role="org.apache.maven.artifact.factory.ArtifactFactory"
 * @required
 * @readonly
 */
protected ArtifactFactory factory;

/**
 * Used to look up Artifacts in the remote repository.
 *
 * @component role="org.apache.maven.artifact.resolver.ArtifactResolver"
 * @required
 * @readonly
 */
protected ArtifactResolver resolver;

/**
 * Location of the local repository.
 *
 * @parameter expression="${localRepository}"
 * @readonly
 * @required
 */
protected ArtifactRepository local;

/**
 * List of Remote Repositories used by the resolver
 *
 * @parameter expression="${project.remoteArtifactRepositories}"
 * @readonly
 * @required
 */
protected List<?> remoteRepos;


public void execute() throws MojoExecutionException, MojoFailureException
{
  List<Artifact> vegetables = new ArrayList<Artifact>();
  @SuppressWarnings("unchecked")
  final Set<Artifact> dependencies = project.getArtifacts();
  if (dependencies != null && !dependencies.isEmpty()) {
    for (final Artifact artifact : dependencies) {
      if (artifact.getClassifier().equals("vegetable") {
        vegetables.add(artifact);
        break;
      }
    }
  }
  if (vegetables.isEmpty()) {
    throw new MojoFailureException("There is no vegetable dependency");
  }
  for(final Artifact vegetable : vegetables) {
    final File vegetable = serviceEjb.getFile();
    final Artifact descriptors = 
      factory.createArtifactWithClassifier(
        vegetable.getGroupId(), vegetable.getArtifactId(),
        vegetable.getVersion(), "jar", "fruit");
    descriptors.setScope(Artifact.SCOPE_PROVIDED);
    final String descriptorFileName = 
      vegetable.getName().substring(0, vegetable.getName().length()
        - vegetable.getArtifactHandler().getExtension().length() - 1)
      + "-fruit." + descriptors.getArtifactHandler().getExtension();
    final File descriptorsFile = new File(vegetable.getParentFile(),
      descriptorFileName);
    if (descriptorsFile.isFile()) { // file in current build ?
      descriptors.setFile(descriptorsFile);
      descriptors.setResolved(true);
    } else {
      try {
        resolver.resolve(descriptors, remoteRepos, local);
      } catch (final ArtifactResolutionException e) {
        throw new MojoExecutionException("Unable to resolve artifact.", e);
      } catch (final ArtifactNotFoundException e) {
        throw new MojoExecutionException("Unable to find artifact.", e);
      }
    }

    final File file = descriptors.getFile();
    if (!file.isFile()) {
      throw new MojoFailureException("Fruit is missing: "
        + file.getAbsolutePath());
    }
    // do what you have to do
  }
}
================== %< =================

Hope this helps,
Jörg


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org