Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven...

38
Praktikum Softwarearchitektur Apache Maven Klaus-Christian Saalfeld 18. Juni 2011 FernUniversit¨ at in Hagen

Transcript of Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven...

Page 1: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Praktikum Softwarearchitektur

Apache Maven

Klaus-Christian Saalfeld

18. Juni 2011

FernUniversitat in Hagen

Page 2: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Inhaltsverzeichnis

1. Einfuhrung in Maven 1

2. Grundlagen 12.1. Erste Schritte mit Maven . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2. Struktur und Beschreibung eines Projektes . . . . . . . . . . . . . . . . . . 22.3. Build Lifecycles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42.4. Repositories und Dependency Management . . . . . . . . . . . . . . . . . . 52.5. Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3. Exemplarische Anwendung 73.1. Ein ANT Projekt als Fallbeispiel . . . . . . . . . . . . . . . . . . . . . . . . 73.2. Vergleich zwischen ANT und Maven . . . . . . . . . . . . . . . . . . . . . 73.3. Portierung des ANT Projektes . . . . . . . . . . . . . . . . . . . . . . . . . 9

3.3.1. Erzeugung eines neuen Maven Projektes . . . . . . . . . . . . . . . 93.3.2. Hinzufugen der Java Quellen . . . . . . . . . . . . . . . . . . . . . 103.3.3. Portierung der Unit-Tests . . . . . . . . . . . . . . . . . . . . . . . 103.3.4. Hinzufugen der C Quellen . . . . . . . . . . . . . . . . . . . . . . . 123.3.5. Erzeugung eines .jar Archivs . . . . . . . . . . . . . . . . . . . . . . 15

4. Architektur 154.1. Plugin-Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4.1.1. Maven als Plugin-Framework . . . . . . . . . . . . . . . . . . . . . 154.1.2. Entwicklung eines Plugins . . . . . . . . . . . . . . . . . . . . . . . 164.1.3. Integration in den Maven Build . . . . . . . . . . . . . . . . . . . . 18

4.2. Dependency Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.3. Plexus als Dependency Injection Framework . . . . . . . . . . . . . . . . . . 23

5. Zusammenfassung und Ausblick 255.1. Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255.2. Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

A. Anhang 27A.1. build.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27A.2. Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27A.3. JniCompilerPluginMojo.java . . . . . . . . . . . . . . . . . . . . . . . . . . 28A.4. pom.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

Literaturverzeichnis 36

i

Page 3: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

1. Einfuhrung in Maven

Maven (deutsch: Experte) ist ein Build Management System fur Java Projekte. Es kombi-niert Funktionalitat zum Programmbau mit zusatzlichen Aspekten zum Management vonAbhangigkeiten. Maven wird von der Apache Software Foundation als Open Source Softwareentwickelt und unter der Apache Software License lizensiert.

2. Grundlagen

2.1. Erste Schritte mit Maven

Maven kann von der Webseite der Apache Software Foundation heruntergeladen werden. Diejeweils aktuelle Version findet sich auf:

http://maven.apache.org/download.html

Fur alle Beispiele in dieser Ausarbeitung wird Version 3.0.3 benutzt. Fur die Nutzung vonMaven ist die Binar-Distribution (apache-maven-3.0.3-bin.zip) ausreichend.

Zur Installation von Maven wird das heruntergeladene Archiv in ein beliebiges Verzeichnisentpackt. Damit Maven auf der Shell verfugbar ist, muss anschließend das Unterverzeichnisbin zum Suchpfad des Systems hinzugefugt werden. Dazu ist die Umgebungsvariable PATH

entsprechend zu modifizieren.

Da Maven selbst auf Java basiert muss ein Java SDK installiert sein. Ein reines Java Runtime(JRE) ist nicht ausreichend. Fur die Beispiele in dieser Ausarbeitung wird das Java SDKVersion 6 Update 25 verwendet. Dieses kann von der Webseite von Oracle bezogen werden:

http://www.oracle.com/technetwork/java/javase/downloads

Fur gangige Betriebssysteme werden Installer angeboten. Die Installation kann in ein belie-biges Verzeichnis erfolgen. Nach der Installation muss jedoch ggf. die UmgebungsvariableJAVA_HOME angepaßt werden. Diese muss auf das Verzeichnis der Java SDK Installation zei-gen.

Die korrekte Installation von Maven kann auf der Shell mit folgender Eingabe gepruft werden:

mvn --help

Bei einer erfolgreichen Installation fuhrt dies zu der (gekurzten) Ausgabe:

usage: mvn [options] [<goal(s)>] [<phase(s)>]

Options:

-am,--also-make If project list is specified, also

build projects required by the

list

...

1

Page 4: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Uber das Kommando mvn konnen Maven Projekte gebaut und verwaltet werden. Alle, fur diepraktische Nutzung von Maven notwendigen, Operationen lassen sich daruber ausfuhren.

Eine typische Operation ware beispielsweise das Compilieren aller .java Quellen eines Pro-jektes und das anschließende Packen in einem .jar Archiv. Mit Maven wird das, fur einProjekt im aktuellen Verzeichnis, wie folgt erreicht:

mvn package

Maven benotigt Zugang zum Internet. Sofern ein Proxy verwendet wird, ist es notwendig dieKonfiguration von Maven entsprechend anzupassen. Dies geschieht uber einen Eintrag in derDatei settings.xml:

<settings>

<proxies>

<proxy>

<active>true</active>

<protocol>http</protocol>

<host>proxy.company.de</host>

<port>8080</port>

<username>myusername</username>

<password>mypassword</password>

</proxy>

Diese befindet sich im Verzeichnis:

~/.m2/

Vergleiche [Tim O’Brien et al., 2010, A.2.4, Proxies, Seite 248].

2.2. Struktur und Beschreibung eines Projektes

Vergleiche [Vincent Massol et al., 2008, Seite 28], [Tim O’Brien et al., 2008, Kapitel 3.4,Seite 34f] und [Tim O’Brien et al., 2010, Kapitel 3, The Project Object Model, Seite 17ff].

Ein Maven Projekt wird uber das Project Object Model (kurz: POM) beschrieben. Die Be-schreibung erfolgt fur jedes Projekt im XML Format in der Datei pom.xml. Diese kann alsAnalogie zu build.xml (ANT) oder zum Makefile (Make) verstanden werden. Als Unter-schied enthalt sie aber, wie in Kapitel 3.2 noch beschrieben wird, keine Beschreibung derBuild-Schritte, sondern eine rein deklarative Beschreibung des Projektes.

Ein minimales Beispiel1 einer pom.xml Datei kann wie folgt aussehen:

1Vergleiche [Tim O’Brien et al., 2010, Kapitel 3.2.2, The Simplest POM, Seite 22]

2

Page 5: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

<project>

<modelVersion>4.0.0</modelVersion>

<groupId>com.company.project</groupId>

<artifactId>SampleJavaProject</artifactId>

<version>1.0</version>

</project>

Als erste Information enthalt sie die Coordinate des Projektes in Form der Tags groupId,artifactId und version. Die Coordinate dient als eindeutiger Bezeichner fur das Projekt2.Projekte mussen in Maven eindeutig identifizierbar sein, damit das Dependency Managementund die Verwaltung der Maven Repositories funktioniert (siehe Kapitel 2.4).

Die zweite Information in der gezeigten pom.xml Datei ist die Object Model Version, diedurch den Tag modelVersion gegeben ist [Vincent Massol et al., 2008, Seite 29]. Diesewahlt indirekt die Super POM des Projektes. In Maven gibt es fur POMs das Prinzip derVererbung. Jedes POM erbt implizit die Informationen aus dieser Super POM. Dies funk-tioniert analog zur Vererbung in der objektorientierten Programmierung (OOP). Wahrendjedoch in der OOP Felder und Methoden vererbt werden, werden in Maven POM Informa-tionen in Gestalt von XML Daten weitervererbt.

Durch die Vererbung wird das Konzept Convention Over Configuration von Maven unter-stutzt. Dieses wird in [Vincent Massol et al., 2008, Kapitel 1.2.1] beschrieben. Fur Mavenbedeutet es, dass fur alle Einstellungen sinnvolle Standardwerte vorgegeben sind, die erst beiNotwendigkeit geandert werden mussen. Solche Einstellungen werden zum Teil durch Verer-bung aus der Super POM, in die POM des jeweiligen Projektes, implizit ubertragen. Nebendieser impliziten Vererbung aus der Super POM, konnen auch eigene POMs erstellt werden,von denen explizit geerbt werden kann. Ein Beispiel dazu findet sich in [Vincent Massol etal., 2008, Kapitel 3.3].

Das gezeigte Beispiel kann, obwohl es nur das Notigste enthalt, bereits genutzt werden, um einJava Projekt mit Maven zu bauen. Dem Prinzip Convention Over Configuration folgend, istdie Struktur des Projektes dabei durch die Super POM vorgegeben. Die Java Quellen mussen,fur einen erfolgreichen Bau, in das Unterverzeichnis src/main/java3 kopiert werden. Furgewohnlich ist es nicht notwendig und sinnvoll von dieser Vorgabe abzuweichen. Wie folgendesBeispiel zeigt, konnte es bei Bedarf aber getan werden:

<project>

<modelVersion>4.0.0</modelVersion>

<groupId>com.company.project</groupId>

<artifactId>SampleJavaProject</artifactId>

<version>1.0</version>

2Der Sinn des Wortes Coordinate kann, wie in [Tim O’Brien et al., 2008, Seite 45] dargestellt, verstandenwerden: Analog zu einem Punkt in einem Koordinatensystem, kann jedes Projekt im Maven Space durcheine Coordinate eindeutig identifiziert werden.

3Die aus dem Package resultierenden Verzeichnisstrukturen mussen hinzugefugt werden.

3

Page 6: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

<build>

<sourceDirectory>source/java</sourceDirectory>

</build>

</project>

Das Beispiel uberschreibt die Vorgaben aus der Super POM und legt source/java als neuesVerzeichnis fur Java Quellen fest. Das uberschriebene Element ware andernfalls durch dieSuper POM wie folgt definiert worden:

<project>

<build>

<sourceDirectory>src/main/java</sourceDirectory>

2.3. Build Lifecycles

Vergleiche [Tim O’Brien et al., 2010, Kapitel 4, Seite 47ff], [Vincent Massol et al., 2008,Seite 30] und [Tim O’Brien et al., 2008, Kapitel 3.5.2, Seite 38ff].

Ein wichtiges Konzept in Maven entspringt der Beobachtung, dass der Bau eines Projektes inimmer gleichen Schritten mit einer wohldefinierten Reihenfolge erfolgt: Es mussen beispiels-weise erst alle Quellen compiliert werden, bevor diese mit einem Unit-Test getestet werdenkonnen. Erst nachdem der Unit-Test erfolgreich war, kann das Projekt veroffentlicht oderanderen Nutzern zur Verfugung gestellt werden.

Diese Aneinanderreihung von Schritten mit einer fest definierten Reihenfolge wird in Ma-ven als Lifecycle bezeichnet4. Maven ist nicht auf einen einzigen Lifecycle beschrankt - esintegriert standardmaßig die Lifecycles default, clean und site. Die in einem Lifecycleabgearbeiteten Schritte werden Phasen genannt. Die Compilierung der Java Quellen findetbeispielsweise im Lifecycle default in der Phase compile statt5.

Bei der praktischen Arbeit mit Maven wird ublicherweise die auszufuhrende Phase vorgegeben.Es werden dann auch alle Phasen ausgefuhrt, die im Lifecycle vor dieser Phase verankert sind.Um zum Beispiel die Phase compile und alle vorangehenden Phasen auszufuhren, kannfolgendes Kommando verwendet werden:

mvn compile

Die dabei ausgefuhrte Funktionalitat ist nicht fest mit der Phase verbunden. Man kann sichvereinfacht vorstellen, dass Phasen vollig ohne Funktion sind und lediglich als Anknupfungs-punkte fur Funktionalitat dienen. Funktionalitat wird in Form sog. Goals an die Phasen

4Das Wort Cycle (deutsch: Zyklus) kann in diesem Zusammenhang zunachst verwirren, da der Bau eherals Sequenz anzusehen ist, die an einem bestimmten Punkt erfolgreich abgeschlossen und damit beendetist. Ein Zyklus entsteht erst uber die Lebenszeit des Projektes gesehen, da in dieser Zeit mit jedem Baudie Sequenz immer wieder von Neuem durchlaufen wird.

5Eine vollstandige Liste der Phasen ist in [Tim O’Brien et al., 2010, Kapitel 4.1.2, Seite 50f] angegeben.Die Phasen des clean und site Lifecycles sind in [Tim O’Brien et al., 2010, Kapitel 4.1.1, Seite 48ff]beschrieben.

4

Page 7: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

gebunden. Die Goals werden dabei uber Plugins zur Verfugung gestellt. Mehr dazu sieheKapitel 2.5 und 4.1.

Es ist auch moglich, einzelne Goals explizit auszufuhren. Dazu wird das Plugin, wie in folgen-dem Schema gezeigt, mit seiner groupId, artifactId und version vorgegeben und dasauszufuhrende Goal benannt:

