- Built with Maven
- Source and runtime upped to Java 7
- Packaged as both zip archives and Windows setup program
- First attempt at visually repositioning a city if it goes out of view
Sunday, 21 April 2013
Worldclock 0.7, Worldclock Saver 0.8, Worldclock editor 1.0
Changes:
Labels:
Java7,
Worldclock
Sunday, 24 March 2013
Building Jigsaw on Windows
Building Jigsaw on Windows is the same as building OpenJDK8 except that the URL to use in step 13 to get the root source is http://hg.openjdk.java.net/jigsaw/jigsaw/
List the modules in the JDK system library:
Post build define a JIG enviroment variable to prefix your java command:hg clonehttp://hg.openjdk.java.net/jigsaw/jigsaw/
set JIG=C:\dev\jigsaw\build\windows-x86_64-normal-server-release\images\jdk-module-imageA few commands:
List the modules in the JDK system library:
%JIG%/bin/jmod listLaunch a modular java application:
%JIG%/bin/java -m jdk.jconsole
Sunday, 20 January 2013
Building Java 8 on Windows
This post is a step by step to build Java 8 using the new build infrastructure on Window (8 64bits). It combines instructions from Volker Simonis, Stanislav Kobylansky and from the OpenJDK8 Build ReadMe.
A different version of these steps initiated by Patrick Reinhart can be found on the Adopt OpenJDK website.
One more version with screenshots by Roberto Coelho.
Last updated: 2013-10-11: added the direct link to VC++2010 web installer in English (for some reason it isn't available from the download page from France)
A different version of these steps initiated by Patrick Reinhart can be found on the Adopt OpenJDK website.
One more version with screenshots by Roberto Coelho.
Last updated: 2013-10-11: added the direct link to VC++2010 web installer in English (for some reason it isn't available from the download page from France)
- Download Visual C++ 2010 Express (only C++ is needed, direct link), install it without optional products (ie without Silverlight or MS SQL 2008 Express SP1).
(it is only needed to build Freetype) - Download and install Windows SDK 7.1 (don't install the samples and .Net tools)
- Download and install Microsoft DirectX 9.0 SDK (the ReadMe says the version from summer 2004, however this does not seem to still be available from Microsoft, the version from June 2010 seems to be a working replacement)
- Download and install TortoiseHg (Mercurial client)
- Download and install Java 7 (if not already done)
- Download and install Cygwin in C:\cygwin64, select the following packages:
- [Archive] unzip
- [Archive] zip
- [Base] gawk
- [Devel] binutils
- [Devel] make
- [Interpreters] m4
- [Utils] cpio
- [Utils] files
- [System] procps
- Create a C:\dev\ directory
- Freetype
- Download the source
- Extract it to C:\dev\freetype-2.5.0.1
- Either
- Download prebuilt binaries from bintray and extract them so that the lib directory goes into C:\dev\freetype-2.5.0.1
or - Build it yourself
- Go to C:\dev\freetype-2.5.0.1\builds\win32\vc2010 and open freetype.sln
- Create a 64 bits configuration
- In the toolbar, click on the arrow by Win32, then on "Configuration Manager", then again click on Win32 below "Active solution platform", then on <New...>
- In the new dialog, call the new platform "x64" and copy its settings from Win32, click OK
- Back in the previous dialog select "Release Multithreaded" from "Active solution configuration" and Close
- Right click on the freetype project, then select Properties
- In the dialog adjust:
- "Output Directory" from ".\..\..\..\objs\win32\vc2010\" to ".\..\..\..\lib\"
- "Intermediate Directory" from ".\..\..\..\objs\release_mt\" to ".\..\..\..\objs\release_mt_64\"
- "Target Name" from "freetype2411MT" to "freetype"
- "Platform Toolset" from "v100" to "Windows7.1SDK"
- Ok to save
- Right click on the freetype project then Build or press <F7> to build
- Once built, return to the properties dialog
Change- "Configuration Type" from "Static library (.lib)" to "Dynamic Library (.dll)"
- Build again
- Download prebuilt binaries from bintray and extract them so that the lib directory goes into C:\dev\freetype-2.5.0.1
- Copy msvcr100.dll to its own directory C:\dev\vcrt from either C:\Windows\System32 or C:\Program Files\Java\jdk1.7.0_XX\bin (this because the build process seem to have difficulties copying the file properly from C:\Windows\System32, and the JDK bin directory is in a path with spaces)
- Adjust the PATH by appending ";C:\cygwin64\bin"
- Open Cygwin terminal (from link on the desktop)
- cd /cygdrive/c/dev
- Get the root source:
hg clone http://hg.openjdk.java.net/jdk8/jdk8 - Move to the new directory
cd /cygdrive/c/dev/jdk8
- Get the remainder of the source
./get_source.sh
- Force the permissions
chmod -R u+rwxs /cygdrive/c/dev/jdk8
(otherwise some files get access denied errors) - Run the auto-conf script
bash configure --with-freetype=/cygdrive/c/dev/freetype-2.5.0.1 --with-msvcr-dll=/cygdrive/c/dev/vcrt/msvcr100.dll
- Time for cooking
make
- Once done, open a new standard Windows console and navigate to
C:\dev\jdk8\build\windows-x86_64-normal-server-release\jdk
check that java runs:bin\java -version
or for something a bit more visual:bin\jconsole
- If needed make the images (ie the directory layouts that are created when installing a jdk/jre from the Oracle installers - or something pretty close to them)
make images
- enjoy!
- Go to the JDK directory
cd /cygdrive/c/dev/jdk8
- Get the sources updates
./get_source.sh
- Force the permissions
chmod -R u+rwxs /cygdrive/c/dev/jdk8
- Re-heat
make
or
make images
- If it fails, try
make clean
(it tends to fail in hotspot, in which case a
make clean-hotspot
is faster)
then re-heat - If it fails again, try to redo the configuration
make dist-clean
then re-heat
bash configure --with-freetype=/cygdrive/c/dev/freetype-2.5.0.1 --with-msvcr-dll=/cygdrive/c/dev/vcrt/msvcr100.dll
Sunday, 25 November 2012
Worldclock on Jigsaw and HK2
In the previous post I 'ported' HK2 to work on Jigsaw, in this post I adapt Worldclock to use it.
gedit ~/dev/worldclock-hk2/panel/src/main/java/lh.worldclock.panel/lh/worldclock/core/WorldClockBoard.java & )
Overwrite the existing pom and module info for the application:
Adjust WorldClockPanel:
replace constructor start with:
add import
remove the initialisation of pane
replace constructor start with:
add imports
replace class declaration
make the frame non static
make void showWindow() non static and change
to add the board
make private PopupMenu createPopup() non static
add the following new methods
Time to run:
Retrieving the existing code:
svn checkout https://svn.java.net/svn/worldclock-application~svn/tags/application6-jigsaw-maven ~/dev/worldclock-hk2
And the new pom and module-info:
svn checkout https://svn.kenai.com/svn/lh-playground~svn/jigsaw/worldclock-hk2 ~/dev/worldclock-hk2-downloads
Panel
Overwrite the existing pom and module info for the panel:cp ~/dev/worldclock-hk2-downloads/panel/pom.xml ~/dev/worldclock-hk2/panel/(update the libraryDirectory path for your set up / username, gedit ~/dev/worldclock-hk2/panel/pom.xml & )
cp ~/dev/worldclock-hk2-downloads/panel/src/main/java/lh.worldclock.panel/module-info.java ~/dev/worldclock-hk2/panel/src/main/java/lh.worldclock.panel/Add the sample HK2 dependency injection contract:
mkdir -p ~/dev/worldclock-hk2/panel/src/main/java/lh.worldclock.panel/lh/worldclock/hk2/
gedit ~/dev/worldclock-hk2/panel/src/main/java/lh.worldclock.panel/lh/worldclock/hk2/PanelProvider.java &then add the content
package lh.worldclock.hk2;Add the sample HK2 dependency injection service:
import lh.worldclock.core.WorldClockBoard;
import org.jvnet.hk2.annotations.Contract;
@Contract
public interface PanelProvider
{
WorldClockBoard getPanel();
}
gedit ~/dev/worldclock-hk2/panel/src/main/java/lh.worldclock.panel/lh/worldclock/hk2/PanelProviderImpl.java &then add the content
package lh.worldclock.hk2;build
import lh.worldclock.core.WorldClockBoard;
import org.jvnet.hk2.annotations.Service;
@Service
public class PanelProviderImpl implements PanelProvider
{
@Override
public WorldClockBoard getPanel()
{
return new WorldClockBoard();
}
}
cd ~/dev/worldclock-hk2/panel/(if the build fail due to invalid characters, edit the file and remove the comments
mvn -Dmaven.test.skip=true clean install
gedit ~/dev/worldclock-hk2/panel/src/main/java/lh.worldclock.panel/lh/worldclock/core/WorldClockBoard.java & )
Application
Overwrite the existing pom and module info for the application:
cp ~/dev/worldclock-hk2-downloads/application/pom.xml ~/dev/worldclock-hk2/application/(update the libraryDirectory path for your set up / username, gedit ~/dev/worldclock-hk2/application/pom.xml & )
cp ~/dev/worldclock-hk2-downloads/application/src/main/java/lh.worldclock.application/module-info.java ~/dev/worldclock-hk2/application/src/main/java/lh.worlclock.application/
Adjust WorldClockPanel:
gedit ~/dev/worldclock-hk2/application/src/main/java/lh.worlclock.application/lh/worldclock/WorldClockPanel.java &
replace constructor start with:
public WorldClockPanel(final WorldClockBoard board)Adjust WorldClockFrame:
{
// board = new WorldClockBoard();
this.board = board;
gedit ~/dev/worldclock-hk2/application/src/main/java/lh.worlclock.application/lh/worldclock/WorldClockFrame.java &
add import
import lh.worldclock.core.WorldClockBoard;
remove the initialisation of pane
WorldClockPanel pane;
replace constructor start with:
public WorldClockFrame(ImageIcon icon, final WorldClockBoard board)Adjust WorldClock
{
pane = new WorldClockPanel(board);
gedit ~/dev/worldclock-hk2/application/src/main/java/lh.worlclock.application/lh/worldclock/WorldClock.java &
add imports
import com.sun.enterprise.module.bootstrap.ModuleStartup;
import com.sun.enterprise.module.bootstrap.StartupContext;
import org.jvnet.hk2.annotations.Inject;
import org.jvnet.hk2.annotations.Service;
import lh.worldclock.core.WorldClockBoard;
replace class declaration
@Service
public class WorldClock implements ModuleStartup
make the frame non static
/*static*/ WorldClockFrame frame = null;add the injection
@Injectmake main method non static
WorldClockBoard board;
make void showWindow() non static and change
frame = new WorldClockFrame(icon, board);
to add the board
make private PopupMenu createPopup() non static
add the following new methods
public void setStartupContext(StartupContext context)build
{
}
public void start()
{
main(new String[]{});
}
public void stop()
{
}
cd ~/dev/worldclock-hk2/application/
mvn -Dmaven.test.skip=true clean install
Time to run:
cd ~/dev/hk2-jigsaw/jigsaw-adapter/
mvn lh.jigsaw:jigsaw-maven-plugin:run
Labels:
HK2,
Jigsaw,
Worldclock
HK2 and Jigsaw
In 2007, Jerôme Dochez presented HK2 as a module system loosely based on JSR277, I tend to see Jigsaw as the continuation of JSR277, so I wanted to see how HK2 could interface with Jigsaw.
Setting up the environement:
1. Build Jigsaw2. Build the Maven plugin for Jigsaw
3. Download and extract Maven 3 in ~/dev
4. Export the variables:
export M2_HOME=~/dev/apache-maven-3.0.4/give some extra room to Maven:
export MAVEN_HOME=~/dev/apache-maven-3.0.4/
export JAVA_HOME='/usr/lib/jvm/java-7-openjdk-i386'
export PATH=$JAVA_HOME/bin:$M2_HOME/bin:$PATH
export MAVEN_OPTS="-XX:PermSize=64M -XX:MaxPermSize=128M"
Get and build HK2:
svn checkout https://svn.java.net/svn/hk2~svn/tags/hk2-parent-1.6.32 ~/dev/hk2-1.6.32
cd ~/dev/hk2-1.6.32
mvn -DskipTests=true -Prelease-phase1 clean install
mvn -DskipTests=true clean install
Get the additions/replacements:
In order to reduce the amount of typing/copying some of the added/modified files are downloadable.svn checkout https://svn.kenai.com/svn/lh-playground~svn/jigsaw/hk2 ~/dev/hk2-jigsaw-downloads
Patch HK2:
HK2 1.6.32 still uses the APT to build, this is removed from Java8/Jigsaw, so some adjustments are needed. These replace APT API with JSR269 API.cd ~/dev/hk2-1.6.32/as a result of the patch some of the tests in HK2 are failing, so disabling them for now
patch -p0 < ~/dev/hk2-jigsaw-downloads/hk2-1.6.32-java7-maven-plugin.diff
gedit ~/dev/hk2-1.6.32/pom.xml &then comment line 307 (<module>auto-depends-tests</module>).
Build the patched version:
mvn -DskipTests=true clean install
Clean up no longer needed classes from the Maven plugin:
rm -f ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/CompositeAnnotationProcessorFactory.java
rm -f ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/AptInvoker.java
rm -f ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/AptCompiler.java
Adjust hk2-maven-plugin for Jigsaw:
Replace components.xml with a version that defines the packaging type to hk2-jmod rather than hk2-jar, and that also adds the Jigsaw extensions.cp ~/dev/hk2-jigsaw-downloads/hk2-1.6.32/hk2-maven-plugin/src/main/resources/META-INF/plexus/components.xml ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/resources/META-INF/plexus/components.xmlAdjust PackageMojo:
gedit ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/PackageMojo.java &replace line 109:
@parameter expression="${component.org.codehaus.plexus.archiver.Archiver#jar}"with
@component role="org.codehaus.plexus.archiver.Archiver" roleHint="jar"
Adjust RunMojo:
gedit ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/RunMojo.java &
set the goal to hk2-run on line 65 so that the default run is the Jigsaw run
Add the non compile parts from the Jigsaw Maven plugin and override the compile part:
cp -r ~/dev/jigsaw-maven-plugin/src/main/java/lh ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/Adjust AbstractCompilerMojo:
mv ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/lh/jigsaw/plugin/AbstractCompilerMojo.java ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/
mv ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/lh/jigsaw/plugin/CompilerMojo.java ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/
gedit ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/AbstractCompilerMojo.java &
replace the package
package lh.jigsaw.plugin;with
package com.sun.enterprise.module.maven;
Adjust CompilerMojo:
gedit ~/dev/hk2-1.6.32/hk2-maven-plugin/src/main/java/com/sun/enterprise/module/maven/CompilerMojo.java &
replace the package
package lh.jigsaw.plugin;with
package com.sun.enterprise.module.maven;
Adjust the pom:
gedit ~/dev/hk2-1.6.32/hk2-maven-plugin/pom.xml &Add to the build:
<plugins>Replace the auto-depends-plugin dependency with:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-javac</artifactId>
<version>1.8.1-jigsaw</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</plugin>
</plugins>
<dependency>Replace the plexus-compiler-javac dependency with:
<groupId>org.glassfish.hk2</groupId>
<artifactId>auto-depends-plugin</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>Build the modified plugin with Jigsaw:
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-javac</artifactId>
<version>1.8.1-jigsaw</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</exclusion>
</exclusions>
</dependency>
export JAVA_HOME=~/dev/jigsaw/build/linux-i586/jdk-module-image
cd ~/dev/hk2-1.6.32/hk2-maven-plugin/
mvn clean install
Make (parts of) hk2 Jigsaw friendly (ie Jigsaw projects):
JSR330 support
mkdir ~/dev/hk2-jigsaw(update the libraryDirectory path for your set up / username, gedit ~/dev/hk2-jigsaw/hk2jsr330/pom.xml & )
cp -r ~/dev/hk2-jigsaw-downloads/hk2-jigsaw/hk2jsr330/ ~/dev/hk2-jigsaw/
cd ~/dev/hk2-jigsaw/hk2jsr330/
mvn -Dmaven.test.skip=true clean install
HK2-API
cp ~/dev/hk2-jigsaw-downloads/hk2-1.6.32/hk2-api/pom.xml ~/dev/hk2-1.6.32/hk2-api/(update the libraryDirectory path for your set up / username, gedit ~/dev/hk2-1.6.32/hk2-api/pom.xml & )
mkdir ~/dev/hk2-1.6.32/hk2-api/src/main/java/lh.jigsaw.hk2.apibuild
mv ~/dev/hk2-1.6.32/hk2-api/src/main/java/org/ ~/dev/hk2-1.6.32/hk2-api/src/main/java/lh.jigsaw.hk2.api/
cp ~/dev/hk2-jigsaw-downloads/hk2-1.6.32/hk2-api/src/main/java/lh.jigsaw.hk2.api/module-info.java ~/dev/hk2-1.6.32/hk2-api/src/main/java/lh.jigsaw.hk2.api/
cd ~/dev/hk2-1.6.32/hk2-api/
mvn -Dmaven.test.skip=true clean install
Auto-depends
cp ~/dev/hk2-jigsaw-downloads/hk2-1.6.32/auto-depends/pom.xml ~/dev/hk2-1.6.32/auto-depends/(update the libraryDirectory path for your set up / username, gedit ~/dev/hk2-1.6.32/auto-depends/pom.xml & )
mkdir ~/dev/hk2-1.6.32/auto-depends/src/main/java/lh.jigsaw.hk2.autodependsbuild
mv ~/dev/hk2-1.6.32/auto-depends/src/main/java/org/ ~/dev/hk2-1.6.32/auto-depends/src/main/java/lh.jigsaw.hk2.autodepends
mv ~/dev/hk2-1.6.32/auto-depends/src/main/java/com/ ~/dev/hk2-1.6.32/auto-depends/src/main/java/lh.jigsaw.hk2.autodepends
cp ~/dev/hk2-jigsaw-downloads/hk2-1.6.32/auto-depends/src/main/java/lh.jigsaw.hk2.autodepends/module-info.java ~/dev/hk2-1.6.32/auto-depends/src/main/java/lh.jigsaw.hk2.autodepends/
cd ~/dev/hk2-1.6.32/auto-depends/HK2-Core
mvn -Dmaven.test.skip=true clean install
cp ~/dev/hk2-jigsaw-downloads/hk2-1.6.32/core/pom.xml ~/dev/hk2-1.6.32/core/(update the libraryDirectory path for your set up / username, gedit ~/dev/hk2-1.6.32/core/pom.xml & )
mkdir ~/dev/hk2-1.6.32/core/src/main/build
mv ~/dev/hk2-1.6.32/core/src/java ~/dev/hk2-1.6.32/core/src/main/
mkdir ~/dev/hk2-1.6.32/core/src/main/java/lh.jigsaw.hk2.core
mv ~/dev/hk2-1.6.32/core/src/main/java/com ~/dev/hk2-1.6.32/core/src/main/java/lh.jigsaw.hk2.core/
cp ~/dev/hk2-jigsaw-downloads/hk2-1.6.32/core/src/main/java/lh.jigsaw.hk2.core/module-info.java ~/dev/hk2-1.6.32/core/src/main/java/lh.jigsaw.hk2.core/
cd ~/dev/hk2-1.6.32/core/
mvn -Dmaven.test.skip=true clean install
Add the adapter for Jigsaw:
The adapter only implements the minimum required to start HK2 over Jigsaw and inject a dependency in a program. It inspired by both the initial HK2 launcher and the OSGi adapter. The Jigsaw interaction bits are in JigsawFactory (obtain a library instance), JigsawModuleDefinition (obtain the inhabitants file content from the Jisaw library for a module), JigsawModulesRegistry (obtain a class loader for a module).cp -r ~/dev/hk2-jigsaw-downloads/hk2-jigsaw/jigsaw-adapter ~/dev/hk2-jigsaw/
cd ~/dev/hk2-jigsaw/jigsaw-adapter
mvn -Dmaven.test.skip=true clean install
Let's us it:
See Worldclock on Jigsaw and HK2Wednesday, 18 January 2012
Jigsaw: Worldclock with the Maven plugin
Last updated: 2012-02-02
In the previous post I created a Maven plugin for Jigsaw, now I'll adapt Worldclock to use it.
The transformed source code is also available at: https://svn.java.net/svn/worldclock-application~svn/tags/application6-jigsaw-maven
1. Create the directory
3. Cleanup
Remove the files that are not needed.
4. Code adjustment
The current combinaison of Jigsaw/JDK8/Ubuntu does not support the sytem tray properly, so adjust the Worldclock.java to bypass it
5. Move the source
Move the files to create the java sources for the application:
7. Add module-info for Application
8. Add the pom for Panel
9. Add the pom for Application
10. Install Panel
11. Install Application
12. Run
In the previous post I created a Maven plugin for Jigsaw, now I'll adapt Worldclock to use it.
The transformed source code is also available at: https://svn.java.net/svn/worldclock-application~svn/tags/application6-jigsaw-maven
1. Create the directory
mkdir -p ~/dev/worldclock2. Get the source
cd ~/dev/worldclock
svn checkout https://svn.java.net/svn/worldclock-application~svn/tags/application6-jigsaw ~/dev/worldclock/application
3. Cleanup
Remove the files that are not needed.
rm -rf ~/dev/worldclock/application/*.*
rm -rf ~/dev/worldclock/application/src/META-INF
4. Code adjustment
The current combinaison of Jigsaw/JDK8/Ubuntu does not support the sytem tray properly, so adjust the Worldclock.java to bypass it
gedit ~/dev/worldclock/application/src/lh/worldclock/WorldClock.java &
on line 106 replace:
if (SystemTray.isSupported())
with:
if (false)
on line 135 replace:
if (showWindowOnStart)
with:
if (true)
5. Move the source
Move the files to create the java sources for the application:
mkdir -p ~/dev/worldclock/application/src/main/java/lh.worlclock.application/lh/worldclockMove the application resources:
mv ~/dev/worldclock/application/src/lh/worldclock/*.java ~/dev/worldclock/application/src/main/java/lh.worlclock.application/lh/worldclock
mkdir -p ~/dev/worldclock/application/src/main/resources/lh/worldclockMove the panel source:
mv ~/dev/worldclock/application/src/lh/worldclock/*.* ~/dev/worldclock/application/src/main/resources/lh/worldclock
mkdir -p ~/dev/worldclock/panel/src/main/java/lh.worldclock.panel/lh/worldclock/coreMove the panel resources:
mv ~/dev/worldclock/application/src/lh/worldclock/core/*.java ~/dev/worldclock/panel/src/main/java/lh.worldclock.panel/lh/worldclock/core
mkdir -p ~/dev/worldclock/panel/src/main/resources/lh/worldclock/coreMore cleanup:
mv ~/dev/worldclock/application/src/lh/worldclock/core/*.jpg ~/dev/worldclock/panel/src/main/resources/lh/worldclock/core
rm -rf ~/dev/worldclock/application/src/lh/worldclock/core6. Add module-info for Panel
gedit ~/dev/worldclock/panel/src/main/java/lh.worldclock.panel/module-info.java &
module lh.worldclock.panel @ 0.7
{
requires jdk.base;
requires jdk.desktop;
exports lh.worldclock.core.*;
}
7. Add module-info for Application
gedit ~/dev/worldclock/application/src/main/java/lh.worlclock.application/module-info.java &
module lh.worldclock.application @ 0.7
{
requires jdk.base;
requires jdk.desktop;
requires lh.worldclock.panel @ 0.7;
class lh.worldclock.WorldClock;
}
8. Add the pom for Panel
gedit ~/dev/worldclock/panel/pom.xml &
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>lh.worldclock</groupId>
<artifactId>panel</artifactId>
<packaging>jmod</packaging>
<version>0.7-SNAPSHOT</version>
<name>Worldclock Panel</name>
<url>http://worldclock-application.java.net/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>lh.jigsaw</groupId>
<artifactId>jigsaw-maven-plugin</artifactId>
<version>0.1-SNAPSHOT</version>
<extensions>true</extensions>
<configuration>
<libraryDirectory>../modules</libraryDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
9. Add the pom for Application
gedit ~/dev/worldclock/application/pom.xml &
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>lh.worldclock</groupId>
<artifactId>application</artifactId>
<packaging>jmod</packaging>
<version>0.7-SNAPSHOT</version>
<name>Worldclock Application</name>
<url>http://worldclock-application.java.net/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>lh.jigsaw</groupId>
<artifactId>jigsaw-maven-plugin</artifactId>
<version>0.1-SNAPSHOT</version>
<extensions>true</extensions>
<configuration>
<libraryDirectory>../modules</libraryDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
10. Install Panel
cd ~/dev/worldclock/panel/
mvn install
11. Install Application
cd ~/dev/worldclock/application/
mvn install
12. Run
cd ~/dev/worldclock/application/
mvn lh.jigsaw:jigsaw-maven-plugin:run
(use ctrl+c on the console to exit)
Labels:
Java8,
Jigsaw,
Maven,
Worldclock
Jigsaw and Maven: Take 2, a Maven plugin
Last updated: 2012-11-01
This post will create a Maven plugin for Jigsaw. This plugin is based on HK2 Maven plugin.
The post includes all the code needed to build the plugin.
(the resulting source code, except for changes in Jigsaw's source, is available at: https://svn.kenai.com/svn/lh-playground~svn/jigsaw )
Setting up the environment:
1. Build Jigsaw
2. Get Subversion
Custom Plexus Javac Component:
1. Get the code
skip the tests as some are now failing due to the different way to handle errors/warnings
1. Create the directories
This is needed so that the CompilerMojo subclass parent get its dependencies properly injected. The sole change from the original from the Maven compiler plugin is the package name.
Jigsaw adjustments to the compiler mojo.
Package the module into a .jmod file.
Installs the jmod file into the library.
Runs the project's module from the library.
See Jigsaw: Worldclock with the Maven plugin
This post will create a Maven plugin for Jigsaw. This plugin is based on HK2 Maven plugin.
The post includes all the code needed to build the plugin.
(the resulting source code, except for changes in Jigsaw's source, is available at: https://svn.kenai.com/svn/lh-playground~svn/jigsaw )
Setting up the environment:
1. Build Jigsaw
2. Get Subversion
sudo apt-get install subversion3. Get Maven
sudo apt-get install maven24. Set JAVA_HOME
export JAVA_HOME='/usr/lib/jvm/java-7-openjdk-i386'
Custom Plexus Javac Component:
1. Get the code
cd ~/dev2. Compile without modification
svn checkout https://svn.codehaus.org/plexus/plexus-components/tags/1.8.1/plexus-compilers/plexus-compiler-javac ~/dev/plexus-compiler-javac
cd ~/dev/plexus-compiler-javac3. Adjust the pom
mvn install
gedit ~/dev/plexus-compiler-javac/pom.xml &4. Adjust the code
replace the existing content with
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compilers</artifactId>
<version>1.8.1</version>
</parent>
<artifactId>plexus-compiler-javac</artifactId>
<name>Jigsaw Plexus Javac Component</name>
<version>1.8.1-jigsaw</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-javac</artifactId>
<version>1.8.1</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-api</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-test</artifactId>
<version>1.8.1</version>
</dependency>
</dependencies>
</project>
gedit ~/dev/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java &5. Compile the modifed code
add the imports:
import java.util.Locale;
import javax.tools.*;
import javax.tools.Diagnostic.Kind;
locate the call to compileInProcess (line 165)
messages = compileInProcess( args );
replace it with:
messages = compileInProcessJSR199( buildCompilerArgumentsJSR199( config ), sourceFiles );
add the method:
public static List<String> buildCompilerArgumentsJSR199( CompilerConfiguration config )
{
List<String> args = new ArrayList<String>();
// ----------------------------------------------------------------------
// Set output
// ----------------------------------------------------------------------
File destinationDir = new File( config.getOutputLocation() );
args.add( "-d" );
args.add( destinationDir.getAbsolutePath() );
// ----------------------------------------------------------------------
// Set the class and source paths
// ----------------------------------------------------------------------
List classpathEntries = config.getClasspathEntries();
if ( classpathEntries != null && !classpathEntries.isEmpty())
{
args.add( "-classpath" );
args.add( getPathString( classpathEntries ) );
}
List sourceLocations = config.getSourceLocations();
if ( sourceLocations != null && !sourceLocations.isEmpty() )
{
//always pass source path, even if sourceFiles are declared,
//needed for jsr269 annotation processing, see MCOMPILER-98
args.add( "-sourcepath" );
args.add( getPathString( sourceLocations ) );
}
//now add jdk 1.6 annotation processing related parameters
if ( config.getGeneratedSourcesDirectory() != null )
{
config.getGeneratedSourcesDirectory().mkdirs();
args.add( "-s" );
args.add( config.getGeneratedSourcesDirectory().getAbsolutePath() );
}
if ( config.getProc() != null )
{
args.add( "-proc:" + config.getProc() );
}
if ( config.getAnnotationProcessors() != null )
{
args.add("-processor");
String[] procs = config.getAnnotationProcessors();
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < procs.length; i++)
{
if (i > 0)
{
buffer.append( "," );
}
buffer.append( procs[i] );
}
args.add( buffer.toString() );
}
if ( config.isOptimize() )
{
args.add( "-O" );
}
if ( config.isDebug() )
{
if ( StringUtils.isNotEmpty( config.getDebugLevel() ) )
{
args.add( "-g:" + config.getDebugLevel() );
}
else
{
args.add( "-g" );
}
}
if ( config.isVerbose() )
{
args.add( "-verbose" );
}
if ( config.isShowDeprecation() )
{
args.add( "-deprecation" );
// This is required to actually display the deprecation messages
config.setShowWarnings( true );
}
if ( !config.isShowWarnings() )
{
args.add( "-nowarn" );
}
// TODO: this could be much improved
if ( StringUtils.isEmpty( config.getTargetVersion() ) )
{
// Required, or it defaults to the target of your JDK (eg 1.5)
args.add( "-target" );
args.add( "1.1" );
}
else
{
args.add( "-target" );
args.add( config.getTargetVersion() );
}
if ( !suppressSource( config ) && StringUtils.isEmpty( config.getSourceVersion() ) )
{
// If omitted, later JDKs complain about a 1.1 target
args.add( "-source" );
args.add( "1.3" );
}
else if ( !suppressSource( config ) )
{
args.add( "-source" );
args.add( config.getSourceVersion() );
}
if ( !suppressEncoding( config ) && !StringUtils.isEmpty( config.getSourceEncoding() ) )
{
args.add( "-encoding" );
args.add( config.getSourceEncoding() );
}
for ( Iterator it = config.getCustomCompilerArguments().entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
if ( StringUtils.isEmpty( key ) )
{
continue;
}
args.add( key );
String value = (String) entry.getValue();
if ( StringUtils.isEmpty( value ) )
{
continue;
}
args.add( value );
}
return args;
}
add the method:
List compileInProcessJSR199(List<String> args, String[] sources)
{
List<CompilerError> messages = new ArrayList<CompilerError>();
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
getLogger().info("javac =" + javac);
getLogger().info("args = " + args);
DiagnosticCollector<JavaFileObject> filesDiagnostics = new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager filesManager = javac.getStandardFileManager(filesDiagnostics, null, null);
Iterable<? extends JavaFileObject> compilationUnit = filesManager.getJavaFileObjects(sources);
javac.getTask(null, null, filesDiagnostics, args, null, compilationUnit).call();
for (Diagnostic<? extends JavaFileObject> diag: filesDiagnostics.getDiagnostics())
{
messages.add(new CompilerError(diag.toString(), diag.getKind() == Kind.ERROR));
}
try
{
filesManager.close();
}
catch (IOException ex)
{
messages.add(new CompilerError("ex closing file manager: " + ex.getMessage(), false));
}
return messages;
}
skip the tests as some are now failing due to the different way to handle errors/warnings
cd ~/dev/plexus-compiler-javac6. Set JAVA_HOME
mvn -DskipTests=true install
export JAVA_HOME=~/dev/jigsaw/build/linux-i586/jdk-module-image
Custom Maven plugin:
1. Create the directories
mkdir -p ~/dev/jigsaw-maven-plugin/src/main/java/lh/jigsaw/plugin2. Add the pom
mkdir -p ~/dev/jigsaw-maven-plugin/src/main/resources/META-INF/plexus
gedit ~/dev/jigsaw-maven-plugin/pom.xml &3. Add the components.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>lh.jigsaw</groupId>
<artifactId>jigsaw-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>0.1-SNAPSHOT</version>
<name>Jigsaw Maven Plugin</name>
<description>Maven2 plugin for creating Jigsaw modules</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration> <dependencies> <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-compiler-javac</artifactId> <version>1.8.1-jigsaw</version> <exclusions> <exclusion> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-component-api</artifactId> </exclusion> </exclusions> </dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-api</artifactId>
<version>1.8.1</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-manager</artifactId>
<version>1.8.1</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-javac</artifactId>
<version>1.8.1-jigsaw</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
<version>1.0-alpha-9-stable-1</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-toolchain</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
gedit ~/dev/jigsaw-maven-plugin/src/main/resources/META-INF/plexus/components.xml &4. Add InitialiseMojo:
<component-set>
<!-- this defines a custom life cycle for .jmod -->
<components>
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>jmod</role-hint>
<implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
<configuration>
<lifecycles>
<lifecycle>
<id>default</id>
<phases>
<initialize>lh.jigsaw:jigsaw-maven-plugin:initialise</initialize>
<process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
<compile>lh.jigsaw:jigsaw-maven-plugin:lh-compile</compile>
<process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
<test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
<test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
<package>lh.jigsaw:jigsaw-maven-plugin:jpkg,org.apache.maven.plugins:maven-jar-plugin:jar</package>
<install>lh.jigsaw:jigsaw-maven-plugin:jmod,org.apache.maven.plugins:maven-install-plugin:install</install>
<deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
</phases>
</lifecycle>
</lifecycles>
</configuration>
</component>
<component>
<role>org.apache.maven.artifact.handler.ArtifactHandler</role>
<role-hint>jmod</role-hint>
<implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
<configuration>
<extension>jmod</extension>
<type>jmod</type>
<packaging>jmod</packaging>
<language>java</language>
<addedToClasspath>true</addedToClasspath>
</configuration>
</component>
</components>
</component-set>
gedit ~/dev/jigsaw-maven-plugin/src/main/java/lh/jigsaw/plugin/InitialiseMojo.java &5. Add AbstractCompilerMojo:
package lh.jigsaw.plugin;
import java.io.File;
import java.io.IOException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.openjdk.jigsaw.SimpleLibrary;
/**
* Initialise the library if it doesn't exist, will fail the build if the directory is not a valid library<br>
* It will use ${project.build.directory}/library as the default location for the project library, the JDK library
* as its parent.
*
* @requiresProject
* @goal initialise
* @requiresDependencyResolution runtime
* @phase initialize
*
* @author ludovic
*/
public class InitialiseMojo extends AbstractMojo
{
/**
* library directory
*
* @parameter default-value="${project.build.directory}/library"
* @required
*/
private File libraryDirectory;
@Override
public void execute() throws MojoExecutionException, MojoFailureException
{
getLog().info("InitialiseMojo");
try
{
if (libraryDirectory.exists())
{
SimpleLibrary.open(libraryDirectory);
}
else
{
File homeLibrary = new File(System.getProperty("java.home"),
"lib/modules");
SimpleLibrary.create(libraryDirectory, homeLibrary);
}
}
catch (IOException ex)
{
throw new MojoExecutionException("Library '" + libraryDirectory + "' is not valid.", ex);
}
}
}
This is needed so that the CompilerMojo subclass parent get its dependencies properly injected. The sole change from the original from the Maven compiler plugin is the package name.
gedit ~/dev/jigsaw-maven-plugin/src/main/java/lh/jigsaw/plugin/AbstractCompilerMojo.java &6. Add CompilerMojo:
package lh.jigsaw.plugin;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.CompilationFailureException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.codehaus.plexus.compiler.Compiler;
import org.codehaus.plexus.compiler.CompilerConfiguration;
import org.codehaus.plexus.compiler.CompilerError;
import org.codehaus.plexus.compiler.CompilerException;
import org.codehaus.plexus.compiler.CompilerOutputStyle;
import org.codehaus.plexus.compiler.manager.CompilerManager;
import org.codehaus.plexus.compiler.manager.NoSuchCompilerException;
import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.mapping.SingleTargetSourceMapping;
import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
/**
* TODO: At least one step could be optimized, currently the plugin will do two
* scans of all the source code if the compiler has to have the entire set of
* sources. This is currently the case for at least the C# compiler and most
* likely all the other .NET compilers too.
*
* @author others
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a>
* @version $Id: AbstractCompilerMojo.java 990573 2010-08-29 12:12:21Z bentmann $
* @since 2.0
*/
public abstract class AbstractCompilerMojo
extends AbstractMojo
{
// ----------------------------------------------------------------------
// Configurables
// ----------------------------------------------------------------------
/**
* Indicates whether the build will continue even if there are compilation errors; defaults to true.
*
* @parameter expression="${maven.compiler.failOnError}" default-value="true"
* @since 2.0.2
*/
private boolean failOnError = true;
/**
* Set to true to include debugging information in the compiled class files.
*
* @parameter expression="${maven.compiler.debug}" default-value="true"
*/
private boolean debug = true;
/**
* Set to true to show messages about what the compiler is doing.
*
* @parameter expression="${maven.compiler.verbose}" default-value="false"
*/
private boolean verbose;
/**
* Sets whether to show source locations where deprecated APIs are used.
*
* @parameter expression="${maven.compiler.showDeprecation}" default-value="false"
*/
private boolean showDeprecation;
/**
* Set to true to optimize the compiled code using the compiler's optimization methods.
*
* @parameter expression="${maven.compiler.optimize}" default-value="false"
*/
private boolean optimize;
/**
* Set to true to show compilation warnings.
*
* @parameter expression="${maven.compiler.showWarnings}" default-value="false"
*/
private boolean showWarnings;
/**
* The -source argument for the Java compiler.
*
* @parameter expression="${maven.compiler.source}" default-value="1.5"
*/
protected String source;
/**
* The -target argument for the Java compiler.
*
* @parameter expression="${maven.compiler.target}" default-value="1.5"
*/
protected String target;
/**
* The -encoding argument for the Java compiler.
*
* @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
*/
private String encoding;
/**
* Sets the granularity in milliseconds of the last modification
* date for testing whether a source needs recompilation.
*
* @parameter expression="${lastModGranularityMs}" default-value="0"
*/
private int staleMillis;
/**
* The compiler id of the compiler to use. See this
* <a href="non-javac-compilers.html">guide</a> for more information.
*
* @parameter expression="${maven.compiler.compilerId}" default-value="javac"
*/
private String compilerId;
/**
* Version of the compiler to use, ex. "1.3", "1.5", if fork is set to true.
*
* @parameter expression="${maven.compiler.compilerVersion}"
*/
private String compilerVersion;
/**
* Allows running the compiler in a separate process.
* If "false" it uses the built in compiler, while if "true" it will use an executable.
*
* @parameter expression="${maven.compiler.fork}" default-value="false"
*/
private boolean fork;
/**
* Initial size, in megabytes, of the memory allocation pool, ex. "64", "64m"
* if fork is set to true.
*
* @parameter expression="${maven.compiler.meminitial}"
* @since 2.0.1
*/
private String meminitial;
/**
* Sets the maximum size, in megabytes, of the memory allocation pool, ex. "128", "128m"
* if fork is set to true.
*
* @parameter expression="${maven.compiler.maxmem}"
* @since 2.0.1
*/
private String maxmem;
/**
* Sets the executable of the compiler to use when fork is true.
*
* @parameter expression="${maven.compiler.executable}"
*/
private String executable;
/**
* <p>
* Sets whether annotation processing is performed or not. Only applies to JDK 1.6+
* If not set, both compilation and annotation processing are performed at the same time.
* </p>
* <p>
* Allowed values are:
* none - no annotation processing is performed.
* only - only annotation processing is done, no compilation.
* </p>
*
* @parameter
* @since 2.2
*/
private String proc;
/**
* <p>
* Names of annotation processors to run. Only applies to JDK 1.6+
* If not set, the default annotation processors discovery process applies.
* </p>
*
* @parameter
* @since 2.2
*/
private String[] annotationProcessors;
/**
* <p>
* Sets the arguments to be passed to the compiler (prepending a dash) if fork is set to true.
* </p>
* <p>
* This is because the list of valid arguments passed to a Java compiler
* varies based on the compiler version.
* </p>
*
* @parameter
* @since 2.0.1
*/
protected Map<String, String> compilerArguments;
/**
* <p>
* Sets the unformatted argument string to be passed to the compiler if fork is set to true.
* </p>
* <p>
* This is because the list of valid arguments passed to a Java compiler
* varies based on the compiler version.
* </p>
*
* @parameter
*/
protected String compilerArgument;
/**
* Sets the name of the output file when compiling a set of
* sources to a single file.
*
* @parameter expression="${project.build.finalName}"
*/
private String outputFileName;
/**
* Keyword list to be appended to the -g command-line switch. Legal values are none or a comma-separated list of the following keywords: lines, vars, and source.
* If debuglevel is not specified, by default, nothing will be appended to -g. If debug is not turned on, this attribute will be ignored.
*
* @parameter expression="${maven.compiler.debuglevel}"
* @since 2.1
*/
private String debuglevel;
/** @component */
private ToolchainManager toolchainManager;
// ----------------------------------------------------------------------
// Read-only parameters
// ----------------------------------------------------------------------
/**
* The directory to run the compiler from if fork is true.
*
* @parameter default-value="${basedir}"
* @required
* @readonly
*/
private File basedir;
/**
* The target directory of the compiler if fork is true.
*
* @parameter default-value="${project.build.directory}"
* @required
* @readonly
*/
private File buildDirectory;
/**
* Plexus compiler manager.
*
* @component
*/
private CompilerManager compilerManager;
/**
* The current build session instance. This is used for
* toolchain manager API calls.
*
* @parameter default-value="${session}"
* @required
* @readonly
*/
private MavenSession session;
protected abstract SourceInclusionScanner getSourceInclusionScanner( int staleMillis );
protected abstract SourceInclusionScanner getSourceInclusionScanner( String inputFileEnding );
protected abstract List<String> getClasspathElements();
protected abstract List<String> getCompileSourceRoots();
protected abstract File getOutputDirectory();
protected abstract String getSource();
protected abstract String getTarget();
protected abstract String getCompilerArgument();
protected abstract Map<String, String> getCompilerArguments();
protected abstract File getGeneratedSourcesDirectory();
@SuppressWarnings( "unchecked" )
public void execute()
throws MojoExecutionException, CompilationFailureException
{
// ----------------------------------------------------------------------
// Look up the compiler. This is done before other code than can
// cause the mojo to return before the lookup is done possibly resulting
// in misconfigured POMs still building.
// ----------------------------------------------------------------------
Compiler compiler;
getLog().debug( "Using compiler '" + compilerId + "'." );
try
{
compiler = compilerManager.getCompiler( compilerId );
}
catch ( NoSuchCompilerException e )
{
throw new MojoExecutionException( "No such compiler '" + e.getCompilerId() + "'." );
}
//-----------toolchains start here ----------------------------------
//use the compilerId as identifier for toolchains as well.
Toolchain tc = getToolchain();
if ( tc != null )
{
getLog().info( "Toolchain in compiler-plugin: " + tc );
if ( executable != null )
{
getLog().warn( "Toolchains are ignored, 'executable' parameter is set to " + executable );
}
else
{
fork = true;
//TODO somehow shaky dependency between compilerId and tool executable.
executable = tc.findTool( compilerId );
}
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
List<String> compileSourceRoots = removeEmptyCompileSourceRoots( getCompileSourceRoots() );
if ( compileSourceRoots.isEmpty() )
{
getLog().info( "No sources to compile" );
return;
}
if ( getLog().isDebugEnabled() )
{
getLog().debug( "Source directories: " + compileSourceRoots.toString().replace( ',', '\n' ) );
getLog().debug( "Classpath: " + getClasspathElements().toString().replace( ',', '\n' ) );
getLog().debug( "Output directory: " + getOutputDirectory() );
}
// ----------------------------------------------------------------------
// Create the compiler configuration
// ----------------------------------------------------------------------
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
compilerConfiguration.setOutputLocation( getOutputDirectory().getAbsolutePath() );
compilerConfiguration.setClasspathEntries( getClasspathElements() );
compilerConfiguration.setSourceLocations( compileSourceRoots );
compilerConfiguration.setOptimize( optimize );
compilerConfiguration.setDebug( debug );
if ( debug && StringUtils.isNotEmpty( debuglevel ) )
{
String[] split = StringUtils.split( debuglevel, "," );
for ( int i = 0; i < split.length; i++ )
{
if ( !( split[i].equalsIgnoreCase( "none" ) || split[i].equalsIgnoreCase( "lines" )
|| split[i].equalsIgnoreCase( "vars" ) || split[i].equalsIgnoreCase( "source" ) ) )
{
throw new IllegalArgumentException( "The specified debug level: '" + split[i]
+ "' is unsupported. " + "Legal values are 'none', 'lines', 'vars', and 'source'." );
}
}
compilerConfiguration.setDebugLevel( debuglevel );
}
compilerConfiguration.setVerbose( verbose );
compilerConfiguration.setShowWarnings( showWarnings );
compilerConfiguration.setShowDeprecation( showDeprecation );
compilerConfiguration.setSourceVersion( getSource() );
compilerConfiguration.setTargetVersion( getTarget() );
compilerConfiguration.setProc( proc );
compilerConfiguration.setGeneratedSourcesDirectory( getGeneratedSourcesDirectory() );
compilerConfiguration.setAnnotationProcessors( annotationProcessors );
compilerConfiguration.setSourceEncoding( encoding );
Map<String, String> effectiveCompilerArguments = getCompilerArguments();
String effectiveCompilerArgument = getCompilerArgument();
if ( ( effectiveCompilerArguments != null ) || ( effectiveCompilerArgument != null ) )
{
LinkedHashMap<String, String> cplrArgsCopy = new LinkedHashMap<String, String>();
if ( effectiveCompilerArguments != null )
{
for ( Map.Entry<String, String> me : effectiveCompilerArguments.entrySet() )
{
String key = (String) me.getKey();
String value = (String) me.getValue();
if ( !key.startsWith( "-" ) )
{
key = "-" + key;
}
cplrArgsCopy.put( key, value );
}
}
if ( !StringUtils.isEmpty( effectiveCompilerArgument ) )
{
cplrArgsCopy.put( effectiveCompilerArgument, null );
}
compilerConfiguration.setCustomCompilerArguments( cplrArgsCopy );
}
compilerConfiguration.setFork( fork );
if ( fork )
{
if ( !StringUtils.isEmpty( meminitial ) )
{
String value = getMemoryValue( meminitial );
if ( value != null )
{
compilerConfiguration.setMeminitial( value );
}
else
{
getLog().info( "Invalid value for meminitial '" + meminitial + "'. Ignoring this option." );
}
}
if ( !StringUtils.isEmpty( maxmem ) )
{
String value = getMemoryValue( maxmem );
if ( value != null )
{
compilerConfiguration.setMaxmem( value );
}
else
{
getLog().info( "Invalid value for maxmem '" + maxmem + "'. Ignoring this option." );
}
}
}
compilerConfiguration.setExecutable( executable );
compilerConfiguration.setWorkingDirectory( basedir );
compilerConfiguration.setCompilerVersion( compilerVersion );
compilerConfiguration.setBuildDirectory( buildDirectory );
compilerConfiguration.setOutputFileName( outputFileName );
// TODO: have an option to always compile (without need to clean)
Set<File> staleSources;
boolean canUpdateTarget;
try
{
staleSources =
computeStaleSources( compilerConfiguration, compiler, getSourceInclusionScanner( staleMillis ) );
canUpdateTarget = compiler.canUpdateTarget( compilerConfiguration );
if ( compiler.getCompilerOutputStyle().equals( CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES ) &&
!canUpdateTarget )
{
getLog().info( "RESCANNING!" );
// TODO: This second scan for source files is sub-optimal
String inputFileEnding = compiler.getInputFileEnding( compilerConfiguration );
Set<File> sources = computeStaleSources( compilerConfiguration, compiler,
getSourceInclusionScanner( inputFileEnding ) );
compilerConfiguration.setSourceFiles( sources );
}
else
{
compilerConfiguration.setSourceFiles( staleSources );
}
}
catch ( CompilerException e )
{
throw new MojoExecutionException( "Error while computing stale sources.", e );
}
if ( staleSources.isEmpty() )
{
getLog().info( "Nothing to compile - all classes are up to date" );
return;
}
// ----------------------------------------------------------------------
// Dump configuration
// ----------------------------------------------------------------------
if ( getLog().isDebugEnabled() )
{
getLog().debug( "Classpath:" );
for ( String s : getClasspathElements() )
{
getLog().debug( " " + s );
}
getLog().debug( "Source roots:" );
for ( String root : getCompileSourceRoots() )
{
getLog().debug( " " + root );
}
try
{
if ( fork )
{
if ( compilerConfiguration.getExecutable() != null )
{
getLog().debug( "Excutable: " );
getLog().debug( " " + compilerConfiguration.getExecutable() );
}
}
String[] cl = compiler.createCommandLine( compilerConfiguration );
if ( cl != null && cl.length > 0 )
{
StringBuffer sb = new StringBuffer();
sb.append( cl[0] );
for ( int i = 1; i < cl.length; i++ )
{
sb.append( " " );
sb.append( cl[i] );
}
getLog().debug( "Command line options:" );
getLog().debug( sb );
}
}
catch ( CompilerException ce )
{
getLog().debug( ce );
}
}
// ----------------------------------------------------------------------
// Compile!
// ----------------------------------------------------------------------
if ( StringUtils.isEmpty( compilerConfiguration.getSourceEncoding() ) )
{
getLog().warn(
"File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
+ ", i.e. build is platform dependent!" );
}
List<CompilerError> messages;
try
{
messages = compiler.compile( compilerConfiguration );
}
catch ( Exception e )
{
// TODO: don't catch Exception
throw new MojoExecutionException( "Fatal error compiling", e );
}
List<CompilerError> warnings = new ArrayList<CompilerError>();
List<CompilerError> errors = new ArrayList<CompilerError>();
if ( messages != null )
{
for ( CompilerError message : messages )
{
if ( message.isError() )
{
errors.add( message );
}
else
{
warnings.add( message );
}
}
}
if ( failOnError && !errors.isEmpty() )
{
if ( !warnings.isEmpty() )
{
getLog().info( "-------------------------------------------------------------" );
getLog().warn( "COMPILATION WARNING : " );
getLog().info( "-------------------------------------------------------------" );
for ( CompilerError warning : warnings )
{
getLog().warn( warning.toString() );
}
getLog().info( warnings.size() + ( ( warnings.size() > 1 ) ? " warnings " : " warning" ) );
getLog().info( "-------------------------------------------------------------" );
}
getLog().info( "-------------------------------------------------------------" );
getLog().error( "COMPILATION ERROR : " );
getLog().info( "-------------------------------------------------------------" );
for ( CompilerError error : errors )
{
getLog().error( error.toString() );
}
getLog().info( errors.size() + ( ( errors.size() > 1 ) ? " errors " : " error" ) );
getLog().info( "-------------------------------------------------------------" );
throw new CompilationFailureException( errors );
}
else
{
for ( CompilerError message : messages )
{
getLog().warn( message.toString() );
}
}
}
private String getMemoryValue( String setting )
{
String value = null;
// Allow '128' or '128m'
if ( isDigits( setting ) )
{
value = setting + "m";
}
else
{
if ( ( isDigits( setting.substring( 0, setting.length() - 1 ) ) ) &&
( setting.toLowerCase().endsWith( "m" ) ) )
{
value = setting;
}
}
return value;
}
//TODO remove the part with ToolchainManager lookup once we depend on
//3.0.9 (have it as prerequisite). Define as regular component field then.
private Toolchain getToolchain()
{
Toolchain tc = null;
if ( toolchainManager != null )
{
tc = toolchainManager.getToolchainFromBuildContext( "jdk", session );
}
return tc;
}
private boolean isDigits( String string )
{
for ( int i = 0; i < string.length(); i++ )
{
if ( !Character.isDigit( string.charAt( i ) ) )
{
return false;
}
}
return true;
}
@SuppressWarnings( "unchecked" )
private Set<File> computeStaleSources( CompilerConfiguration compilerConfiguration, Compiler compiler,
SourceInclusionScanner scanner )
throws MojoExecutionException, CompilerException
{
CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
SourceMapping mapping;
File outputDirectory;
if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE )
{
mapping = new SuffixMapping( compiler.getInputFileEnding( compilerConfiguration ), compiler
.getOutputFileEnding( compilerConfiguration ) );
outputDirectory = getOutputDirectory();
}
else if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
{
mapping = new SingleTargetSourceMapping( compiler.getInputFileEnding( compilerConfiguration ), compiler
.getOutputFile( compilerConfiguration ) );
outputDirectory = buildDirectory;
}
else
{
throw new MojoExecutionException( "Unknown compiler output style: '" + outputStyle + "'." );
}
scanner.addSourceMapping( mapping );
Set<File> staleSources = new HashSet<File>();
for ( String sourceRoot : getCompileSourceRoots() )
{
File rootFile = new File( sourceRoot );
if ( !rootFile.isDirectory() )
{
continue;
}
try
{
staleSources.addAll( scanner.getIncludedSources( rootFile, outputDirectory ) );
}
catch ( InclusionScanException e )
{
throw new MojoExecutionException(
"Error scanning source root: \'" + sourceRoot + "\' " + "for stale files to recompile.", e );
}
}
return staleSources;
}
/**
* @todo also in ant plugin. This should be resolved at some point so that it does not need to
* be calculated continuously - or should the plugins accept empty source roots as is?
*/
private static List<String> removeEmptyCompileSourceRoots( List<String> compileSourceRootsList )
{
List<String> newCompileSourceRootsList = new ArrayList<String>();
if ( compileSourceRootsList != null )
{
// copy as I may be modifying it
for ( String srcDir : compileSourceRootsList )
{
if ( !newCompileSourceRootsList.contains( srcDir ) && new File( srcDir ).exists() )
{
newCompileSourceRootsList.add( srcDir );
}
}
}
return newCompileSourceRootsList;
}
}
Jigsaw adjustments to the compiler mojo.
gedit ~/dev/jigsaw-maven-plugin/src/main/java/lh/jigsaw/plugin/CompilerMojo.java &7. Add JPkgMojo:
package lh.jigsaw.plugin;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.CompilationFailureException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner;
/**
* Jigsaw adjustments to the compiler mojo
*
* @since 2.0
* @goal lh-compile
* @phase compile
* @threadSafe
* @requiresDependencyResolution compile
*/
public class CompilerMojo extends AbstractCompilerMojo
{
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* The source directories containing the sources to be compiled.
*
* @parameter default-value="${project.compileSourceRoots}"
* @required
* @readonly
*/
private List<String> compileSourceRoots;
/**
* <p>
* Specify where to place generated source files created by annotation processing.
* Only applies to JDK 1.6+
* </p>
* @parameter default-value="${project.build.directory}/generated-sources/annotations"
* @since 2.2
*/
private File generatedSourcesDirectory;
/**
* Project classpath.
*
* @parameter default-value="${project.compileClasspathElements}"
* @required
* @readonly
*/
private List<String> classpathElements;
/**
* The directory for compiled classes.
*
* @parameter default-value="${project.build.outputDirectory}"
* @required
* @readonly
*/
private File outputDirectory;
/**
* Project artifacts.
*
* @parameter default-value="${project.artifact}"
* @required
* @readonly
* @todo this is an export variable, really
*/
private Artifact projectArtifact;
/**
* A list of inclusion filters for the compiler.
*
* @parameter
*/
private Set<String> includes = new HashSet<>();
/**
* A list of exclusion filters for the compiler.
*
* @parameter
*/
private Set<String> excludes = new HashSet<>();
/**
* library directory
*
* @parameter default-value="${project.build.directory}/library"
* @required
*/
private File libraryDirectory;
@Override
protected List<String> getCompileSourceRoots()
{
return compileSourceRoots;
}
@Override
protected List<String> getClasspathElements()
{
return classpathElements;
}
@Override
protected File getOutputDirectory()
{
return outputDirectory;
}
private void lhJigsawCompilerAdjustments()
{
compilerArguments = new HashMap<>(2);
compilerArguments.put("modulepath", outputDirectory.getAbsolutePath());
compilerArguments.put("L", libraryDirectory.getAbsolutePath());
}
@Override
public void execute() throws MojoExecutionException, CompilationFailureException
{
lhJigsawCompilerAdjustments();
super.execute();
projectArtifact.setFile(outputDirectory);
}
@Override
protected SourceInclusionScanner getSourceInclusionScanner(int staleMillis)
{
SourceInclusionScanner scanner;
if (includes.isEmpty() && excludes.isEmpty())
{
scanner = new StaleSourceScanner(staleMillis);
}
else
{
if (includes.isEmpty())
{
includes.add("**/*.java");
}
scanner = new StaleSourceScanner(staleMillis, includes, excludes);
}
return scanner;
}
@Override
protected SourceInclusionScanner getSourceInclusionScanner(String inputFileEnding)
{
SourceInclusionScanner scanner;
if (includes.isEmpty() && excludes.isEmpty())
{
includes = Collections.singleton("**/*." + inputFileEnding);
scanner = new SimpleSourceInclusionScanner(includes, Collections.EMPTY_SET);
}
else
{
if (includes.isEmpty())
{
includes.add("**/*." + inputFileEnding);
}
scanner = new SimpleSourceInclusionScanner(includes, excludes);
}
return scanner;
}
@Override
protected String getSource()
{
return source;
}
@Override
protected String getTarget()
{
return target;
}
@Override
protected String getCompilerArgument()
{
return compilerArgument;
}
@Override
protected Map<String, String> getCompilerArguments()
{
return compilerArguments;
}
@Override
protected File getGeneratedSourcesDirectory()
{
return generatedSourcesDirectory;
}
}
Package the module into a .jmod file.
gedit ~/dev/jigsaw-maven-plugin/src/main/java/lh/jigsaw/plugin/JPkgMojo.java &8 Add JModMojo:
package lh.jigsaw.plugin;
import java.io.File;
import java.io.IOException;
import java.lang.module.ModuleInfo;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.openjdk.jigsaw.JigsawModuleSystem;
import org.openjdk.jigsaw.cli.*;
/**
* Package the module into a jmod file.<br>
* Drops the file into ${project.build.directory}/module
*
* @requiresProject
* @goal jpkg
* @requiresDependencyResolution runtime
* @phase package
*
* @author ludovic
*/
public class JPkgMojo extends AbstractMojo
{
/**
* Library directory
*
* @parameter default-value="${project.build.directory}/library"
* @required
*/
private File libraryDirectory;
/**
* Classes directory.
*
* @parameter expression="${project.build.outputDirectory}"
* @required
* @readonly
*/
private File classesDir;
/**
* Output directory.
*
* @parameter expression="${project.build.directory}/module"
* @required
* @readonly
*/
private File outputDir;
/**
* Module name
*
* @parameter expression="${moduleName}"
* @readonly
*/
private String moduleName;
@Override
public void execute() throws MojoExecutionException, MojoFailureException
{
getLog().info("JPkgMojo");
try
{
if (outputDir.exists())
{
deleteDir(outputDir.toPath());
}
outputDir.mkdirs();
String[] params = new String[]
{
"-L",
libraryDirectory.getAbsolutePath(),
"-m",
classesDir.getAbsolutePath(),
"-d",
outputDir.getAbsolutePath(),
"jmod",
getModuleName()
};
getLog().info(Arrays.toString(params));
Packager.run(params);
}
catch (MojoExecutionException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new MojoExecutionException("Could not package '" + moduleName + "'.", ex);
}
}
private String getModuleName() throws MojoExecutionException
{
if (moduleName == null)
{
try
{
Path path = classesDir.toPath().resolve("module-info.class");
byte[] bytes = java.nio.file.Files.readAllBytes(path);
JigsawModuleSystem jms = JigsawModuleSystem.instance();
ModuleInfo mif = jms.parseModuleInfo(bytes);
moduleName = mif.id().name();
getLog().info("module name read from module-info = " + moduleName);
}
catch (IOException ex)
{
throw new MojoExecutionException("Could not read the module name, check that module-info.class exist.", ex);
}
}
return moduleName;
}
private static void deleteDir(Path dir) throws IOException
{
try (DirectoryStream<Path> s = Files.newDirectoryStream(dir))
{
for (Path p : s)
{
if (Files.isDirectory(p))
{
deleteDir(p);
}
Files.delete(p);
}
}
}
}
Installs the jmod file into the library.
gedit ~/dev/jigsaw-maven-plugin/src/main/java/lh/jigsaw/plugin/JModMojo.java &9. Add RunMojo:
package lh.jigsaw.plugin;
import java.io.File;
import java.io.IOException;
import java.lang.module.ModuleId;
import java.lang.module.ModuleInfo;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.openjdk.jigsaw.JigsawModuleSystem;
import org.openjdk.jigsaw.cli.Librarian;
/**
* Installs the jmod file into the library.<br>
* Remove the module from that library if it already exist before adding the new content.
*
* @requiresProject
* @goal jmod
* @requiresDependencyResolution runtime
* @phase install
*
* @author ludovic
*/
public class JModMojo extends AbstractMojo
{
/**
* library directory
*
* @parameter default-value="${project.build.directory}/library"
* @required
*/
private File libraryDirectory;
/**
* Classes directory.
*
* @parameter expression="${project.build.outputDirectory}"
* @required
* @readonly
*/
private File classesDir;
/**
* module dir
*
* @parameter expression="${project.build.directory}/module/"
* @required
* @readonly
*/
private File moduleDir;
/**
* Module name
*
* @parameter expression="${moduleName}""
* @readonly
*/
private String moduleName;
@Override
public void execute() throws MojoExecutionException, MojoFailureException
{
getLog().info("JModMojo");
try
{
File[] files = moduleDir.listFiles();
if (files == null)
{
throw new MojoExecutionException("no files in <target>/module directory");
}
File moduleFile = null;
for (File f : files)
{
if (f.getName().endsWith("jmod"))
{
moduleFile = f;
break;
}
}
if (moduleFile == null)
{
throw new MojoExecutionException("no jmod file in <target>/module directory");
}
// allow to update the module by removing it, may have to reindex?
ModuleId moduleId = getModuleId();
Path installedModule = libraryDirectory.toPath().resolve(moduleId.name()).resolve(moduleId.version().toString());
if (Files.exists(installedModule))
{
String[] params = new String[]
{
"-L",
libraryDirectory.getAbsolutePath(),
"remove",
"-f",
moduleId.toString()
};
getLog().info(Arrays.toString(params));
Librarian.run(params);
}
String[] params = new String[]
{
"-L",
libraryDirectory.getAbsolutePath(),
"install",
moduleFile.getAbsolutePath()
};
getLog().info(Arrays.toString(params));
Librarian.run(params);
}
catch (MojoExecutionException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new MojoExecutionException("Could not install '" + moduleName + "' into the '" + libraryDirectory + "' library.", ex);
}
}
private String getModuleName() throws MojoExecutionException
{
if (moduleName == null)
{
try
{
Path path = classesDir.toPath().resolve("module-info.class");
byte[] bytes = java.nio.file.Files.readAllBytes(path);
JigsawModuleSystem jms = JigsawModuleSystem.instance();
ModuleInfo mif = jms.parseModuleInfo(bytes);
moduleName = mif.id().name();
getLog().info("module name read from module-info = " + moduleName);
}
catch (IOException ex)
{
throw new MojoExecutionException("Could not read the module name, check that module-info.class exist.", ex);
}
}
return moduleName;
}
private ModuleId getModuleId() throws MojoExecutionException
{
ModuleId id;
try
{
Path path = classesDir.toPath().resolve("module-info.class");
byte[] bytes = java.nio.file.Files.readAllBytes(path);
JigsawModuleSystem jms = JigsawModuleSystem.instance();
ModuleInfo mif = jms.parseModuleInfo(bytes);
id = mif.id();
getLog().info("module name read from module-info = " + moduleName);
}
catch (IOException ex)
{
throw new MojoExecutionException("Could not read the module name, check that module-info.class exist.", ex);
}
return id;
}
}
Runs the project's module from the library.
gedit ~/dev/jigsaw-maven-plugin/src/main/java/lh/jigsaw/plugin/RunMojo.java &10. Compile and install the plugin:
package lh.jigsaw.plugin;
import java.io.File;
import java.io.IOException;
import java.lang.module.ModuleInfo;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.openjdk.jigsaw.JigsawModuleSystem;
/**
* Runs the project's module from the library.
*
* @requiresProject
* @goal run
* @requiresDependencyResolution runtime
*
* @author ludovic
*/
public class RunMojo extends AbstractMojo
{
/**
* library directory
*
* @parameter default-value="${project.build.directory}/library"
* @required
*/
private File libraryDirectory;
/**
* Classes directory.
*
* @parameter expression="${project.build.outputDirectory}"
* @required
* @readonly
*/
private File classesDir;
/**
* Module name
*
* @parameter expression="${moduleName}""
* @readonly
*/
private String moduleName;
/**
* vm args
* @parameter default-value="${vmargs}"
*/
String vmargs;
/**
* args
* @parameter default-value="${args}"
*/
String args;
@Override
public void execute() throws MojoExecutionException, MojoFailureException
{
getLog().info("RunMojo");
try
{
List<String> cmdline = new ArrayList<>();
Path javaCmdDirPath = Paths.get(System.getProperty("java.home"));
Path javaCmdPath = javaCmdDirPath.resolve("bin/java");
cmdline.add(javaCmdPath.toString());
cmdline.add("-L");
cmdline.add(libraryDirectory.toString());
cmdline.addAll(split(vmargs));
cmdline.add("-m");
cmdline.add(getModuleName());
cmdline.addAll(split(args));
ProcessBuilder pb = new ProcessBuilder(cmdline);
System.out.println("cmd: " + pb.command());
pb = pb.inheritIO();
Process p = pb.start();
int ret = p.waitFor();
System.out.println("ret = " + ret);
}
catch (Exception ex)
{
getLog().error(ex);
}
}
private String getModuleName()
{
if (moduleName == null)
{
try
{
Path path = classesDir.toPath().resolve("module-info.class");
byte[] bytes = java.nio.file.Files.readAllBytes(path);
JigsawModuleSystem jms = JigsawModuleSystem.instance();
ModuleInfo mif = jms.parseModuleInfo(bytes);
moduleName = mif.id().name();
System.out.println("name = " + moduleName);
}
catch (IOException ex)
{
getLog().error(ex);
}
}
return moduleName;
}
private List<String> split(String arg)
{
if (arg == null)
{
return Collections.emptyList();
}
String[] elts = arg.split(" ");
return Arrays.asList(elts);
}
}
cd ~/dev/jigsaw-maven-pluginUsing the plugin
mvn install
See Jigsaw: Worldclock with the Maven plugin
Subscribe to:
Posts (Atom)