Package management on the JDK since the introduction of Maven and Gradle is a goodness that many other dev platforms still can’t grasp. I’m thinking of you, pip+virtualenv hacky weirdness :)
Recently as work I was tasked with the generic task of auditing the project code for possible Open Source license violations. At first this raised some eyebrows among us, as one thing that I rarely look at though is what license the library is released under. Also, nowadays we use these very rapid and easy to use frameworks like Spring Boot, where more and more dependencies are pulled without us end-users really controlling them.
Unfortunately, for a library user, a license is VERY important. It is also important for the code that you write, but the license of the dependency could even affect the licensing scheme of your own code. I’ll explain better in a moment.
The license spectrum is wide
I don’t want to make a blog post about licenses, I am not an expert. Keeping it simple: beside commercial "Closed Source" code (e.g. the Microsoft Windows code) the Open Source code can have a varying degree of copyleft. There are permissive licenses, like MIT, Apache 2.0, and BSD, which allow any fair use of their code (linked or embedded). There are less permissive licenses like the LGPL and the GPL with classpath exception that allow the code to be linked by any other code (so in Java terms, you can have dependencies with those licenses), but not embedded (or, more likely copy-pasted). Finally there are licenses like the GPL and the AGPL which are considered strong copyleft and viral: if your code links a library with GPL code, then your code too should be licensed as GPL. This of course is acceptable if you are developing a open-source project, but it may be not if you are developing a commercial application.
If we are talking about commercial applications, it is not even black and white, it really depends also on many things like: is your application a service, or a product? Is your application residing on the customer premises? is your application charged on usage or as flat? and so on and on.
As you can understand the terrain here is very flaky, and many commercial companies try to stay away from GPL and similar strong copyleft code. Moreso, the commercial code embedding or linking open source code is required to attach the Licenses of the dependencies with the delivery software as well. So, you may end up being requested to audit code like it happened to me.
Maven license plugin
You would think that managing and auditing licenses in Java would be easy. The natural solution would be to use Maven during the CI builds. And this means, we are looking for a Maven plugin just like Jacoco, CheckStyle or similar.
I found out, however, that it is not that easy :). Yes, you can produce a mvn site
and retrieve all dependencies and transitive dependencies on your project, including the licenses, and audit that potentially huge list. You can actually easily use the official CodeHaus maven-license-plugin for this (pretty fast and complete). This is after all the solution that we adopted at my workplace.
Introducing licensescan-maven-plugin
However, it would be really more useful to have an automated way to alert me if my project was using dependency artifacts with permissive or non permissive licenses and potentially fail the build. Surprisingly, the web was not very generous and I only found out about sparse experiments like https://github.com/mrice/license-check and https://www.ayoy.se/en/blog/2017/10-27-maven-license-plugin/. I could not make the first work, as the code seems unmaintained.
So i said, let’s take two pidgeons with one stone: I will produce the plugin that I want and in the meantime I will also learn how to produce a Maven plugin myself.
Again, turns out that the Maven documentation to write a plugin is not that easy, and I bounced a lot between the official maven.org
documentation and StackOverflow.
In the end, I was able to hack something in the last two weeks on my own, that I think does the work. It is very basic, but has parametric configuration and I believe it is easy to use. You just need to follow the directions on the GitHub https://github.com/carlomorelli/licensescan-maven-plugin Readme file. Here is a summary:
1) Put the plugin configuration in your pom.xml
:
<plugin>
<groupId>com.github.carlomorelli</groupId>
<artifactId>licensescan-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<printLicenses>true</printLicenses>
<blacklistedLicenses>
<license>GNU Lesser General Public License</license>
<license>GNU General Public License, v2.0</license>
</blacklistedLicenses>
<failBuildOnBlacklisted>true</failBuildOnBlacklisted>
</configuration>
</plugin>
2) Put the JitPack repository in your pluginRepository management block — this is required as the plugin is not published on the official Maven Central yet:
<pluginRepositories>
<pluginRepository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</pluginRepository>
</pluginRepositories>
Here is the outcome of mvn clean compile
for a simple Spring Boot project I was using to test the plugin:
[warn] BLACKLIST
[warn] -----------------------
[warn] Found 5 violations for license 'GNU Lesser General Public License':
[warn] - ch.qos.logback:logback-classic:1.1.11:compile
[warn] - ch.qos.logback:logback-core:1.1.11:compile
[warn] - org.hibernate:hibernate-core:5.0.12.Final:compile
[warn] - org.hibernate.common:hibernate-commons-annotations:5.0.1.Final:compile
[warn] - org.hibernate:hibernate-entitymanager:5.0.12.Final:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.753 s
[INFO] Finished at: 2018-04-01T17:02:01+02:00
[INFO] Final Memory: 37M/430M
[INFO] ------------------------------------------------------------------------
Few warnings
Hacking Maven plugins is a strange thing. It feels OK, there is an automatic IoC managed by the Maven toolkit so passing parameters is not very difficult. But the documentation is a little bit lacky, so most of the times you are just guessing. Again, god bless StackOverflow.
Also I coded the plugin on Java 1.5 standard. I am not sure if forcing 1.8 would have made things not working on older projects. What I am sure is that once you learn Java 8 streams, it really sucks to program with the old for loop style. If you ever take a look at the code, please be gentle with the Mojo code :)
Tests? Not yet unfortunately. Maybe in future step releases as I find a good way to test the code. Right now I am experimenting with the official maven-plugin-test-harness, which is something very ancient (I mean, it is based on JUnit 3.x … ), but allows to hijack the dependency injection for testing.
And by all means, contributions are welcome.