mvn groupId:artifactId:version:goal

Vergleiche dazu [Tim O’Brien et al., 2010, Kapitel 11.4.2, A Simple Java Mojo, Seite 186].Um fur ein Projekt Unit Tests auszufuhren, ohne dabei den Lifecycle zu durchlaufen, kannbeispielsweise folgender Aufruf verwendet werden:

mvn org.apache.maven.plugins:maven-surefire-plugin:2.7.2:test

2.4. Repositories und Dependency Management

Softwareprojekte nutzen haufig externe Bibliotheken und Frameworks. Da diese zum Bau desSoftwareprojektes notwendig sind, werden sie auch Dependencies genannt. Fur Java Projek-te stehen diese Dependencies meist als .jar Packages zur Verfugung. Dependencies konnenin unterschiedlichen Versionen vorliegen und ihrerseits weitere Dependencies besitzen (sog.Transitive Dependencies [Tim O’Brien et al., 2010, Kapitel 3.4.4, Transitive Dependencies,Seite 31]). Deshalb kann es in der Praxis schwierig sein, fur ein Softwareprojekt ein korrektesSetup aller Dependencies zu erzeugen. Maven entlastet den Entwickler von dieser Arbeit,indem es das Dependency Management ubernimmt.

In der Praxis funktioniert das Dependency Management, indem in der Datei pom.xml diebenotigten Dependencies des Projektes definiert werden. Download und Verwaltung dieserDependencies (und ggf. weiterer transitiver Dependencies) ubernimmt Maven.

Maven ladt benotigte Dependencies automatisch aus einem Remote Repository herunter6.Das voreingestellte Remote Repository ist:

http://repo1.maven.org/

Die Dependencies werden in einem lokalen Repository abgelegt. Bei zukunftigen Builds wer-den die Dependencies aus dem lokalen Repository verwendet, sodaß sie nicht erneut aus demRemote Depository bezogen werden mussen. Das lokale Repository befindet sich per Defaultim Home Verzeichnis des Benutzers unter:

~/.m2/repository

Ein Beispiel fur eine Dependency ist JUnit. Ein Projekt, das JUnit fur seine Unit Testsbenotigt, kann diese Dependency in der Datei pom.xml angeben:

6Dazu ist eine Internetverbindung erforderlich. Gerade nach einer Erstinstallation wird Maven beim Baueines Projektes eine große Anzahl an Dependencies aus dem Remote Repository herunterladen.

5

Page 8: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

<project>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

Die Dependency muss dazu, wie in Kapitel 2.2 beschrieben, durch ihre Coordinate eindeutigidentifiziert werden. Sofern JUnit noch nicht im lokalen Repository verfugbar ist, wird diegewunschte Version, vor dem Ausfuhren der Tests, zunachst aus dem Remote Repositoryubertragen. Bei der Ausfuhrung der Tests wird der classpath durch Maven dann geeigneterganzt:

...:~/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar

Vertiefende Informationen zum Dependency Management mit Maven finden sich in [TimO’Brien et al., 2010, Kapitel 3.4, Project Dependencies, Seite 27].

2.5. Plugins

Vergleiche [Tim O’Brien et al., 2010, Kapitel 11.2.4, What is a Plugin?]:

Ein großer Teil der Funktionalitat von Maven wird durch Plugins bereitgestellt. Eine Listebereits verfugbarer Plugins findet sich unter:

http://maven.apache.org/plugins/index.html

Plugins fur Maven werden in Java geschrieben und typischerweise mit Maven selbst gebaut7.Außerlich unterscheidet sich ein Plugin nicht von einem ”normalen” Maven Projekt: Fertiggebaut liegt es als .jar Package vor, das in ein Repository installiert und so von anderenMaven Nutzern verwendet werden kann. Zusatzlich zu den compilierten Klassen, enthalt dasPackage lediglich einen Plugin Descriptor, der zusatzliche Informationen fur die Nutzung desPlugins durch Maven liefert.

Ein Plugin stellt ein oder mehrere Goals zur Verfugung. Ein solches Goal kann, wie in Kapitel2.3 beschrieben, an eine Phase im Lifecycle gebunden werden. Wie in Kapitel 4.1 noch gezeigtwird, kann man sich ein Goal auch als Java Methode vorstellen, die von Maven aufgerufenwird. Jedes Goal wird in einer eigenen Klasse implementiert. Da ein Plugin mehrere Goals zurVerfugung stellen kann, kann es mehrere solcher Klassen enthalten. Eine Klasse, die ein Goalimplementiert, wird auch Mojo genannt. Ein Mojo stellt somit genau ein Goal zur Verfugung.

7Maven besitzt fur diesen Zweck ein eigenes Plugin namens maven-plugin-plugin

6

Page 9: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

3. Exemplarische Anwendung

3.1. Ein ANT Projekt als Fallbeispiel

Um den praktischen Umgang mit Maven zu zeigen, soll exemplarisch ein ANT Projekt furMaven portiert werden.

Ein gibt Literatur in welcher der Einstieg in Maven anhand eines Beispiel-Projektes beschrie-ben ist. Insbesondere [Vincent Massol et al., 2008, Kapitel 3, Seite 55ff] soll an dieser Stellegenannt werden. Ein ”Problem” der Arbeiten zu diesem Thema ist jedoch, dass verstandli-cherweise Beispiele gewahlt werden, die optimal fur Maven geeignet sind. In der Praxis istes jedoch haufig die eigentliche Herausforderung, die Grenzen einer Technologie zu kennen,um entscheiden zu konnen, ob sie fur die Losung eines Problems sinnvoll ist oder nicht. Einederartige Abgrenzung wird in der Literatur selten vorgenommen, da primar die Vorteile einerneuen Technologie herausgestellt werden. In dieser Arbeit wurde deshalb ein reales Beispielgewahlt, das an den Randbereichen des sinnvollen Einsatzgebietes von Maven vermutet wird.

Das exemplarisch gewahlte Projekt erganzt Java uber JNI mit Funktionalitat zum Lesen undVerandern der Microsoft Windows Registry. Es hat zwei Bestandteile: Ein in Java erstellterTeil und eine in C geschriebene DLL. Das Projekt wird bisher mit ANT gebaut. Zwar wirddie DLL mit Make erzeugt (siehe Anhang A.2), die entsprechenden Aufrufe werden allerdingsvom ANT Skript (siehe Anhang A.1) delegiert. Insgesamt wird der Bau des Projektes alsouber ANT gesteuert.

3.2. Vergleich zwischen ANT und Maven

Ein wichtiger Aspekt von Maven ist der Programmbau. Da Maven aber auch weitere Funktio-nalitaten beinhaltet, ist es kein reines Tool zum Programmbau wie ANT (oder das klassischeMake). Fur einen Vergleich wird hier deshalb zunachst nur der Aspekt des Programmbausbetrachtet. Um die Unterschiede zu reinen Build-Tools zu verdeutlichen, wird auch kurz dasklassische Make betrachtet. Beim Programmbau unterscheidet sich Maven von ANT undMake:

In ANT und Make werden Ziele und Abhangigkeiten spezifiziert. Fur jedes Ziel werden danndie notwendigen Aktionen beschrieben um es zu erreichen. Als eine grobe Unterscheidungzwischen ANT und Make kann festgestellt werden, dass in ANT die Aktionen (hier Tasksgenannt) abstrakter sind als in Make.

Dies kann an einem kleinen Beispiel verdeutlicht werden. Ein Ziel beim Bau eines Java Projek-tes besteht beispielsweise in der Erzeugung von .class Dateien aus den .java Quelldateien,welche in diesem Fall die Abhangigkeiten darstellen. Eine Losungsmoglichkeit in Make waredie folgende:

.PHONY: all compile

7

Page 10: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

all: .depend compile

.depend:

echo "compile: \\" >.depend

find . -name "*.java" -type f | \

sed -n "s%^\(.*\)\.java.*%\1.class \\\\\\%p" >>.depend

-include .depend

%.class: %.java

javac $<

Das Aquivalent in ANT ist im Folgenden dargestellt:

<project name="SampleJavaProject" default="compile">

<target name="compile">

<javac srcdir="." includeantruntime="false" />

</target>

</project>

Beide Losungen haben offensichtliche Unterschiede8. Als Gemeinsamkeit kann fur beide aberfestgestellt werden, dass die notwendigen Schritte fur einen erfolgreichen Bau des Projektesbeschrieben werden.

Im Gegensatz dazu, wird in Maven das zu bauende Projekt beschrieben. Der Weg, wie einProjekt zu bauen ist, muss nicht angegeben werden. Es gibt demnach auch keine Ziele undAbhangigkeiten. Die notwendigen Schritte fur den erfolgreichen Bau werden von Maven furdas Projekt passend gewahlt und ausgefuhrt.

Ein korrespondierendes Maven Projekt9 (genauer: die Datei pom.xml) sahe wie folgt aus:

<project>

<modelVersion>4.0.0</modelVersion>

<groupId>com.company.project</groupId>

<artifactId>SampleJavaProject</artifactId>

<version>1.0</version>

</project>

Man sieht, dass hier weder einzelne Build-Schritte noch die, dem Projekt zugeordneten,Quelldateien definiert sind. Damit dies funktionieren kann, muss man sich allerdings an dieKonventionen von Maven halten (siehe Kapitel 2.2).

8Das Beispiel zeigt, dass ANT in Bezug auf die Verstandlichkeit Vorteile bringt. Auch Plattformunabhan-gigkeit ist ein weiterer wichtiger Vorteil von ANT - das Makefile dieses Beispiels funktioniert nur aufunixoiden Systemen. Flexibilitat ist hingegen der große Vorteil von Make - beispielsweise steuert es dieUbersetzung der LATEX Quellen dieser Arbeit.

9Vergleiche [Tim O’Brien et al., 2010, Kapitel 3.2.2, Seite 22]

8

Page 11: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

3.3. Portierung des ANT Projektes

3.3.1. Erzeugung eines neuen Maven Projektes

Erster Schritt bei der Portierung ist die Erzeugung eines neuen Maven Projektes. Dies ge-schieht wie folgt:

mvn archetype:create -DgroupId=com.sse.jregedit \

-DartifactId=JRegEdit -Dversion=1.0

Maven erzeugt dadurch ein neues Projekt, das einen minimalen Satz an Beispiel-Dateien ent-halt. Hierbei von Interesse ist lediglich die Datei pom.xml und die erzeugten Verzeichnisse -die restlichen .java Dateien sind Beispiele und konnen geloscht werden. Es ist nicht zwingendein neues Projekt auf diese Weise zu erzeugen. Es ware ebenso moglich gewesen, die notwen-digen Dateien und Verzeichnisse von Hand zu erstellen. Die Datei- und Verzeichnisstruktursollte am Ende lediglich wie folgt aussehen:

JRegEdit / pom.xml

/ src / main / java / com / sse / jregedit

/ test / java / com / sse / jregedit

Der Inhalt der erzeugten pom.xml sieht wie folgt aus:

<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>

<groupId>com.sse.jregedit</groupId>

<artifactId>JRegEdit</artifactId>

<version>1.0</version>

<packaging>jar</packaging>

<name>JRegEdit</name>

<url>http://maven.apache.org</url>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

9

Page 12: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

</dependency>

</dependencies>

</project>

3.3.2. Hinzufugen der Java Quellen

Als zweiter Schritt werden die Java Quellen dem neuen Maven Projekt hinzugefugt. Die JavaQuellen (ohne die Unit-Test Klassen) werden in die Verzeichnisstruktur unterhalb von src

eingefugt. Dies resultiert in folgender Projektstruktur10:

JRegEdit / pom.xml

/ src / main / java / [...] / JRegEdit.java

/ JRegEditException.java

/ JRegEditKeyChangeListener.java

/ JRegEditListenHandle.java

/ JRegEditListenProperties.java

/ test / java / [...] /

Die Quellen konnen nun mit Maven wie folgt compiliert werden:

mvn compile

Die compilierten .class Dateien werden in einer neuen Verzeichnisstruktur gespeichert:

JRegEdit / target / classes / [...] / JRegEdit.class

/ JRegEditException.class

/ JRegEditKeyChangeListener.class

/ JRegEditListenHandle.class

/ JRegEditListenProperties.class

Das Loschen der erzeugten Dateien geschieht mit Maven wie folgt:

mvn clean

3.3.3. Portierung der Unit-Tests

Ein nachster Schritt bei der Portierung ist das Hinzufugen der Klassen fur die Unit-Tests.Maven unterstutzt Unit-Tests mit JUnit als Standard11. Es macht Sinn, sich dieser Konven-tion anzupassen und den proprietaren Unit-Test fur JUnit zu portieren. Dies ermoglicht esjedem Entwickler (ganz im Sinne von Maven) sich schnell in das Projekt einzuarbeiten, davorhandenes Wissen aus anderen Maven Projekten (wie z.B. uber JUnit) wiederverwendetwerden kann. Die Einarbeitung in (unnotige) ”Eigenheiten”des Projektes wie ein proprietarer

