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

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

Embed Size (px)

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

  • Praktikum Softwarearchitektur

    Apache Maven

    Klaus-Christian Saalfeld

    18. Juni 2011

    FernUniversitat in Hagen

  • 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

  • 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 anschlieend das Unterverzeichnisbin zum Suchpfad des Systems hinzugefugt werden. Dazu ist die Umgebungsvariable PATHentsprechend 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 angepat 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] [] []

    Options:

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

    build projects required by the

    list

    ...

    1

    http://maven.apache.org/download.htmlhttp://www.oracle.com/technetwork/java/javase/downloads

  • 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 anschlieende 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:

    true

    http

    proxy.company.de

    8080

    myusername

    mypassword

    Diese befindet sich im Verzeichnis:

    ~/.m2/

    Vergleiche [Tim OBrien 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 OBrien et al., 2008, Kapitel 3.4,Seite 34f] und [Tim OBrien 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 OBrien et al., 2010, Kapitel 3.2.2, The Simplest POM, Seite 22]

    2

  • Apache Maven Klaus-Christian Saalfeld

    4.0.0

    com.company.project

    SampleJavaProject

    1.0

    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:

    4.0.0

    com.company.project

    SampleJavaProject

    1.0

    2Der Sinn des Wortes Coordinate kann, wie in [Tim OBrien 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

  • Apache Maven Klaus-Christian Saalfeld

    source/java

    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:

    src/main/java

    2.3. Build Lifecycles

    Vergleiche [Tim OBrien et al., 2010, Kapitel 4, Seite 47ff], [Vincent Massol et al., 2008,Seite 30] und [Tim OBrien 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 standardmaig 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 OBrien et al., 2010, Kapitel 4.1.2, Seite 50f] angegeben.Die Phasen des clean und site Lifecycles sind in [Tim OBrien et al., 2010, Kapitel 4.1.1, Seite 48ff]beschrieben.

    4

  • 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 OBrien 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 OBrien 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 groe Anzahl an Dependencies aus dem Remote Repository herunterladen.

    5

    http://repo1.maven.org/

  • Apache Maven Klaus-Christian Saalfeld

    junit

    junit

    3.8.1

    test

    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 [TimOBrien et al., 2010, Kapitel 3.4, Project Dependencies, Seite 27].

    2.5. Plugins

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

    Ein groer 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.Auerlich 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

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

  • 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

  • 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 $< f i l e s e t d i r=${doc . d i r } />

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

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

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

    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

  • 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 [email protected] $< $ (CFLAGS)

    %.o : %.cpp Make f i l e$ (GCC) c $ (C INCLUDE PATH) o [email protected] $< $ (CFLAGS)

    %. r e s : %. r c Make f i l e$ (WINDRES) i $< i nputfo rmat=rc o [email protected] 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 ./

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

    a r t i f a c t I d

    28

  • 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 ;/

    com . s s e . j r e g e d i t /

    / 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 tv 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 ;/

    s r c /main/ n a t i v e /windows/

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

    t a r g e t /

    / 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 iva 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 idec o n f i g u r i n gp 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 ;/

    ${ env .JAVA HOME}/ i n c l u d e ${ env .JAVA HOME}/ i n c l u d e /win32 /

    / 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

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

  • 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 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 r e s u l t = new Vector() ;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

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

  • 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 n a t i v e S o u r c e F i l e s = new Vector() ;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 n a t i v e T a r g e t F i l e s = new Vector() ;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

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

  • 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

    4 . 0 . 0

    com . s s e . j r e g e d i tJRegEdi t1 .0 j a r

    JRegEdi th t t p : //maven . apache . org

    UTF8

    j u n i t j u n i t3 . 8 . 1 t e s t

    com . s s e . maven . j n imavenj n icomp i l e rp l u g i n1 .0

    ${ b a s e d i r }

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

    comp i l e

    comp i l e

    35

  • 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 OBrien et al. 2008] Tim OBrien et al.: Maven: The Definitive Guide. 0.3. SonatypeInc., January 2008. http://www.sonatype.com

    [Tim OBrien et al. 2010] Tim OBrien 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

    http://martinfowler.com/articles/injection.htmlhttp://martinfowler.com/articles/injection.htmlhttp://swt-www.informatik.uni-hamburg.de/attachments/LVTermine/DependencyInjection20051207.pdfhttp://swt-www.informatik.uni-hamburg.de/attachments/LVTermine/DependencyInjection20051207.pdfhttp://www.sonatype.comhttp://www.sonatype.comhttp://en.wikipedia.org/wiki/Unix_philosophyhttp://en.wikipedia.org/wiki/Unix_philosophy

    Einfhrung in MavenGrundlagenErste Schritte mit MavenStruktur und Beschreibung eines ProjektesBuild LifecyclesRepositories und Dependency ManagementPlugins

    Exemplarische AnwendungEin ANT Projekt als FallbeispielVergleich zwischen ANT und MavenPortierung des ANT ProjektesErzeugung eines neuen Maven ProjektesHinzufgen der Java QuellenPortierung der Unit-TestsHinzufgen der C QuellenErzeugung eines .jar Archivs

    ArchitekturPlugin-ArchitekturMaven als Plugin-FrameworkEntwicklung eines PluginsIntegration in den Maven Build

    Dependency InjectionPlexus als Dependency Injection Framework

    Zusammenfassung und AusblickZusammenfassungAusblick

    Anhangbuild.xmlMakefileJniCompilerPluginMojo.javapom.xml

    Literaturverzeichnis