14

Let's say I have a project that uses a dependency that can be found in the Maven repository. However, lets also say that the jar file that will be downloaded is NOT in a format that is suitable for my project (e.g. if my maven project is an Android project and the jar has been compiled in a way the dex tool does not like). What I want to do instead is to downloaded the source version of that dependency. Once I add java-source, however, the classes are not accessible anymore from my own source code. I would like that maven downloads the source jar and compiles the java files inside it and places the compiled class files in the classpath. Is that possible?

My only alternative is to create a new project containing that library myself, but that's cumbersome.

David Arenburg
  • 91,361
  • 17
  • 137
  • 196
MShekow
  • 1,526
  • 2
  • 14
  • 28

2 Answers2

12

You could do the following:

  1. Use maven dependency plugin's unpack goal and place the contents of the dependency into a folder
  2. Use build-helper-maven-plugin's add-source goal to add this folder as a source folder

Here is some code snippet...

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>2.2</version>
  <executions>
    <execution>
      <id>unpack</id>
      <phase>process-sources</phase>
      <goals>
        <goal>unpack</goal>
      </goals>
      <configuration>
        <artifactItems>
          <artifactItem>
            <groupId>my.group</groupId>
            <artifactId>my.artifact</artifactId>
            <version>my.artifact.version</version>
            <classifier>sources</classifier>
            <overWrite>false</overWrite>
            <outputDirectory>${project.build.directory}/my.artifact</outputDirectory>
          </artifactItem>
        </artifactItems>
      </configuration>
    </execution>
  </executions>
</plugin>
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>build-helper-maven-plugin</artifactId>
  <version>1.5</version>
  <executions>
    <execution>
      <id>add-source</id>
      <phase>generate-sources</phase>
      <goals>
        <goal>add-source</goal>
      </goals>
      <configuration>
        <sources>
          <source>${project.build.directory}/my.artifact.source</source>
        </sources>
      </configuration>
    </execution>
  </executions>
</plugin>
Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
Raghuram
  • 51,854
  • 11
  • 110
  • 122
  • In general this already looks like a viable approach to me. However, when I tried it, the unpacked sources wouldn't compile, because this library that I am unpacking needs other dependencies, and they were not found during compilation :( – MShekow Sep 21 '11 at 14:20
  • This helped me for a simple case where I have a shared artifact with various sources generated (Java/C#/CPP). It was unclear until I ran it if you need to add the unpacked items to the dependency list - with artifactItem you don't. – Greg Domjan Aug 21 '12 at 13:26
  • Build Helper plugin is now at [https://www.mojohaus.org/build-helper-maven-plugin/](https://www.mojohaus.org/build-helper-maven-plugin/). – watery Nov 08 '18 at 08:34
0

Downloading the source packages using Maven is easy:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.16</version>
    <classifier>sources</classifier>
</dependency>

How to configure Maven to expand this dependency and then compile it's contents is beyond me....

Have you considered an ANT solution? The ivy plug-in provides it with Maven-like abilities and the groovy plug-in can be used to script your special build logic:

build.xml

Ivy uses "configurations" (similar to Maven scopes) to group dependencies.

In this example the "sources" configuration holds the downloaded source packages. These are placed into a referenced fileset, which can be processed sequentially by the groovy task.

Each downloaded source jar is unzipped into the "build/src" directory:

<project name="demo" default="unzip-sources" xmlns:ivy="antlib:org.apache.ivy.ant">

    <property name="build.dir" location="build"/>
    <property name="src.dir"   location="${build.dir}/src"/>

    <target name="resolve">
        <ivy:resolve/>
        <ivy:cachepath pathid="build.path" conf="build"/>
        <ivy:cachefileset setid="sourcezips" conf="sources"/>
    </target>

    <target name="unzip-sources" depends="resolve">
        <taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>

        <groovy>
        project.references.sourcezips.each {
            ant.unzip(src: it, dest: properties["src.dir"])
        }
        </groovy>
    </target>

    <target name="clean">
        <delete dir="${build.dir}"/>
    </target>

</project>

ivy.xml

Each source package dependency uses the "sources" configuration. This maps directly to the "sources" scope of the Maven module.

<ivy-module version="2.0">
    <info organisation="org.myspotontheweb" module="demo"/>
    <configurations>
        <conf name="build" description="ANT tasks"/>
        <conf name="sources" description="Source packages"/>
    </configurations>
    <dependencies>
        <!-- Build dependencies -->
        <dependency org="org.codehaus.groovy" name="groovy-all" rev="1.8.2" conf="build->default"/>

        <!-- Source dependencies -->
        <dependency org="log4j" name="log4j" rev="1.2.16" conf="sources"/>
        <dependency org="commons-lang" name="commons-lang" rev="2.6" conf="sources"/>
    </dependencies>
</ivy-module>
Betlista
  • 10,327
  • 13
  • 69
  • 110
Mark O'Connor
  • 76,015
  • 10
  • 139
  • 185
  • Hi. I guess this solution looks a bit too complex to me. I wouldn't like to go via Ant to solve this problem. Thanks anyways! :) – MShekow Sep 21 '11 at 14:19