10Die aus dem Package Namen com.sse.jregedit resultierenden Verzeichnisse (com/sse/jregedit) wer-den zur besseren Ubersichtlichkeit hier und in den folgenden Ausfuhrungen durch [...] ersetzt.

11In Maven wird diese Funktionalitat uber das Surefire Plugin maven-surefire-plugin realisiert.

10

Page 13: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Unit-Test entfallt in diesem Fall.

Der portierte Unit-Test wird in Form der Klasse JRegEditTest.java in das Projekt ein-gebunden. Die Unit-Test Quellen werden nicht unterhalb von src, sondern unterhalb desVerzeichnisses test eingefugt:

JRegEdit / test / java / [...] / JRegEditTest.java

Um die Tests auszufuhren wird folgendes Kommando verwendet:

mvn test

Auf das Beispiel angewendet, fuhrt das Kommando zur folgenden Ausgabe (gekurzt undaufbereitet):

...

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Running com.sse.jregedit.JRegEditTest

Tests run: 18, Failures: 0, Errors: 18, Skipped: 0,

Time elapsed: 0.078 sec <<< FAILURE!

Results :

Tests in error:

testRegCreateKey(com.sse.jregedit.JRegEditTest):

no jregedit in java.library.path

testRegDeleteKey(com.sse.jregedit.JRegEditTest):

Could not initialize class com.sse.jregedit.JRegEdit

testRegExistsKey(com.sse.jregedit.JRegEditTest):

Could not initialize class com.sse.jregedit.JRegEdit

...

Tests run: 18, Failures: 0, Errors: 18, Skipped: 0

[INFO] ------------------------------------------------

[INFO] BUILD FAILURE

[INFO] ------------------------------------------------

...

Wie hier zu sehen ist, treten beim Test Fehler auf. Der Grund fur diese Fehler liegt in derfehlenden DLL die noch nicht dem neuen Maven Projekt hinzugefugt wurde. Wird diesetestweise in das aktuelle Verzeichnis kopiert12, werden die Unit-Tests bestanden:

...

-------------------------------------------------------

12Es genugt diese in ein Verzeichnis zu legen, welches das System nach DLLs durchsucht.

11

Page 14: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

T E S T S

-------------------------------------------------------

Running com.sse.jregedit.JRegEditTest

Tests run: 18, Failures: 0, Errors: 0, Skipped: 0,

Time elapsed: 4.328 sec

Results :

Tests run: 18, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------

...

Sofern die DLL noch nicht erzeugt vorliegt, kann die Phase test auch explizit ubersprungenwerden. Dies zeigt folgendes Beispiel, das ein Package aus den compilierten Klassen erzeugt,ohne diese zuvor zu testen:

mvn package -Dmaven.test.skip=true

Als Reaktion auf mvn test werden die Java Quellen des Unit-Tests und (soforn notwendig)alle Java Quellen des Projektes compiliert13. Die compilierten Unit-Test Klassen werden ineinem neuen Verzeichnis der Projektstruktur abgelegt:

JRegEdit / target / test-classes / [...] / JRegEditTest.class

/ JRegEditTest$1.class

/ JRegEditTest$2.class

/ JRegEditTest$3.class

Mit der Ausfuhrung der Unit-Tests werden weitere Verzeichnisse erzeugt. In diesen werdenunter anderem die Ergebnisse der Tests gespeichert.

3.3.4. Hinzufugen der C Quellen

Nachdem der Bau der Java Quellen funktioniert, ist ein nachster Schritt, die Erzeugung derDLL in den Build-Prozess zu integrieren. Zunachst werden dazu die C Quellen dem Projekthinzugefugt. Da Maven keine Vorgabe besitzt, wo diese abzulegen sind, muss das Verzeichnisselbst gewahlt werden. Die C Quellen werden wie folgt in die Projektstruktur eingefugt14:

JRegEdit / src / main / native / windows / app

/ jni

/ reg

/ utils

/ win32

13Dies resultiert aus der Tatsache, dass die Phase test im Default Lifecycle nach der Phase compile undtest-compile verankert ist

14Die Namen der .c und .cpp Dateien werden, der Ubersichtlichkeit wegen, nicht dargestellt

12

Page 15: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Wie sich mit dem Kommando mvn compile prufen laßt, hatte das Hinzufugen der Dateiennoch keinen Einfluss auf den Build. Das Ziel ware das gleiche Verhalten zu erhalten wiebei Verwendung des ANT Skriptes (siehe Anhang A.1): Ein Bauen der Java Quellen uberdas Target all fuhrt hier auch zum Compilieren der C Quellen. Alle Bauprodukte werdengemeinsam durch das Target clean wieder entfernt.

Um ein solches Verhalten mit Maven zu erzielen, mussen neue Goals an die Phasen im Life-cycle gebunden werden (siehe Kapitel 2.3). Dies wird durch Modifikation der Datei pom.xmlerreicht. Das Verfahren dazu wird beispielhaft in [Vincent Massol et al., 2008, Kapitel 3.7,Seite 68f] beschrieben und liegt auch der hier vorgestellten Losung zu Grunde.

Um das gleiche Verhalten wie bei Verwendung des ANT Skriptes zu erhalten, kann ein zu-satzliches Goal an die Phase compile im Default Lifecycle gebunden werden, das die Com-pilierung der C Quellen ubernimmt. Ein an clean gebundenes Goal, kann die, aus den CQuellen erzeugten, Bauprodukte wieder entfernen. Die einfachste Losung dafur scheint hierdie Verwendung des Plugins exec-maven-plugin zu sein, welches das Goal exec bereit-stellt. Dieses erlaubt die Ausfuhrung beliebiger Anwendungen15. Dadurch ist es moglich, diegenannten Aufgaben wie bisher an Make zu delegieren.

Es wird dazu der folgende Ausschnitt unterhalb von project ! build ! plugins in dieDatei pom.xml eingefugt:

<plugin>

<groupId>org.codehaus.mojo</groupId>

<artifactId>exec-maven-plugin</artifactId>

<version>1.2</version>

<executions>

<execution>

<id>native-compile</id>

<phase>compile</phase>

<goals>

<goal>exec</goal>

</goals>

<configuration>

<executable>make</executable>

<commandlineArgs>-C ./src/main/native/windows all</commandlineArgs>

</configuration>

</execution>

<execution>

<id>native-clean</id>

<phase>clean</phase>

<goals>

<goal>exec</goal>

</goals>

<configuration>

15Vergleiche http://mojo.codehaus.org/exec-maven-plugin/exec-mojo.html

13

Page 16: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

<executable>make</executable>

<commandlineArgs>-C ./src/main/native/windows clean</commandlineArgs>

</configuration>

</execution>

</executions>

</plugin>

Das Kommando mvn compile fuhrt nun zur Ausgabe (gekurzt und aufbereitet):

...

[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @

JRegEdit ---

[INFO] Compiling 5 source files to D:\JRegEdit\target\classes

[INFO]

[INFO] --- exec-maven-plugin:1.2:exec (native-compile) @ JRegEdit ---

make.exe: Entering directory ‘D:/JRegEdit/src/main/native/windows’

...

g++ -s -shared -static-libgcc -static -mwindows -o jregedit.dll

utils/utils.o win32/win32_utils.o app/reg_key_copy.o

app/reg_key_create.o app/reg_key_delete.o app/reg_key_enum.o

app/reg_key_exists.o app/reg_key_flush.o app/reg_key_listen.o

app/reg_key_map.o app/reg_value_create.o app/reg_value_delete.o

app/reg_value_enum.o app/reg_value_exists.o app/reg_value_get.o

jni/jni_exception.o jni/jni_object.o reg/reg_utils.o

jregedit.o jregedit.res jregedit.def -O3 -Wall -Wextra

make.exe: Leaving directory ‘D:/JRegEdit/src/main/native/windows’

[INFO] --------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] --------------------------------------------------------------

...

Ein anschließendes mvn clean fuhrt zur Ausgabe (gekurzt und aufbereitet):

...

[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @

JRegEdit ---

[INFO] Deleting D:\JRegEdit\target

[INFO]

[INFO] --- exec-maven-plugin:1.2:exec (native-clean) @ JRegEdit ---

make.exe: Entering directory ‘D:/JRegEdit/src/main/native/windows’

...

rm -f utils/utils.o win32/win32_utils.o app/reg_key_copy.o

app/reg_key_create.o app/reg_key_delete.o app/reg_key_enum.o

app/reg_key_exists.o app/reg_key_flush.o app/reg_key_listen.o

app/reg_key_map.o app/reg_value_create.o app/reg_value_delete.o

app/reg_value_enum.o app/reg_value_exists.o app/reg_value_get.o

jni/jni_exception.o jni/jni_object.o reg/reg_utils.o jregedit.o

make.exe: Leaving directory ‘D:/JRegEdit/src/main/native/windows’

14

Page 17: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

[INFO] --------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] --------------------------------------------------------------

...

Bei einem Blick in das ANT Skript (siehe Anhang A.1) fallt auf, dass die Erzeugung der JNIHeader Datei mit Hilfe von javah und die Kopieraktionen noch nicht in pom.xml integriertwurden. Dies ware ebenfalls nach der hier vorgestellten Methode moglich. Man kann aberdaruber streiten, ob die hier vorgestellte Losung dem Grundgedanken von Maven entspricht,da mit dem exec-maven-plugin eigentlich wieder Build-Schritte beschrieben werden - nurwesentlich umstandlicher. Ein JNI Plugin welches den Bau der DLL aus C Quellen ubernimmtware eine sauberere Losung. In Kapitel 4.1 wird ein solcher Ansatz vorgestellt.

3.3.5. Erzeugung eines .jar Archivs

Die bei der Compilierung erzeugten .class Dateien werden uber

mvn package

in einem .jar Archiv gepackt. Als zusatzliche Aufgabe muss diesem die DLL hinzugefugtwerden. Alle Versuche, dies direkt durch Konfiguration von maven-jar-plugin zu errei-chen, blieben ohne Erfolg16. In diesem Fall konnte mit Assemblies gearbeitet werden. MitAssemblies konnen benutzerdefinierte Zusammenstellungen von Dateien als Package erzeugtwerden. Dies funktionierte im Versuch gut, fuhrte allerdings zu weiterer Arbeit, da das er-zeugte Package nicht automatisch mit in das Repository installiert wird. Der Versuch wurdean diesem Punkt deshalb beendet. Zur Losung dieses Problems wird in Kapitel 4.1 ein Pluginentwickelt und beschrieben.

4. Architektur

4.1. Plugin-Architektur

4.1.1. Maven als Plugin-Framework

Ein großer Teil der Funktionalitat wird in Maven durch Plugins bereitgestellt. Man kannMaven deshalb auch als Plugin-Framework ansehen. Um diese Architektur zu verstehen, sollexemplarisch ein neues Plugin fur Maven erstellt werden. An diesem Beispiel wird gezeigt,wie und mit welchen Techniken das Plugin in Maven integriert wird.

16Das Einbinden von Dateien funktioniert offenbar nur unterhalb des classesDirectory. Dieses kann zwarumkonfiguriert werden, dadurch andern sich allerdings auch die Pfade im .jar Archiv.

15

Page 18: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

4.1.2. Entwicklung eines Plugins

Das exemplarisch entwickelte Plugin (siehe Anhang A.3) knupft an den Erkenntnissen ausKapitel 3.3.5 an. Dort wurde die Portierung eines ANT basierten JNI Projektes beschrieben.Es wurde gezeigt, wie ein bestehendes Makefile, das den Bau der C Quellen ubernimmt, inden Maven Build integriert werden kann. Allein mit den verfugbaren ”Bordmitteln”waren abernicht alle Probleme in akzeptabler Zeit losbar. Auch wurde angemerkt, dass die vorgestellteLosung im Sinne von Maven nicht optimal ist. An dieser Stelle wird deshalb zur Losungder Probleme ein JNI Plugin entwickelt, dass den Bau des nativen Teils des JNI Projektesubernimmt.

Ein neues Plugin wird uber den bereits bekannten Archetype Mechanismus wie folgt erzeugt:

mvn archetype:create -DgroupId=com.sse.maven.jni \

-DartifactId=maven-jni-compiler-plugin \

-DarchetypeArtifactId=maven-archetype-mojo

Die entwickelte Plugin-Klasse JniCompilerPluginMojo.java (siehe Anhang A.3) kann an-schließend in die erzeugte Verzeichnisstruktur

\maven-jni-compiler-plugin\src\main\java\com\sse\maven\jni

eingefugt werden. Alle Beispiel-Klassen konnen aus dem Projekt entfernt werden. Das Pluginkann anschließend mit

mvn compile

compiliert werden.

Die Bestandteile eines Maven Plugins werden exemplarisch anhand der entwickelten Plugin-Klasse JniCompilerPluginMojo.java vorgestellt. Diese kann auf folgendes Grundgerustreduziert werden:

package com.sse.maven.jni;

import org.apache.maven.plugin.AbstractMojo;

import org.apache.maven.plugin.MojoExecutionException;

/**

* @goal compile

* @phase compile

*/

public class JniCompilerPluginMojo extends AbstractMojo

{

public void execute() throws MojoExecutionException

{

// ...

}

}

16

Page 19: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Fur jedes Goal enthalt ein Plugin eine Klasse, die direkt oder indirekt das Interface

org.apache.maven.plugin.Mojo

implementiert. Hier geschieht das durch Ableitung von AbstractMojo. Die von einem Goalbereitgestellte Funktionalitat muss uber die Methode execute() implementiert werden. Die-se Methode wird von Maven aufgerufen, um ein Goal auszufuhren. Nicht immer kann ein Goalerfolgreich abgeschlossen werden: Beispielsweise kann ein Syntaxfehler den erfolgreichen Bauder Java Quellen mit dem maven-compiler-plugin verhindern. In solchen Fallen kann dieMethode eine MojoExecutionException werfen. Der Maven Build wird dann mit einemFehler abgebrochen:

[ERROR] Failed to execute goal org.apache.maven.plugins:

maven-compiler-plugin:2.3.2:compile (default-compile) on project ...

Die Klasse AbstractMojo stellt auch ein Log bereit, mit dem eigene Ausgaben erzeugt wer-den konnen.

Vergleiche [Tim O’Brien et al., 2010, Kapitel 11.4.5, Mojo Class Annotations]:

Bei der Klasse fallen Annotationen auf, die nicht mit Javadoc in Zusammenhang stehen.Aus diesen wird automatisch beim Bau des Plugins der Plugin Descriptor erzeugt, welcherals XML Datei in das .jar Package eingebunden wird. Uber die Annotation @goal wirdder Name des Goals festgelegt, welches die Klasse bereitstellt. Die Annotation @phase istoptional und bezeichnet die Phase, an welche das Goal standardmaßig gebunden ist, fallsder Nutzer des Plugins keine explizite Bindung vorgibt. Der Plugin Descriptor findet sich imPackage des Plugins unter:

/META-INF/maven/plugin.xml

Uber die Annotationen werden dem Plugin Descriptor folgende Informationen hinzugefugt:

<plugin>

<mojos>

<mojo>

<goal>compile</goal>

<phase>compile</phase>

</mojo>

Durch die Verwendung von Annotationen muss der Plugin Descriptor nicht manuell erstelltoder angepaßt werden. Grundsatzlich ware dies aber auch moglich.

In vielen Fallen ist es notwendig, im Plugin auf Informationen uber den Build zuzugreifen.Quelle dieser Informationen ist unter anderem die Datei pom.xml eines Projektes17. Der Zu-griff auf diese Daten wird ebenfalls durch Annotationen und damit uber den Plugin Descriptorermoglicht. Der folgende Ausschnitt zeigt beispielhaft den Zugriff auf die artifactId undgroupId eines Projektes:

17Genauer: Die aus Super POM und ggf. anderen POMs gebildete Effective POM. Diese kann man sichdurch das Kommando mvn help:effective-pom anzeigen lassen.

17

Page 20: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

public class JniCompilerPluginMojo extends AbstractMojo

{

/**

* @parameter expression="${project.artifactId}"

* @required

*/

private String artifactId;

/**

* @parameter expression="${project.groupId}"

* @required

*/

private String groupId;

// ...

}

Wird das Goal in einem Projekt verwendet, stehen die artifactId und groupId des Pro-jektes, dem instanziierten Objekt, in den hier gezeigten, gleichnamigen, privaten Feldern zurVerfugung. Im Plugin Descriptor wurden dazu folgende Eintrage erganzt:

<plugin>

<mojos>

<mojo>

<parameters>

<parameter>

<name>artifactId</name>

<type>java.lang.String</type>

<required>true</required>

<editable>true</editable>

<description />

</parameter>

<parameter>

<name>groupId</name>

<type>java.lang.String</type>

<required>true</required>

<editable>true</editable>

<description />

</parameter>

In Kapitel 4.2 wird diese Umsetzung noch einmal genauer betrachtet.

4.1.3. Integration in den Maven Build

Das vorgestellte Plugin kann mit folgendem Kommando compiliert und in das lokale Repo-sitory installiert werden:

mvn install

18

Page 21: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Nachdem das Plugin im lokalen Repository abgelegt wurde, kann es im JNI Projekt verwendetwerden. Dazu wird die pom.xml des JNI Projektes (siehe Anhang A.4) wie folgt erganzt:

<project>

<build>

<plugins>

<plugin>

<groupId>com.sse.maven.jni</groupId>

<artifactId>maven-jni-compiler-plugin</artifactId>

<version>1.0</version>

<executions>

<!-- this binds the JNI compiler plugin to the compile phase -->

<execution>

<phase>compile</phase>

<goals>

<goal>compile</goal>

</goals>

</execution>

Dies bindet das vom Plugin bereitgestellte Goal compile an die compile Phase im DefaultLifecycle. Es wird nun beim Compilieren des JNI Projektes automatisch in der Phase compileausgefuhrt. Das Bauen des JNI Projektes mit

mvn compile

fuhrt dann zu folgender Ausgabe (gekurzt und optisch aufgearbeitet):

...

[INFO] --- maven-jni-compiler-plugin:1.0:compile (default) @ JRegEdit ---

[INFO] javah -jni -classpath "D:\JRegEdit_Maven\target\classes"

-o "D:\JRegEdit_Maven\target\native\windows\JRegEdit_jni.h"

com.sse.jregedit.JRegEdit

...

[INFO] g++ -c

"D:\JRegEdit_Maven\src\main\native\windows\app\reg_key_create.cpp"

-o "D:\JRegEdit_Maven\target\native\windows\app\reg_key_create.o"

-I"D:\JRegEdit_Maven\src\main\native\windows"

-I"D:\Programme\Java\jdk1.6.0_24\include"

-I"D:\Programme\Java\jdk1.6.0_24\include\win32"

-I"D:\JRegEdit_Maven\target\native\windows"

-O3 -Wall -Wextra

...

[INFO] windres -i

"D:\JRegEdit_Maven\src\main\native\windows\jregedit.rc"

--input-format=rc

-o "D:\JRegEdit_Maven\target\native\windows\jregedit.res"

-O coff

...

19

Page 22: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

[INFO] g++ -s -shared -static-libgcc -static

-o "D:\JRegEdit_Maven\target\native\windows\JRegEdit.dll"

"D:\JRegEdit_Maven\target\native\windows\app\reg_key_copy.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_key_create.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_key_delete.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_key_enum.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_key_exists.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_key_flush.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_key_listen.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_key_map.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_value_create.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_value_delete.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_value_enum.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_value_exists.o"

"D:\JRegEdit_Maven\target\native\windows\app\reg_value_get.o"

"D:\JRegEdit_Maven\target\native\windows\jni\jni_exception.o"

"D:\JRegEdit_Maven\target\native\windows\jni\jni_object.o"

"D:\JRegEdit_Maven\target\native\windows\reg\reg_utils.o"

"D:\JRegEdit_Maven\target\native\windows\jregedit.o"

"D:\JRegEdit_Maven\target\native\windows\utils\utils.o"

"D:\JRegEdit_Maven\target\native\windows\win32\win32_utils.o"

"D:\JRegEdit_Maven\target\native\windows\jregedit.res"

"D:\JRegEdit_Maven\src\main\native\windows\JRegEdit.def"

-O3 -Wall -Wextra

[INFO] --------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] --------------------------------------------------------------

...

Es verbleibt ein offener Punkt aus Kapitel 3.3.5: Das Hinzufugen der DLL in das .jar

Archiv. Das entwickelte Plugin bietet dafur eine Losung. Per Konfiguration des ParametersnativeOutputArtifactPlacements in der Datei pom.xml (siehe Anhang A.4) kann dieerzeugte DLL an beliebige Orte im Projekt und im System kopiert werden:

<plugin>

<groupId>com.sse.maven.jni</groupId>

<artifactId>maven-jni-compiler-plugin</artifactId>

<configuration>

<nativeOutputArtifactPlacements>

<nativeOutputArtifactPlacement>

${basedir}

</nativeOutputArtifactPlacement>

<nativeOutputArtifactPlacement>

${project.build.outputDirectory}/com/sse/jregedit/resources

</nativeOutputArtifactPlacement>

</nativeOutputArtifactPlacements>

</configuration>

</plugin>

20

Page 23: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Die DLL wird daruber in die von maven-jar-plugin genutzten Verzeichnisse kopiert, sodaßsie automatisch in das Package eingebunden wird. Durch das Kopieren der DLL in ein Ver-zeichnis, aus dem das System Libraries ladt (hier: ${basedir}), kann auch das Problem desTestens gelost werden (siehe Kapitel 3.3.3). Fur den Test wird dadurch immer die aktuelleVersion der DLL gefunden und genutzt. Ein Problem besitzt das Plugin dann allerdings doch:Der Bau der C Quellen erfolgt, im Vergleich zum originalen Projekt aus Kapitel 3, nicht mehrinkrementell. Eine solche Losung ware deutlich aufwandiger.

4.2. Dependency Injection

In Kapitel 4.1 wurde ein Plugin fur Maven entwickelt und vorgestellt. An diesem Beispielwar zu sehen, dass per XML in der Datei pom.xml definierte Inhalte uber private Felder desPlugins verfugbar waren.

Ein solches Beispiel ist das Feld nativeIncludePaths:

public class JniCompilerPluginMojo extends AbstractMojo

{

/**

* @parameter

*/

private File[] nativeIncludePaths;

// ...

}

Der Inhalt dieses Feldes kann per XML festgelegt werden. Dies geschieht wie folgt:

<project>

<build>

<plugins>

<plugin>

<configuration>

<!--

puts two path names as File objects in nativeIncludePaths

-->

<nativeIncludePaths>

<nativeIncludePath>

${env.JAVA_HOME}/include

</nativeIncludePath>

<nativeIncludePath>

${env.JAVA_HOME}/include/win32

</nativeIncludePath>

</nativeIncludePaths>

Aus Sicht des umgebenden Objektes, ist das Feld, ohne weiteres Zutun, sofort korrekt initia-lisiert. Das Feld ist private und uber keine offentlichen Methoden nach außen verfugbar.

21

Page 24: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Es ist deshalb zunachst offensichtlich, dass es eines speziellen Sprachmittels (Reflection)bedarf, um das Feld wie gesehen zu initialisieren. Es stellt sich daruber hinaus allerdingsdie Frage, welchen Sinn ein solches Vorgehen hat. So ware es durchaus auch denkbar, dassdas Feld vom Objekt selbst initialisiert wird und der Initialwert beispielsweise aus einer ex-ternen Factory bezogen wird. Mit der Antwort auf diese Frage beschaftigt sich dieses Kapitel.

Zunachst jedoch eine Definition: Das gezeigte Prinzip nennt sich Dependency Injection (DI)und die dahinter stehende allgemeine Idee Inversion of Control (IoC). Dependency Injection18

bezeichnet also das Prinzip, dass ein Objekt benotigte Objekte nicht selbst erzeugt, sonderndass diese extern erzeugt und von außen eingefugt werden. Da dabei die Kontrolle uber dieErzeugung aus dem Objekt selbst nach außen verlagert wird, spricht man hierbei von Inver-sion of Control. Frameworks, die dies umsetzen, werden auch Inversion of Control Containergenannt.

Mit Dependency Injection begegnet man Problemen, die sich insbesondere bei großen Softwa-resystemen ergeben konnen: Betrachtet man eine objektorientiere Software zur Laufzeit, sostellt sich diese als ein Netz miteinander verbundener Objekte dar. Es stellt sich die Frage, werdie Dependencies fur diese Objekte erzeugt. Als klassische Moglichkeit erzeugt jedes Objektseine Dependencies selbst. Dies ist oft zu unflexibel. Man kann dann mit Factories arbeiten.Insbesondere beim Testen großer Systeme konnen hierbei aber auch die Grenzen erreichtsein. In solchen Fallen kann man auf Dependency Injection zuruckgreifen, das hier Vorteilebringt: Zur Realisierung von Dependency Injection werden haufig Frameworks verwendet, beiwelchen die Abhangigkeiten in XML Dateien abgelegt sind. Fur Testzwecke konnen daruberAbhangigkeiten leicht und ohne Anderungen im Quellcode getauscht werden. Beispielsweisekann ein via TCP/IP kommunizierendes Objekt gegen ein Test-Objekt (Mock-Objekt) ge-tauscht werden, das gezielt Fehlerfalle simuliert. Auch konnen beliebige Zusammenstellungenvon Objekten leichter realisiert werden.19

Dependency Injection kann auf verschiedene Arten umgesetzt werden. Diese unterscheidensich darin, wie Abhangigkeiten in ein Objekt eingefugt werden. Unter anderem existieren dazufolgenden Moglichkeiten:

• Setter InjectionAbhangigkeiten werden uber eine offentliche Setter Methode in ein Feld ubernommen.

18Zur Erklarung dieser Wortschopfung: Ein Objekt das in einem Feld eine Referenz auf ein anderes Objektbesitzt, ist von dem referenzierten Objekt abhangig: Ohne das referenzierte andere Objekt konnte dasObjekt selbst seine Arbeit typischerweise nicht verrichten. Man spricht deshalb in diesem Fall von einerDependency (deutsch: Abhangigkeit). Wird diese nicht vom Objekt selbst erzeugt sondern von außeneingeschleußt, liegt eine Injection vor.

19Dependency Injection bringt aber nicht nur Vorteile: Da die Identitat von abhangigen Objekten im Quell-code nicht mehr erkennbar ist, kann das Verstandnis der Zusammenhange erschwert werden. Auchsind Kenntnisse uber das Dependency Injection Framework notwendig. Probleme ergeben sich auch furAnalyse-Tools, die auf statischer Ebene arbeiten sowie fur bestimmte Funktionen in Entwicklungsumge-bungen.

22

Page 25: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

• Constructor InjectionAbhangigkeiten werden dem Konstruktor als Parameter bei der Objekt Instanziierungubergeben.

• Field InjectionAbhangigkeiten werden uber Reflection direkt in ein Feld geschrieben.

Eine weiterfuhrende Einfuhrung in Dependency Injection findet sich in Fowler [2004]. Ein kur-zer Vergleich verschiedener Dependency Injection Frameworks kann in Sanitz [2005] gefundenwerden.

4.3. Plexus als Dependency Injection Framework

In Kapitel 4.2 wird Dependency Injection und seine Verwendung in Maven vorgestellt. Mavennutzt ein Framework namens Plexus um Dependency Injection zu realisieren [Tim O’Brien etal., 2010, Kapitel 11.2.1, What is Inversion of Control?]. Das Framework und weiterfuhrendeInformationen finden sich unter:

http://plexus.codehaus.org

Siehe auch [Tim O’Brien et al., 2010, Kapitel 11.2.3, Why Plexus?].

Es kann an dieser Stelle keine komplette Einfuhrung in Plexus erfolgen. Die Verwendung vonPlexus soll aber beispielhaft am Maven 3.0.3 Quellcode gezeigt werden. Es wird hier dergekurzte Ausschnitt aus DefaultMavenPluginManager.java gezeigt, der das Laden vonMojos uber Plexus realisiert:

package org.apache.maven.plugin.internal;

public class DefaultMavenPluginManager // implements...

{

private PlexusContainer container;

public <T> T getConfiguredMojo( Class<T> mojoInterface, ...,

MojoExecution mojoExecution ) // throws...

{

MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();

T mojo;

mojo = container.lookup(

mojoInterface, mojoDescriptor.getRoleHint()

);

populatePluginFields( mojo, mojoDescriptor, ... );

return mojo;

}

}

23

Page 26: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Innerhalb der Methode getConfiguredMojo() wird das Mojo uber ein PlexusContainer

Objekt mittels lookup() geladen. Die Methode populatePluginFields() ubernimmt, mitder Hilfe von Plexus, anschließend die Dependency Injection der Mojo Felder.

Die lookup() Methode ist in Plexus definiert als:

package org.codehaus.plexus;

public class DefaultPlexusContainer // extends... implements...

{

public <T> T lookup( Class<T> type, String roleHint )

throws ComponentLookupException

{

return componentRegistry.lookup(

type, type.getName(), roleHint

);

}

}

Sie erhalt zwei Parameter: Der Parameter type bezeichnet die Klasse oder das Interface desgewunschten Objektes. Mit roleHint wird das Objekt in einer Menge moglicher Kandidatenexakt bestimmt. Hier bestunde die Menge moglicher Kandidaten aus allen Mojo implemen-tierenden Klassen. Uber den Parameter roleHint kann dann, die fur ein bestimmtes Goalbenotigte Mojo Klasse genau bestimmt werden.

Die Funktion getConfiguredMojo() liefert das fertig konstruierte Mojo an den Aufruferzuruck. Dies ist die Methode executeMojo() in der Klasse DefaultBuildPluginMana-

ger.java. Hier wird schließlich die aus Kapitel 4.1.2 bekannte execute() Methode desMojos aufgerufen:

package org.apache.maven.plugin;

public class DefaultBuildPluginManager // implements...

{

private MavenPluginManager mavenPluginManager;

public void executeMojo(

MavenSession session, MojoExecution mojoExecution ) // throws...

{

Mojo mojo = null;

mojo = mavenPluginManager.getConfiguredMojo(

Mojo.class, session, mojoExecution

);

mojo.execute();

}

}

24

Page 27: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

5. Zusammenfassung und Ausblick

5.1. Zusammenfassung

Kapitel 1 stellt Apache Maven als Open Source Build Management System fur Java Projektevor. Ein praktisch orientierter Einstieg in Maven beginnt in Kapitel 2 mit einer Kurzfassungwesentlicher Grundlagen. In Kapitel 3 wird ein exemplarisch gewahltes JNI Projekt von ANTnach Maven portiert. Es werden die Unterschiede zu ANT dargelegt und die Probleme beider Portierung aufgezeigt. Um diese zu losen, geht Kapitel 4 zunachst auf architektonischeAspekte von Maven ein und beschreibt es als Plugin-Framework. Zum erfolgreichen Bau desJNI Projektes wird, darauf aufbauend, ein neues Maven Plugin entwickelt. Zum Verstandnisdes Plugins, werden relevante Techniken (Dependency Injection) und benutzte Frameworks(Plexus) kurz vorgestellt.

5.2. Ausblick

”Write programs that do one thing and do it well.” Wikipedia [2011]

Maven vereint viel Funktionalitat. Erfolgreiche Software erkennt man aber oft an einer schar-fen funktionalen Begrenzung bei einem klar definierten Einsatzzweck. Ein exemplarischesBeispiel fur diese Theorie soll die Mozilla Suite sein. Die Mozilla Suite kombiniert Browser,EMail-Client, Adressbuch und einen HTML Composer. Ihre offizielle Weiterentwicklung wurdevon der Mozilla Foundation jedoch zu Gunsten von Firefox eingestellt - einem reinen Browser.Auch Thunderbird, ein aus der Mozilla Suite isolierter EMail-Client, hat respektablen Erfolg.Als Begrundung fur die offizielle Einstellung der Weiterentwicklung wird genannt:

”Der Hauptgrund fur diese Anderung [die Konzentration auf die Weiterentwick-lung von Firefox und Thunderbird] ist, dass die Akzeptanz von Einzelapplikatio-nen bei den Anwendern als hoher angenommen wurde als die einer komplettenApplikationssuite [...]”20

Die Mozilla Suite wird als unabhangiges Projekt namens SeaMonkey weiterentwickelt21. EinBlick auf eine aktuelle Browserstatistik22 zeigt, dass SeaMonkey aber nur noch marginaleBedeutung hat.

”Rule of Composition: Design programs to be connected to other programs.”Wikipedia [2011]

Ubertragen auf Maven ware insbesondere zu fragen, ob Repository-Verwaltung, DependencyManagement und Build Tool sich separiert nicht erfolgreicher weiterentwickeln konnen als derkombinierte Ansatz von Maven. Dazu ware insbesondere die Annahme zu untersuchen, dassmit zunehmender Kopplung unterschiedlicher Funktionalitaten, die universelle Verwendbarkeit

20http://de.wikipedia.org/wiki/Mozilla_Application_Suite21http://de.wikipedia.org/wiki/Mozilla22http://www.browser-statistik.de/statistiken

25

Page 28: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

einer Losung und damit der Kreis moglicher Einsatzbereiche abnimmt. Es ware zu prufen, obund welche Einschrankungen von Maven durch die Separierung von Funktionalitaten gelostwerden konnten.

”Rule of Modularity: Write simple parts connected by clean interfaces.”Wikipedia[2011]

Beispielsweise konnte die Entscheidung, in Maven ein eigenes Repository zu integrieren, hin-terfragt werden: Praktisch jedes Softwareprojekt benotigt eine Revisionsverwaltung. Diesestellt das Repository fur den Quellcode des Softwareprojekts zur Verfugung23. Da Mavendie Aufgaben einer Revisionsverwaltung nicht ubernimmt, ist auch fur ein Maven Projekteine Revisionsverwaltung erforderlich. Das bedeutet Arbeit mit zwei separaten Repositories,die miteinander synchron gehalten werden mussen. Mogliche Probleme und Konfliktpoten-tiale waren zu untersuchen. Es ware zu prufen, ob das Repository von Maven durch eineSchnittstelle zur Anbindung einer Revisionsverwaltung ersetzt werden konnte.

”Rule of Diversity: Distrust all claims for ”one true way”.” Wikipedia [2011]

Man kann davon ausgehen, dass der ”Maven Way” fur Standard Java Projekte stimmig ist.Kapitel 3.3.5 und 4.1.3 zeigen aber auch die Grenzen auf, bei denen Anpassungen zu einemarbeitsintensiven Unterfangen werden. Es konnte sich als schwierig erweisen, fur ein neuesProjekt einzuschatzen, ob Maven eine Erleichterung oder ein Hindernis bedeutet. WeitereFallstudien konnten bei der Beantwortung dieser Frage helfen.

”Rule of Silence: When a program has nothing surprising to say, it should saynothing.” Wikipedia [2011]

Die Fehlersuche in einem Maven Build Log kann muhsam sein - die Ausgabe nach mvn com-

pile fur das Plugin aus Kapitel 4.1 betragt, wenn es bereits auf dem aktuellen Stand ist,32 Zeilen. Viele Ausgaben dienen kosmetischen Zwecken oder sind fur die Arbeit vollig uner-heblich (Ausfuhrungszeiten, Speicherauslastung). Sie verschleiern aber den Blick auf Fehlerund Warnungen. Mit der Option -q konnen zwar alle Ausgaben bis auf Fehler unterdrucktwerden, allerdings schließt dies Warnungen mit ein. Es konnte untersucht werden, wie eindurch Plugins erweiterbares Framework, trotz der Menge an moglichen Erweiterungen, eineverstandliche Benutzerschnittstelle sicherstellen kann.

23Dies ist eine naturliche Konsequenz aus dem Tatsache, dass eine Revisionsverwaltung die Anderungen unddie Geschichte eines Quellcodeartefakts verwaltet und dazu das Artefakt selbst kennen muss.

26

Page 29: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

A. Anhang

A.1. build.xml

<p r o j e c t name=”JRegEdi t ” d e f a u l t=”a l l ”>

<p r op e r t y name=”base . d i r ” l o c a t i o n=”j a v a ” /><p r op e r t y name=”sou r c e . d i r ” l o c a t i o n=”${ base . d i r }/com/ s s e / j r e g e d i t ” /><p r op e r t y name=”de s t . d i r ” l o c a t i o n=”${ base . d i r }/com/ s s e / j r e g e d i t ” /><p r op e r t y name=”doc . d i r ” l o c a t i o n=”${ base . d i r }/doc ” /><p r op e r t y name=”n a t i v e . d i r ” l o c a t i o n=”n a t i v e /windows ” /><p r op e r t y name=” j a r . f i l e ” l o c a t i o n=”${ base . d i r }/ j r e g e d i t . j a r ” />

<t a r g e t name=” a l l ” depends=”compi le , n a t i v e , j a r , t e s t , doc ” />

<t a r g e t name=”c l e a n ”><d e l e t e i n c l u d e emp t y d i r s=”t r u e ” q u i e t=”t r u e ”>

< f i l e s e t d i r=”${ s ou r c e . d i r } ” i n c l u d e s=”∗∗/∗. c l a s s ” />< f i l e s e t d i r=”${doc . d i r } ” />

</ d e l e t e><d e l e t e f i l e=”${ j a r . f i l e } ” qu i e t=”t r u e ” /><exec e x e c u t a b l e=”make ” d i r=”${ n a t i v e . d i r } ”>

<arg v a l u e=”c l e a n ” /></ exec><d e l e t e f i l e=” j r e g e d i t . d l l ” q u i e t=”t r u e ” /><d e l e t e f i l e=”${ de s t . d i r }/ r e s o u r c e s / j r e g e d i t . d l l ” q u i e t=”t r u e ” />

</ t a r g e t>

<t a r g e t name=”comp i l e ”>< j a v a c s r c d i r=”${ s ou r c e . d i r } ” d e s t d i r=”${ base . d i r } ” i n c l u d e a n t r u n t ime=” f a l s e ” />

</ t a r g e t>

<t a r g e t name=”n a t i v e ” depends=”comp i l e ”><j a vah o u t p u t F i l e=”${ n a t i v e . d i r }/ j r e g e d i t j n i . hpp ”

c l a s sPa t h=”${ base . d i r } ” c l a s s=”com . s s e . j r e g e d i t . JRegEdi t ” /><exec e x e c u t a b l e=”make ” d i r=”${ n a t i v e . d i r } ”>

<arg v a l u e=” a l l ” /></ exec><mkdir d i r=”${ de s t . d i r }/ r e s o u r c e s ” /><copy f i l e=”${ n a t i v e . d i r }/ j r e g e d i t . d l l ” t o d i r=”${ de s t . d i r }/ r e s o u r c e s ” />

</ t a r g e t>

<t a r g e t name=” j a r ” depends=”compi le , n a t i v e , t e s t ”>< j a r j a r f i l e=”${ j a r . f i l e } ”>

< f i l e s e t d i r=”${ base . d i r } ” i n c l u d e s=”∗∗/∗. c l a s s ” />< f i l e s e t d i r=”${ de s t . d i r } ” i n c l u d e s=”MANIFEST .MF” />< f i l e s e t d i r=”${ base . d i r } ” i n c l u d e s=”∗∗/∗. d l l ” />

</ j a r></ t a r g e t>

<t a r g e t name=”t e s t ” depends=”compi le , n a t i v e ”><!�� get l a t e s t b u i l d DLL i n t o p l a c e f o r t e s t i n g ��><copy f i l e=”${ n a t i v e . d i r }/ j r e g e d i t . d l l ” t o d i r=”. ” />< j a v a f a i l o n e r r o r=”t r u e ” f o r k=”t r u e ” c l a s s p a t h=”${ base . d i r } ”

c la s sname=”com . s s e . j r e g e d i t . JRegEd i tUn i tTes t ” /></ t a r g e t>

<t a r g e t name=”doc ”><j a vadoc sou r c epa th=”${ s ou r c e . d i r } ” d e s t d i r=”${doc . d i r } ” packagenames=”com . s s e . j r e g e d i t .∗ ”>

< f i l e s e t d i r=”${ s ou r c e . d i r } ” i n c l u d e s=”∗∗/∗. j a v a ” /></ j avadoc>

</ t a r g e t>

</ p r o j e c t>

A.2. Makefile

RM = �rm �fGCC = g++WINDRES = wind r e s

TARGET = j r e g e d i t

CFLAGS = �O3 �Wall �WextraC INCLUDE PATH = � I ”$ (JAVA HOME)/ i n c l u d e ” � I ”$ (JAVA HOME)/ i n c l u d e /win32 ”

SRCS = $ ( w i l d c a r d ∗/∗ . c ) $ ( w i l d c a r d ∗/∗ . cpp ) $ (TARGET) . cppOBJS = $ ( pa t s ub s t %.cpp , %.o , $ ( p a t s ub s t %.c , %.o , $ (SRCS) ) )

.PHONY: a l l c l e a n

a l l : . depend $ (TARGET) . d l l

# In c l u d e path omi t ted because i t c o n t a i n s a b s o l u t e path names .# I f a make po r t f o r win32 i s used t h i s r e s u l t s i n e r r o r s ( because o f the ”: ”) .. depend :

$ (GCC) �MM $(SRCS) >. depend

27

Page 30: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

� i n c l u d e . depend

$ (TARGET) . d l l : $ (OBJS) $ (TARGET) . r e s $ (TARGET) . de f$ (GCC) �s �sha r ed �s t a t i c � l i b g c c � s t a t i c �mwindows �o $ (TARGET) . d l l $ˆ $ (CFLAGS)

$ (TARGET) . r e s : $ (TARGET) . r c r e s o u r c e . h

%.o : %.c Make f i l e$ (GCC) �c $ (C INCLUDE PATH) �o $@ $< $ (CFLAGS)

%.o : %.cpp Make f i l e$ (GCC) �c $ (C INCLUDE PATH) �o $@ $< $ (CFLAGS)

%. r e s : %. r c Make f i l e$ (WINDRES) � i $< ��i nput�fo rmat=rc �o $@ �O c o f f

c l e a n : :$ (RM) . depend$ (RM) ∗ . r e s$ (RM) $ (OBJS)

A.3. JniCompilerPluginMojo.java

package com . s s e . maven . j n i ;

/∗∗ JNI Compi l e r P l ug i n f o r Apache Maven .∗ Copy r i gh t (C) 2011 Klaus S a a l f e l d∗∗ This program i s f r e e s o f twa r e : you can r e d i s t r i b u t e i t and/ or modi fy∗ i t under the terms o f the GNU Gene ra l Pub l i c L i c e n s e as p u b l i s h e d by∗ the Free So f tware Foundat ion , e i t h e r v e r s i o n 3 o f the L i c en s e , o r∗ ( a t your op t i on ) any l a t e r v e r s i o n .∗∗ This program i s d i s t r i b u t e d i n the hope tha t i t w i l l be u s e f u l ,∗ but WITHOUT ANY WARRANTY; w i thout even the imp l i e d war ran ty o f∗ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the∗ GNU Gene ra l Pub l i c L i c e n s e f o r more d e t a i l s .∗∗ You shou ld have r e c e i v e d a copy o f the GNU Gene ra l Pub l i c L i c e n s e∗ a long wi th t h i s program . I f not , s e e <ht tp ://www. gnu . org / l i c e n s e s />.∗∗/

import org . apache . maven . p l u g i n . Abst ractMojo ;import org . apache . maven . p l u g i n . Mo joExecut i onExcept i on ;

import j a v a . i o . Bu f f e r edReade r ;import j a v a . i o . F i l e ;import j a v a . i o . F i l e F i l t e r ;import j a v a . i o . F i l e I n pu tS t r e am ;import j a v a . i o . F i l eOutputSt ream ;import j a v a . i o . IOExcept i on ;import j a v a . i o . InputSt reamReader ;import j a v a . i o . P r i n tS t r eam ;import j a v a . u t i l . Vecto r ;

/∗∗ On anno t a t i o n s used w i t h i n j a vadoc comments o f t h i s c l a s s :∗∗ goa l :∗ This i s the on l y r e q u i r e d anno t a t i o n which g i v e s a name to t h i s goa l un ique to t h i s p l u g i n .∗∗ phase :∗ This anno t a t i on s p e c i f i e s the d e f a u l t phase f o r t h i s goa l .∗ I f you add an e x e c u t i o n f o r t h i s goa l to a pom . xml and do not s p e c i f y the phase ,∗ Maven w i l l b ind the goa l to the phase s p e c i f i e d i n t h i s anno t a t i o n by d e f a u l t .∗ See ”Maven � The Complete Re f e r en c e ” page 193 .∗/

/∗∗∗ JNI Compi l e r P l ug i n f o r Apache Maven .∗ Suppor t s c omp i l a t i o n o f the n a t i v e pa r t o f Java Nat i v e I n t e r f a c e ( JNI ) p r o j e c t s .∗∗ @goal comp i l e∗∗ @phase comp i l e∗/

p u b l i c c l a s s Jn iComp i l e rP lug inMo jo extends AbstractMojo{

/∗∗∗ Target p r e f i x f o r the n a t i v e main a r t i f a c t .∗ For example the f i l e n ame o f the comp i l ed n a t i v e l i b r a r y i s d e r i v e d from t h i s v a l u e .∗ I t i s bound to the a r t i f a c t I d o f the p r o j e c t .∗∗ @parameter e x p r e s s i o n =”${ p r o j e c t . a r t i f a c t I d }”∗ @requ i r ed∗/

p r i v a t e S t r i n g a r t i f a c t I d ;/∗∗ <p r o j e c t>∗ <groupId>a r t i f a c t I d </groupId>

28

Page 31: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

∗/

/∗∗∗ @parameter e x p r e s s i o n =”${ p r o j e c t . g roup Id }”∗ @requ i r ed∗/

p r i v a t e S t r i n g g roup Id ;/∗∗ <p r o j e c t>∗ <groupId>com . s s e . j r e g e d i t </groupId>∗/

/∗∗∗ The d e f a u l t d i r e c t o r y c o n t a i n i n g the n a t i v e s ou r c e code .∗∗ @parameter e x p r e s s i o n =”${ p r o j e c t . b u i l d . p l u g i n s . p l u g i n . c o n f i g u r a t i o n . n a t i v e S o u r c eD i r e c t o r y }” d e f a u l t�v a l u e=”s r c /

main/ n a t i v e /windows ”∗ @requ i r ed∗/

p r i v a t e F i l e n a t i v e S o u r c eD i r e c t o r y ;/∗∗ <p r o j e c t>∗ <bu i l d>∗ <p l u g i n s>∗ <p lug i n>∗ <c o n f i g u r a t i o n>∗ <na t i v e S ou r c eD i r e c t o r y>s r c /main/ n a t i v e /windows</n a t i v e S ou r c eD i r e c t o r y>∗/

/∗∗∗ Output d i r e c t o r y ( t y p i c a l l y ”/ t a r g e t ”) where gene r a t ed f i l e s s h a l l be p l a c ed .∗∗ @parameter e x p r e s s i o n =”${ p r o j e c t . b u i l d . d i r e c t o r y }”∗ @requ i r ed∗/

p r i v a t e F i l e o u t p u tD i r e c t o r y ;/∗∗ <p r o j e c t>∗ <bu i l d>∗ <d i r e c t o r y>t a r g e t </d i r e c t o r y>∗/

/∗∗∗ This i s the JDK i n s t a l l d i r e c t o r y∗∗ @parameter e x p r e s s i o n =”${ env .JAVA HOME}”∗ @requ i r ed∗/

p r i v a t e F i l e j avaHomeDi rec to ry ;

/∗∗∗ I n c l u d e d i r e c t o r i e s pas sed to n a t i v e c omp i l e r .∗ Each path $x w i l l be added as � I ”$x ” paramete r to the command l i n e .∗ See ”Maven � The Complete Re f e r en c e ” chap t e r 1 1 . 5 . 2 . f o r d e t a i l s on mul t i�va l u ed mojo pa ramete r s .∗ Another s ou r c e i s : h t tp : //maven . apache . org / gu i d e s /min i / gu ide�c o n f i g u r i n g�p l u g i n s . html#Con f i g u r i n g Pa r ame t e r s∗∗ @parameter∗/

p r i v a t e F i l e [ ] n a t i v e I n c l u d eP a t h s ;/∗∗ <p r o j e c t>∗ <bu i l d>∗ <p l u g i n s>∗ <p lug i n>∗ <c o n f i g u r a t i o n>∗ <na t i v e I n c l u d ePa t h s>∗ <na t i v e I n c l u d ePa t h>${ env .JAVA HOME}/ i n c l u d e </na t i v e I n c l u d ePa t h>∗ <na t i v e I n c l u d ePa t h>${ env .JAVA HOME}/ i n c l u d e /win32</na t i v e I n c l u d ePa t h>∗ </na t i v e I n c l u d ePa t h s>∗/

/∗∗∗ D i r e c t o r i e s to which the gene r a t ed n a t i v e l i b r a r y i s cop i ed on s u c c e s s f u l b u i l d .∗ Can be used to put i t i n t o the / t a r g e t / c l a s s e s d i r e c t o r y so tha t i t i s i n c l u d e d i n the . j a r package .∗ Another use i s to copy the l i b r a r y to a system l o c a t i o n where i t i s found by the OS .∗∗ @parameter∗/

p r i v a t e F i l e [ ] n a t i v eOu t pu tA r t i f a c tP l a c emen t s ;

/∗∗∗ Returns an a b b r e v i a t i o n f o r the o p e r a t i n g system runn ing t h i s VM.∗∗ @re tu rn P o s s i b l e r e t u r n v a l u e s i n c l u d e :∗ � windows∗ � l i n u x∗ � mac∗/

p r i v a t e S t r i n g getOS ( ){

S t r i n g os = System . g e tP rope r t y ( ”os . name ”) . toLowerCase ( ) ;i f ( os . i ndexOf ( ”windows ”) != �1)

r e t u r n ”windows ” ;

29

Page 32: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

i f ( os . i ndexOf ( ” l i n u x ”) != �1)r e t u r n ” l i n u x ” ;

i f ( os . i ndexOf ( ”mac ”) != �1)r e t u r n ”mac ”;

// A more comprehens i ve l i s t can be found he r e :// h t tp :// l o p i c a . s o u r c e f o r g e . net / os . html// We do not r e c o g n i z e a l l p o s s i b l e OS and s imp l y r e t u r n a d e f a u l t v a l u e .r e t u r n ”o th e r ” ;

}

/∗∗∗ Execute s a command l i n e i n the g i v en work ing d i r e c t o r y .∗ The con s o l e output o f the command can be r e d i r e c t e d i n t o the maven l o g .∗∗ @param cmd Program to exe cu t e i n c l u d i n g command l i n e arguments .∗ @param d i r Working d i r e c t o r y .∗ I f n u l l the work ing d i r e c t o r y i s i n h e r i t e d from from cu r r e n t p r o c e s s .∗∗ @throws MojoExecut i onExcept i on∗/

p r i v a t e v o i d exec ( S t r i n g cmd , F i l e d i r ) throws MojoExecut i onExcept i on{

t r y{

getLog ( ) . i n f o (cmd) ;/∗∗ This f u n c t i o n i s messed up i n j a v a : I t might hang and lock�up the p r o c e s s .∗ We need to read s t r eams w i t h i n t h r e ad s to avo i d t h i s .∗/

f i n a l Proce s s p r o c e s s = Runtime . getRunt ime ( ) . exec (cmd , n u l l , d i r ) ;

new Thread (new Runnable ( ){

p u b l i c v o i d run ( ){

t r y{

Buf f e r edReade r r e a d e r =new Buf f e r edReade r (

new I nputSt reamReader (p r o c e s s . ge t I npu tS t r eam ( )

)) ;

S t r i n g ou tpu tL i n e ;w h i l e ( n u l l != ( ou tpu tL i n e = r e ad e r . r e adL i n e ( ) ) )

getLog ( ) . i n f o ( ou tpu tL i n e ) ;r e a d e r . c l o s e ( ) ;

}catch ( IOExcept ion e ){

getLog ( ) . e r r o r ( ” I /O e x c e p t i o n r a i s e d ”) ;}

}}) . s t a r t ( ) ;

new Thread (new Runnable ( ){

p u b l i c v o i d run ( ){

t r y{

Buf f e r edReade r r e a d e r =new Buf f e r edReade r (

new I nputSt reamReader (p r o c e s s . g e tE r ro rS t r eam ( )

)) ;

S t r i n g ou tpu tL i n e ;w h i l e ( n u l l != ( ou tpu tL i n e = r e ad e r . r e adL i n e ( ) ) ){

/∗∗ S ince we r e c e i v e a l l messages send to s t d e r r s t ream he re∗ c u r r e n t l i n e read might be a warn ing or an e r r o r .∗ A s imp l e check i s used he r e ( which i s not a lways c o r r e c t ) :∗ I f a l i n e c o n t a i n s ”e r r o r : ” i t i s c o n s i d e r e d to be an e r r o r ,∗ o t h e rw i s e i t s hand led as warn ing .∗/

i f ( ou tpu tL i n e . matches ( ”.∗ e r r o r : .∗ ”) )getLog ( ) . e r r o r ( ou tpu tL i n e ) ; e l s egetLog ( ) . warn ( ou tpu tL i n e ) ;

}r e a d e r . c l o s e ( ) ;

}catch ( IOExcept ion e ){

getLog ( ) . e r r o r ( ” I /O e x c e p t i o n r a i s e d ”) ;}

}}) . s t a r t ( ) ;

t r y

30

Page 33: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

{i n t r e s u l t = p r o c e s s . wa i tFo r ( ) ;i f (0 != r e s u l t )

throw new MojoExecut i onExcept i on ( ”Ex i t s t a t u s ” + S t r i n g . va lueOf ( r e s u l t ) + ” r e t u r n e d ”) ;}catch ( I n t e r r u p t e dE x c e p t i o n e ){}

}catch ( IOExcept i on e ){

throw new MojoExecut i onExcept i on ( ”E r r o r i n v o k i n g ’ ” + cmd + ” ’ ”) ;}

}

/∗∗∗ Returns a c o l l e c t i o n o f f i l e s c on t a i n ed wi th the d i r e c t o r y ”d i r ”∗ t ha t have the f i l e e x t e n s i o n g i v en by ” s u f f i x ”.∗ S u b d i r e c t o r i e s a r e i n c l u d e d i n the s e a r c h .∗∗ @param d i r D i r e c t o r y to s e a r c h w i t h i n .∗ @param s u f f i x S u f f i x o f the f i l e s to r e t u r n .∗∗ @re tu rn A c o l l e c t i o n o f f i l e s found .∗ I f no f i l e s have been found the c o l l e c t i o n i s empty .∗/

p r i v a t e Vector<F i l e> g e tF i l e s Fo rType ( F i l e d i r , S t r i n g s u f f i x ){

f i n a l Vector<F i l e> r e s u l t = new Vector<F i l e >() ;f i n a l S t r i n g ex t = s u f f i x . toLowerCase ( ) ;F i l e [ ] f i l e s = d i r . l i s t F i l e s (

new F i l e F i l t e r ( ){

@Over r idep u b l i c boolean accep t ( F i l e f i l e F o u n d ){

i f ( f i l e F o u n d . i s D i r e c t o r y ( ) ){

r e s u l t . addA l l ( g e tF i l e s Fo rTyp e ( f i l e Found , e x t ) ) ;}

e l s e{

i f ( f i l e F o u n d . getName ( ) . toLowerCase ( ) . endsWith ( ex t ) )r e t u r n t r u e ;

}r e t u r n f a l s e ;

}}

) ;i f ( n u l l != f i l e s )

f o r ( i n t i =0; i < f i l e s . l e n g t h ; ++i )r e s u l t . add ( f i l e s [ i ] ) ;

r e t u r n r e s u l t ;}

/∗∗∗ Maps the g i v en d i r e c t o r y ”d i r ” tha t has a pa r en t d i r e c t o r y ”sou r c e ”∗ to a new path hav ing the pa r en t d i r e c t o r y ”t a r g e t ”.∗∗ @param d i r D i r e c t o r y to map .∗ @param sou r c e A pa r en t d i r e c t o r y o f ”d i r ”.∗ @param t a r g e t Parent d i r e c t o r y o f the new mapped d i r e c t o r y .∗∗ @re tu rn The new mapped d i r e c t o r y hav ing∗ the pa r en t d i r e c t o r y ”t a r g e t ”.∗/

p r i v a t e F i l e mapDir ( F i l e input , F i l e source , F i l e t a r g e t ){

S t r i n g d i r = i npu t . ge tAbso lu t ePath ( ) ;S t r i n g s r c = sou r c e . ge tAbso lu t ePath ( ) ;

F i l e r e s u l t = t a r g e t ;// qu i ck check by s t r i n g compare : i s ”s ou r c e ” a pa r en t d i r e c t o r y o f ”i npu t ”i f ( d i r . s t a r t sW i t h ( s r c ) ){

// check more p r e c i s e : i s ”s ou r c e ” r e a l l y a pa r en t d i r e c t o r y o f ”i npu t ”w h i l e ( ! i n pu t . e qua l s ( s ou r c e ) ){

i f ( n u l l == ( i npu t = i npu t . g e t P a r e n t F i l e ( ) ) )r e t u r n t a r g e t ;

}r e s u l t =

new F i l e (t a r g e t . g e t A b s o l u t e F i l e ( ) +System . g e tP r ope r t y ( ” f i l e . s e p a r a t o r ”) +d i r . s u b s t r i n g ( s r c . l e n g t h ( ) , d i r . l e n g t h ( ) )

) ;}r e t u r n r e s u l t ;

}

/∗∗

31

Page 34: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

∗ Takes each F i l e e l ement i n the g i v en c o l l e c t i o n ,∗ matches i t by the s p e c i f i e d r e g u l a r e x p r e s s i o n and∗ s u b s t i t u t e s tho s e matches u s i n g the g i v en r ep l a cement s t r i n g .∗∗ @param f i l e s C o l l e c t i o n o f F i l e o b j e c t s to s u b s t i t u t e .∗ The con t en t s o f t h i s c o l l e c t i o n i s r e p l a c e d by t h i s method .∗ @param regex Regu la r e x p r e s s i o n a p p l i e d to each f i l e n ame .∗ Mu l t i p l e matches i n a s i n g l e f i l e n ame a r e s u b s t i t u t e d .∗ @param r e p l a c e Replacement f o r a l l o c c u r r e n c e s found .∗/

p r i v a t e v o i d subs tRegex ( Vector<F i l e> f i l e s , S t r i n g regex , S t r i n g r e p l a c e ){

f o r ( i n t i = 0 ; i < f i l e s . s i z e ( ) ; ++i ){

f i l e s . s e t ( i , subs tRegex ( f i l e s . ge t ( i ) , regex , r e p l a c e ) ) ;}

}

/∗∗∗ Matches ” f i l e ” w i th g i v en ”r egex ” and s u b s t i t u t e s each match a g a i n s t ”r e p l a c e ”.∗ The r e s u l t i s r e t u r n e d to the c a l l e r .∗∗ @param f i l e F i l e to match∗ @param regex Regex to match wi th∗ @param r e p l a c e Replacement f o r each match∗∗ @re tu rn New F i l e o b j e c t c o n t a i n i n g r ep l a c emen t s∗/

p r i v a t e F i l e subs tRegex ( F i l e f i l e , S t r i n g regex , S t r i n g r e p l a c e ){

r e t u r n new F i l e ( f i l e . g e tAbso lu t ePath ( ) . r e p l a c e A l l ( regex , r e p l a c e ) ) ;}

/∗∗∗ Returns the f i l e e x t e n s i o n used f o r dynamic l i b r a r i e s on the a c t i v e OS .∗ For Windows t h i s i s ”. d l l ” and f o r Unix based sys tems ”. so ”.∗∗ @re tu rn F i l e e x t e n s t i o n f o r dynamic l i b r a r i e s .∗/

p r i v a t e S t r i n g g e t L i b F i l e E x t ( ){

i f ( getOS ( ) . e qu a l s ( ”windows ”) )r e t u r n ” . d l l ” ;

r e t u r n ” . so ” ;}

/∗∗∗ Cop ie s the g i v en f i l e to ano the r d i r e c t o r y o v e r w r i t i n g any e x i s t i n g f i l e .∗ An e x c e p t i o n i s thrown i f t h e r e were prob lems copy ing the f i l e .∗∗ @param s o u r c e F i l e F i l e to copy∗ @param t a r g e tD i r e c t o r y E x i s t i n g d i r e c t o r y to copy the s ou r c e f i l e i n t o .∗ A f i l e hav ing the same name as the f i l e to copy i s o v e rw r i t t e n .∗/

p r i v a t e v o i d f o r c e F i l e C o p y ( F i l e s o u r c e F i l e , F i l e t a r g e tD i r e c t o r y ) throws MojoExecut i onExcept i on{

F i l e t a r g e t F i l e = new F i l e (t a r g e tD i r e c t o r y . ge tAbso lu t ePath ( ) +System . g e tP r ope r t y ( ” f i l e . s e p a r a t o r ”) +s o u r c e F i l e . getName ( )

) ;t r y{

i f ( t a r g e t F i l e . e x i s t s ( ) ){

t a r g e t F i l e . d e l e t e ( ) ;}t a r g e t F i l e . c r e a t eNewF i l e ( ) ;

F i l e I n pu tS t r e am f i l e R e a d e r = new F i l e I n pu tS t r e am ( s o u r c e F i l e ) ;F i l eOutputSt ream f i l eW r i t e r = new F i l eOutputSt ream ( t a r g e t F i l e ) ;/∗∗ Copy f i l e data i n 1k b l o c k s i n t o t a r g e t F i l e∗/

byte [ ] b u f f e r = new byte [ 1 0 2 4 ] ;i n t s i z e ;w h i l e (�1 != ( s i z e = f i l e R e a d e r . r ead ( bu f f e r , 0 , b u f f e r . l e n g t h ) ) ){

f i l eW r i t e r . w r i t e ( b u f f e r , 0 , s i z e ) ;}

f i l eW r i t e r . c l o s e ( ) ;f i l e R e a d e r . c l o s e ( ) ;

}catch ( Excep t i on e ){

throw new MojoExecut i onExcept i on (”Unable to copy ’ ” + s o u r c e F i l e . t o S t r i n g ( ) + ” ’ to ’ ” + t a r g e tD i r e c t o r y . t o S t r i n g ( ) + ” ’ ”

) ;}

}

/∗∗

32

Page 35: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

∗ Ca l l e d by Maven to ex e cu t e t h i s Mojo .∗ See ”Maven � The Complete Re f e r en c e ” chap t e r 1 1 . 4 . 6 . ( page 193) f o r d e t a i l s .∗∗ Implements e x e cu t e ( ) d e f i n e d by ”org . apache . maven . p l u g i n . Mojo ” i n t e r f a c e∗/

@Over r idep u b l i c v o i d ex e cu t e ( ) throws MojoExecut i onExcept i on{

t r y{

/∗∗ I f t h e r e were no cus tomized i n c l u d e paths s p e c i f i e d make∗ d e f a u l t path i n c l u d e the JNI header f i l e d i r e c t o r i e s o f JDK .∗/

i f ( n u l l == na t i v e I n c l u d eP a t h s )n a t i v e I n c l u d eP a t h s = new F i l e [ ] {

new F i l e ( j avaHomeDi rec to ry . t o S t r i n g ( ) + ”/ i n c l u d e ”) ,new F i l e ( j avaHomeDi rec to ry . t o S t r i n g ( ) + ”/ i n c l u d e /win32 ”)

} ;

/∗∗ check i f n a t i v e s ou r c e d i r e c t o r y i s p r e s e n t∗/

i f ( ! n a t i v e S o u r c eD i r e c t o r y . e x i s t s ( ) )throw new MojoExecut i onExcept i on ( ”Nat i v e s ou r c e d i r e c t o r y not p r e s e n t ”) ;

/∗∗ Crea te the OS dependent output d i r e c t o r y .∗ This i s the ” r e a l ” base d i r e c t o r y o f comp i l ed s o u r c e s .∗ I t i n c l u d e s the OS dependent s u b d i r e c t o r y .∗∗ For example : / t a r g e t / n a t i v e /windows∗/F i l e n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm =

new F i l e (o u t p u tD i r e c t o r y . ge tAbso lu t ePath ( ) +System . g e tP r ope r t y ( ” f i l e . s e p a r a t o r ”) +”n a t i v e ” +System . g e tP r ope r t y ( ” f i l e . s e p a r a t o r ”) +getOS ( )

) ;i f ( ! n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm . e x i s t s ( ) ){

i f ( ! n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm . mkd i r s ( ) )throw new MojoExecut i onExcept i on ( ”Unable to c r e a t e d i r e c t o r y ” +

na t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm . t o S t r i n g ( ) ) ;}

e l s e{

i f ( n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm . i s F i l e ( ) )throw new MojoExecut i onExcept i on ( ”Name o f e x i s t i n g f i l e e qu a l s output d i r e c t o r y ”) ;

}

/∗∗ Crea te JNI heade r i n t e r f a c e f i l e∗/F i l e j a v aTa r g e tD i r e c t o r y = new F i l e ( o u t p u tD i r e c t o r y + System . g e tP r op e r t y ( ” f i l e . s e p a r a t o r ”) + ”c l a s s e s ”) ;i f ( ! j a v aTa r g e tD i r e c t o r y . e x i s t s ( ) )

throw new MojoExecut i onExcept i on ( ”Output d i r e c t o r y ’ ” + j a v aTa r g e tD i r e c t o r y + ” ’ does not e x i s t ”) ;

F i l e j a v a I n t e r f a c e C l a s s = new F i l e ( g roup Id + ”. ” + a r t i f a c t I d ) ;F i l e n a t i v e I n t e r f a c eH e a d e r F i l e = new F i l e (

n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm +System . g e tP r ope r t y ( ” f i l e . s e p a r a t o r ”) +a r t i f a c t I d + ” j n i . h ”

) ;

exec (S t r i n g . fo rmat (

”j a vah � j n i �c l a s s p a t h \”%s \” �o \”%s \” %s ” ,j a v aTa r g e tD i r e c t o r y ,n a t i v e I n t e r f a c eH e a d e r F i l e ,j a v a I n t e r f a c e C l a s s

) ,j a v aTa r g e tD i r e c t o r y

) ;

// get a l l s ou r c e f i l e sVector<F i l e> n a t i v e S o u r c e F i l e s = new Vector<F i l e >() ;n a t i v e S o u r c e F i l e s . addA l l ( g e tF i l e s Fo rType ( n a t i v e S ou r c eD i r e c t o r y , ” . cpp ”) ) ;n a t i v e S o u r c e F i l e s . addA l l ( g e tF i l e s Fo rType ( n a t i v e S ou r c eD i r e c t o r y , ” . c ”) ) ;

/∗∗ Cons t ruc t c o l l e c t i o n o f n a t i v e t a r g e t ( output ) f i l e s .∗ These a r e d e r i v e d from the n a t i v e s ou r c e f i l e s .∗ We c r e a t e a l l f i l e s i n advance because we need∗ a l l t ho s e f i l e s i n the f i n a l l i n k s t ep .∗/

Vector<F i l e> n a t i v e T a r g e t F i l e s = new Vector<F i l e >() ;f o r ( i n t i = 0 ; i < n a t i v e S o u r c e F i l e s . s i z e ( ) ; ++i ){

n a t i v e T a r g e t F i l e s . add (mapDir (

33

Page 36: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

n a t i v e S o u r c e F i l e s . ge t ( i ) ,n a t i v e S ou r c eD i r e c t o r y ,n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm

)) ;

}subs tRegex ( n a t i v eT a r g e t F i l e s , ” . c ( pp ) ?$ ” , ” . o ”) ;

/∗∗ Cons t ruc t i n c l u d e path :∗ At l e a s t we i n c l u d e n a t i v e s ou r c e and t a r g e t d i r e c t o r i e s .∗/S t r i n gB u f f e r i n c l u d e = new S t r i n gB u f f e r ( ) ;i n c l u d e . append ( S t r i n g . fo rmat ( ”� I \”%s \” ” , n a t i v e S o u r c eD i r e c t o r y . ge tAbso lu t ePath ( ) ) ) ;f o r ( i n t i = 0 ; i < n a t i v e I n c l u d eP a t h s . l e n g t h ; ++i ){

i n c l u d e . append ( S t r i n g . fo rmat ( ”� I \”%s \” ” , n a t i v e I n c l u d eP a t h s [ i ] . g e tAbso lu t ePath ( ) ) ) ;}i n c l u d e . append ( S t r i n g . fo rmat ( ”� I \”%s \”” , n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm ) ) ;

// run comp i l e r to g en e r a t e t a r g e t f i l e sf o r ( i n t i = 0 ; i < n a t i v e S o u r c e F i l e s . s i z e ( ) ; ++i ){

// f i r s t en su r e tha t t a r g e t d i r e c t o r y e x i s t s then i n voke comp i l e rn a t i v e T a r g e t F i l e s . ge t ( i ) . g e t P a r e n t F i l e ( ) . mkd i r s ( ) ;exec (

S t r i n g . fo rmat (”g++ �c \”%s \” �o \”%s \” %s �O3 �Wall �Wextra ” ,n a t i v e S o u r c e F i l e s . ge t ( i ) ,n a t i v e T a r g e t F i l e s . ge t ( i ) ,i n c l u d e . t o S t r i n g ( )

) ,n a t i v e S o u r c eD i r e c t o r y

) ;}

/∗∗ Compi le r e s o u r c e f i l e s ( . r c ) t ha t may be needed on Windows p l a t f o rm .∗/

Vector<F i l e> r e s o u r c e s = ge tF i l e s Fo rType ( n a t i v e S ou r c eD i r e c t o r y , ” . r c ”) ;f o r ( i n t i = 0 ; i < r e s o u r c e s . s i z e ( ) ; ++i ){

F i l e f i l e = mapDir (r e s o u r c e s . ge t ( i ) ,n a t i v e S ou r c eD i r e c t o r y ,n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm

) ;f i l e = subs tRegex ( f i l e , ” . r c$ ” , ” . r e s ”) ;n a t i v e T a r g e t F i l e s . add ( f i l e ) ;f i l e . g e t P a r e n t F i l e ( ) . mkd i r s ( ) ;exec (

S t r i n g . fo rmat (”w ind r e s � i \”%s \” ��i nput�fo rmat=rc �o \”%s \” �O c o f f ” ,r e s o u r c e s . ge t ( i ) ,f i l e

) ,n a t i v e S o u r c eD i r e c t o r y

) ;}

/∗∗ L ink t o g e t h e r a l l p r e v i o u s l y g ene r a t ed o b j e c t f i l e s and r e s o u r c e f i l e s .∗ This i s the f i n a l l i n k i n g s t ep .∗ As r e s u l t a dynamic l i n k l i b r a r y ( . d l l ) o r a sha r ed o b j e c t ( . so ) i s c r e a t e d .∗/

S t r i n g t a r g e t P r e f i x = n a t i v e S o u r c eD i r e c t o r y +System . g e tP r ope r t y ( ” f i l e . s e p a r a t o r ”) +a r t i f a c t I d ;

F i l e t a r g e t L i b r a r y = mapDir (new F i l e ( t a r g e t P r e f i x + g e t L i b F i l e E x t ( ) ) ,n a t i v e S ou r c eD i r e c t o r y ,n a t i v eOu tpu tD i r e c t o r yFo rP l a t f o rm

) ;

S t r i n gB u f f e r o b j F i l e s = new S t r i n gB u f f e r ( ) ;f o r ( i n t i = 0 ; i < n a t i v e T a r g e t F i l e s . s i z e ( ) ; ++i ){

o b j F i l e s . append ( ”\””) ;o b j F i l e s . append ( n a t i v e T a r g e t F i l e s . ge t ( i ) ) ;o b j F i l e s . append ( ”\” ”) ;

}exec (

S t r i n g . fo rmat (”g++ �s �sha r ed �s t a t i c � l i b g c c � s t a t i c �o \”%s \” %s \”%s \” �O3 �Wall �Wextra ” ,t a r g e t L i b r a r y ,o b j F i l e s ,new F i l e ( t a r g e t P r e f i x + ”. de f ”)

) ,n a t i v e S o u r c eD i r e c t o r y

) ;

/∗

34

Page 37: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

∗ The n a t i v e l i b r a r y i s c r e a t e d and now we copy i t i n t o t a r g e t l o c a t i o n ( s ) .∗/

i f ( n u l l != na t i v eOu t pu tA r t i f a c tP l a c emen t s ){

f o r ( i n t i = 0 ; i < na t i v eOu t pu tA r t i f a c tP l a c emen t s . l e n g t h ; ++i ){

na t i v eOu t pu tA r t i f a c tP l a c emen t s [ i ] . mkd i r s ( ) ;f o r c e F i l e C o p y ( t a r g e t L i b r a r y , n a t i v eOu t pu tA r t i f a c tP l a c emen t s [ i ] ) ;

}}

}catch ( Mo joExecut i onExcept i on e ){

getLog ( ) . e r r o r ( e . getMessage ( ) ) ;throw e ;

}}

}

A.4. pom.xml

<p r o j e c t><mode lVe r s i on>4 . 0 . 0</mode lVe r s i on>

<g roup Id>com . s s e . j r e g e d i t</ g roup Id><a r t i f a c t I d>JRegEdi t</ a r t i f a c t I d><v e r s i o n>1 .0</ v e r s i o n><packag ing> j a r</ packag ing>

<name>JRegEdi t</name><u r l>h t t p : //maven . apache . org</ u r l>

<p r o p e r t i e s><p r o j e c t . b u i l d . sou r ceEncod ing>UTF�8</ p r o j e c t . b u i l d . sou r ceEncod ing>

</ p r o p e r t i e s>

<dependenc i e s><dependency>

<g roup Id> j u n i t</ g roup Id><a r t i f a c t I d> j u n i t</ a r t i f a c t I d><v e r s i o n>3 . 8 . 1</ v e r s i o n><scope> t e s t</ scope>

</ dependency></ dependenc i e s>

<b u i l d><p l u g i n s>

<p l u g i n><g roup Id>com . s s e . maven . j n i</ g roup Id><a r t i f a c t I d>maven�j n i�comp i l e r�p l u g i n</ a r t i f a c t I d><v e r s i o n>1 .0</ v e r s i o n><c o n f i g u r a t i o n>

<na t i v eOu t pu tA r t i f a c tP l a c emen t s><na t i v eOu tpu tA r t i f a c tP l a c emen t>

${ b a s e d i r }</ na t i v eOu tpu tA r t i f a c tP l a c emen t><na t i v eOu tpu tA r t i f a c tP l a c emen t>

${ p r o j e c t . b u i l d . o u t p u tD i r e c t o r y }/com/ s s e / j r e g e d i t / r e s o u r c e s</ na t i v eOu tpu tA r t i f a c tP l a c emen t>

</ na t i v eOu t pu tA r t i f a c tP l a c emen t s></ c o n f i g u r a t i o n><e x e c u t i o n s>

<!�� t h i s b i nd s the JNI c omp i l e r p l u g i n to the comp i l e phase ��><e x e c u t i o n>

<phase>comp i l e</ phase><go a l s>

<goa l>comp i l e</ goa l></ go a l s>

</ e x e c u t i o n></ e x e c u t i o n s>

</ p l u g i n></ p l u g i n s>

</ b u i l d>

</ p r o j e c t>

35

Page 38: Apache Maven - klaus-saalfeld.de · Apache Maven Klaus-Christian Saalfeld 1. Einf uhrung in Maven Maven (deutsch: Experte) ist ein Build Management System f ur Java Projekte. Es kombi-

Apache Maven Klaus-Christian Saalfeld

Literaturverzeichnis

[Apache Software Foundation 2010] Apache Software Foundation: Apache Maven UserGuide. 2010-09-05. The Apache Software Foundation, September 2010

[Fowler 2004] Fowler, Martin: Inversion of Control Containers and the Dependency Injec-tion pattern. In: Martin Fowlers Website (2004), January. – http://martinfowler.

com/articles/injection.html

[Li 2006] Li, Sing: Introduction to Apache Maven 2. Wrox Press, December 2006

[Sanitz 2005] Sanitz, Sebastian: Dependency Injection. In: Vortrag Fachbereich InformatikUni Hamburg (2005), September. – http://swt-www.informatik.uni-hamburg.de/

attachments/LVTermine/DependencyInjection20051207.pdf

[Tim O’Brien et al. 2008] Tim O’Brien et al.: Maven: The Definitive Guide. 0.3. SonatypeInc., January 2008. – http://www.sonatype.com

[Tim O’Brien et al. 2010] Tim O’Brien et al.: Maven: The Complete Reference. 0.3.1.Sonatype Inc., January 2010. – http://www.sonatype.com

[Vincent Massol et al. 2008] Vincent Massol et al.: Better Builds with Maven. The How-toGuide for Maven 2.0. 1.7.0. Exist Global, July 2008

[Wikipedia 2011] Wikipedia: Unix philosophy. In: Wikipedia (2011), June. – http:

//en.wikipedia.org/wiki/Unix_philosophy

36