Apache Maven – ANTLR Integration

Im 4ten Teil der Serie über Maven (Teil 1, Teil 2, Teil 3) soll gezeigt werden, wie Maven genutzt werden kann, um im Build-Prozess ANTLR-Dateien zu integrieren.

 ANTLR

ANTLR steht für “ANother Tool for Language Recognition”. ANTLR generiert aus den geeigneten Definitionen Lexer, Parser oder TreeParser. Als Zielsprache ist ANTLR nicht auf Java festgelegt, sondern generiert auch Code für C, C++, Python, JavaScript und weitere. Für uns ist hier die Ausgabe natürlich nur in Java interessant.

Erweiterung der pom.xml

Um ANTLR in einem Projekt verwenden zu können, muss die pom.xml an 2 Stellen geändert werden. Zum einen muss eine neue Abhängigkeit zur ANTLR-Runtime definiert werden. Dies passiert im unteren Abschnitt. Damit stehen die ANTLR-Klassen wie bei jeder anderen Dependency bereit.

Soll Maven jedoch noch automatisch aus ANTLR-Grammatikdateien (*.g) entsprechende Java-Klassen erstellen, so ist eine Erweiterung des Build-Vorgangs notwendig. Dazu wird im oben Bereich das antlr3-maven-plugin eingebunden.

<project ...>
    ...
    <build>
        <plugins>
            ...
            <plugin>
                <groupId>org.antlr</groupId>
                <artifactId>
                    antlr3-maven-plugin
                </artifactId>
                <version>3.1.3-1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>antlr</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            ...
        </plugins>
    </build>
    ...
    <dependencies>
        ...
        <dependency>
            <groupId>org.antlr</groupId>
            <artifactId>antlr-runtime</artifactId>
            <version>3.2</version>
            <type>jar</type>
       </dependency>
        ...
    </dependencies>
</project>

Grammatik für Ausdrücke als Beispiel

Die folgende Beispielgrammatik (b1.g) muss im Verzeichnis src/main/antlr3/package/b1 abgelegt werden. das ANTLR-Plugin durchsucht das Verzeichnis src/main/antlr3/package. Alle .g-Dateien innerhalb des Verzeichnisbaums werden von ANTLR übersetzt und im Verzeichnisbaum target/generated-sources/antlr3/package gespeichert. Im weiteren Verlauf des Build-Prozesses sind diese Klassen dann im Classpath und so normal verwendbar.

// Name der Grammatik
grammar b1;

// einfache, feste Tokens
tokens {
	PLUS 	= '+' ;
	MINUS	= '-' ;
	MULT	= '*' ;
	DIV	= '/' ;
}

@header {
        package b1;
}

@lexer::header {
        package b1;
}

ausdruck:
        term ( ( PLUS | MINUS )  term )* ;

term	:
        faktor ( ( MULT | DIV ) faktor )* ;

faktor	:
        ZAHL ;

ZAHL	:
        (DIGIT)+ ;

WHITESPACE :
        ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+
                { $channel = HIDDEN; } ;

fragment DIGIT	:
        '0'..'9' ;

Aus dieser Grammatik-Datei entstehen 2 Klassen:

  • b1Lexer.java
  • b1Parser.java

Der Lexer zerlegt die Eingabe in sog. Tokens, von denen der Parser prüft, ob sie einen gültigen Satz ergeben. In unserem Fall würde “5 * 4 + 3” im Lexer zu “ZAHL MULT ZAHL PLUS ZAHL” und im Parser zu einem sog. Parsebaum “((ZAHL MULT ZAHL) PLUS ZAHL)”.

Résumé

Eine Integration von ANTLR in den Build-Prozess über Maven ermöglicht eine wesentlich einfachere Entwicklung, da händische Zwischenschritte (Erzeugen von Lexer, Parser und/oder Baumparser) entfallen können. Durch anschließende Tests wird dabei automatisch überprüft, ob ein Build erfolgreich ist oder nicht.

Update 23. Juli 2013

Die Quellen zu diesem Artikel kann man nun auch bei GitHub herunterladen oder forken.

Apache Maven – Ausführbare JAR-Dateien

Im dritten Teil unserer Serie über Apache Maven (Teil 1, Teil 2) soll das Programm nicht nur mit mvn exec:java -Dexec.mainClass=”b1.Main” gestartet werden können sondern auch mit java -jar Datei.jar.

Maven Shade PlugIn

Das Maven Shade PlugIn erlaubt das Erstellen einer JAR-Datei, welches alle Abhängigkeiten des Projektes beinhaltet und die Manifest-Datei entsprechend anpasst.

Zum Einsatz muss die pom.xml erneut erweitert werden:

<project ...>
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>1.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                  implementation="org.apache.maven.
                                  plugins.shade.resource.
                                  ManifestResourceTransformer">
                                    <mainClass>b1.Main</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            ...
        </plugins>
    </build>
    ...
</project>

Führt man nun ein mvn package aus, so werden alle abhängigen JAR-Dateien in ein temporäres Verzeichnis ausgepackt, eine entsprechend dem Eintrag Main-Class in der Manifest-Datei.

Anschließend kann über java -jar target/basics1-0.1.jar das Programm gestartet werden.

Résumé

Natürlich ist die so erstellte JAR-Datei größer als die aus dem letzten Teil, da die komplette JLine-Bibliothek mit eingepackt wurde. Dies ist aber notwendig um die JAR-Datei ausführen zu können. Weitere Informationen zum Maven Shade Plugin findet man hier.

Update 23. Juli 2013

Die Quellen zu diesem Artikel kann man nun auch bei GitHub herunterladen oder forken.

Apache Maven – Dependencies

Im zweiten Teil der Serie über Apache Maven (hier geht es zum ersten Teil) geht es diesmal um Repositories und Dependencies.

Dependencies

Als Beispiel einer Dependency war im ersten Teil bereits JUnit aufgefallen (Ausschnitt pom.xml):

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.2</version>
</dependency>

Das reicht aus, um Maven zu sagen: bitte binde doch mal JUnit in Version 4.8.2 in den ClassPath ein. Maven lädt die notwendigen JARs dabei automatisch aus dem Netz herunter. Dazu dienen eine Reihe von Standardrepositories.

Repositories

Nicht alle Dependencies sind in den Standardrepositories vorhanden. Ist für eine Bibliothek ein eigenes Repository notwendig, so kann das wie folgt in der pom.xml angegeben werden:

<repositories>
    <repository>
        <id>jline</id>
        <name>JLine Project Repository</name>
        <url>http://jline.sourceforge.net/m2repo</url>
    </repository>
</repositories>

Hat man die notwendigen Repositories aktiviert kann man weitere Abhängigkeiten festlegen:

<dependency>
    <groupId>jline</groupId>
    <artifactId>jline</artifactId>
    <version>0.9.9</version>
</dependency>

Beispielprogramm

Ergänzen wir das Projekt aus Teil 1 um die Datei src/main/java/b1/Main.java:

package b1;

import java.io.IOException;
import java.io.PrintWriter;

import jline.ConsoleReader;

public class Main {
    public static void main(String[] args) throws IOException{
        ConsoleReader reader = new ConsoleReader();
        String line;
        PrintWriter out = new PrintWriter(System.out);
        while ((line = reader.readLine("number or quit> ")) != null) {
            if (line.equalsIgnoreCase("quit"))
                break;
            int i = Integer.parseInt(line);
            System.out.println(
                Math.square(i)+" ist " + i + " quadriert");
            out.flush();
        }
    }
}

Übersetzen und in ein JAR-File einpacken mit

mvn package

Testweise ausführen kann man das Programm nun einfach mit:

mvn exec:java -Dexec.mainClass="b1.Main"

Résumé

Dieser Teil der Serie hat das Einbinden von Abhängigkeiten vorgestellt. Sucht man für eine Bibliothek die notwendigen Angaben helfen Seiten wie http://mvnrepository.com. So hilft einem Maven durch das automatische Herunterladen schnell zu einer Menge von mächtigen Bibliotheken.

Update 23. Juli 2013

Die Quellen zu diesem Artikel kann man nun auch bei GitHub herunterladen oder forken.

Apache Maven – Basics

Einführung

Apache Maven ist laut Wikipedia ein Build-Management-Tool, welches insbesondere geeignet ist, Java-Projekte zu standardisiert zu erstellen und zu verwalten.

Installation

Um mit Maven arbeiten zu können, muss man unter Gnu Debian 6.0 mindestens diese beiden Pakete installieren:

  • maven2
  • openjdk-6-jdk

Erstes Projekt

Maven verwendet ein standardisiertes Layout für die Projektverzeichnisse.

\projekt                     - Wurzelverzeichnis des Projekts
    \pom.xml                 - Verwaltungdatei
    \src
    |   \main
    |       \java            - Anwendungscode in Java
    |   \test
    |       \java            - Testcode in Java
    \target                  - alle erzeugten Dateien landen hier

Das target-Verzeichnis legt Maven dabei bei Bedarf neu an.

Die Datei “pom.xml” beschreibt dabei notwendige Informationen über das Projekt.

<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>de.lusiardi.maven</groupId>
        <artifactId>basics1</artifactId>
        <packaging>jar</packaging>
        <version>0.1</version>
        <name>Einfuehrung in Maven</name>
        <url>http://wp.lusiardi.de/?p=197</url>
        <build>
                <plugins>
                        <plugin>
                                <groupId>
                                        org.apache.maven.plugins
                                </groupId>
                                <artifactId>
                                        maven-compiler-plugin
                                </artifactId>
                                <version>2.1</version>
                                <configuration>
                                        <source>
                                                1.5
                                        </source>
                                        <target>
                                                1.5
                                        </target>
                                        <encoding>UTF-8</encoding>
                                </configuration>
                        </plugin>
                </plugins>
       </build>
       <dependencies>
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                        <version>4.8.2</version>
                        <scope>test</scope>
                </dependency>
        </dependencies>
</project>

Im Einzelnen bedeuten die Einträge folgendes:

  • modelVersion: aktuell immer 4.0.0
  • groupId: id für die Gruppe, zu der das Artefakt (das Projekt) gehört
  • artifactId: id des Artefakts (des Projekts)
  • packaging: jar legt fest, dass das Projekt als jar-Datei zusammengepackt werden soll
  • version: die Version des Projekts, -SNAPSHOT sagt aus, dass das Projekt noch im Entwicklungszustand ist und regelmässige Änderungen erwartet werden
  • name: der ausführliche Name des Projekts
  • url: URL zur Projektseite
  • build: Maven erlaubt es durch Plugins den Build-Prozess zu erweitern oder zu erweitern, hier wird der Java-Compiler konfiguriert (Java 5 für Annotations).
  • dependencies: gibt die Abhängigkeiten des Projekts zu anderen Projekten an. Hier wird beispielsweise JUnit in Version 4.8.2 eingebunden. Auf das Einbinden von Abhängigkeiten wird später noch eingegangen.

Unser eigentlicher Source-Code besteht nur aus einer Datei in src/main/java/b1/Math.java (keine Kommentare zum Sinn des Codes bitte):

package b1;                                                          

public class Math {                                                  
        public static int square(int a) {                            
                return a*a;                                          
        }                                                            
}

Unsere Testdateien sind ähnlich hochwertig (zu finden in: src/test/java/b1/MathTest.java):

 package b1;

import org.junit.Assert;
import org.junit.Test;
import b1.Math;

public class MathTest {
        @Test
        public void testSqure() {
                Assert.assertEquals(16, Math.square(4));
        }
}

Wichtige Maven-Kommandos

mvn clean

clean löscht alle durch Maven erzeugten Dateien (inklusive des target-Verzeichnisses)

mvn compile

kompiliert den Quellcode unter src/main

mvn test

kompiliert die Test-Dateien und führt die Tests aus. Die Ergebnisse der Tests landen im Verzeichniss target/surefire-reports.

mvn package

erzeugt ein Paket im angegebenen Format (siehe pom.xml)

mvn install

erzeugt das Paket und installiert es im lokalen Repository. So kann es von anderen Projekten als Abhängigkeit verwendet werde.

Résumé

Natürlich kann man Maven nicht ausführlich auf einer solch kurzen Seite beschreiben und komplett erschöpfen, doch sollte dies ein kleiner Einstieg sein. Weitere Artikel zu Maven werden den Umgang mit Abhängigkeiten, ausführbaren Jar-Dateien und dem Einbinden von ANTLR in den Build-Prozess behandeln.

Update 23. Juli 2013

Die Quellen zu diesem Artikel kann man nun auch bei GitHub herunterladen oder forken.

Testaccount für vServer (Linux, Windows)

United Hoster vergibt gerade Testaccounts für vServer mit

  • Linux,
  • Windows 2003 oder
  • Windows 2008 R2

Unter folgender Adresse können die vServer bestellt werden: http://united-hoster.com/vserver-testaccount.html

Nach der Anmeldung kam bei mir am nächsten Tag eine eMail mit den Zugangsdaten an die angegebene Mail-Adresse. Der vServer ist mit 5 GB Festplatte, 512 MB Ram recht knapp ausgestattet. Aber, hey, ist ja gratis.

 

Rootserver

Gesucht sind Rootserver mit folgenden Eigenschaften:

  • für max. 50€ Grundgebühr im Monat
  • mit möglichst kurzer Laufzeit (1 Monat).
  • 4 Kerne
  • 8 GB Ram
  • Auf Traffic lege ich weniger Augenmerk, da der Server für Webhosting von einigen wenigen Domains und Rechenjobs ist

Hetzner.de

  • Produktname: Root Server EX 4
  • CPU: Intel® Core™ i7-2600 Quad-Core (HT)
  • RAM: 16 GB DDR3 RAM
  • Festplatten: 2 x 3 TB SATA II
  • Traffic: flat
  • IP v4: 1 inklusive
  • Preis: 49€/Monat
  • Laufzeit: 1 Monat
  • Einrichtung 149€
  • Link zum Produkt
  • Support:

Vollmar.net

  • Produktname: Dedicated Server
  • CPU: AMD Athlon™ II X4 (4x ab 2,5 GHz)
  • RAM: 8 GB
  • Festplatten: 2 x 1.000 GB SATA II
  • Traffic: 3000GB
  • IP v4: 1 inklusive
  • Preis: 49€/Monat
  • Laufzeit: 1 Monat
  • Einrichtung 199€
  • Link zum Produkt
  • Support über 0800-Hotline zwischen 10-18 Uhr

Server4You.de

  • Produktname: EcoServer LARGE
  • CPU: AMD Athlon™ II X4 (4x 2,3 GHz)
  • RAM: 8 GB DDR3 ECC
  • Festplatten: 2 x 1.000 GB SATA II
  • Traffic: flat
  • IP v4: 1 inklusive (bis zu 3 weiteren, 5€/Mon Pro IP)
  • Preis: 44,99€/Monat
  • Laufzeit: 1 Monat
  • Einrichtung 0€
  • Link zum Produkt
  • Support über 0180 – 370 60 20 (9 cent/min)

webtropia.de

  • Produktname: Server i5-6
  • CPU: Intel Core i5-750 (4 mal 2,66 GHz)
  • Ram: 6 GB DDR3-RAM
  • Festplatte: 2 x 1.000 GB SATA II
  • Traffic: flat
  • IP v4: 1 inklusive
  • Preis: 49€/Monat
  • Laufzeit: 1 Monat
  • Einrichtung 0€
  • Link zum Produkt
  • Support kostenlos von 8 bis 20 Uhr

Sind jetzt nur 4 Anbieter. Wenn jemand noch einen kennt, der meine Anforderungen erfüllt, dann bitte melden per Mail oder Google+.

Update:

Mir wurden noch 2 Anbieter genannt (Danke Michael), die eventuell interessant sein könnten:

strato-pro.de

  • Produktname: HighQ-Server SR-7
  • CPU: Opteron 1381 (4 mal 2,5 GHz)
  • Ram: 4 GB
  • Festplatte: 2 x 500 GB
  • Traffic: flat
  • IP v4: 2 inklusive
  • Preis: 49€/Monat
  • Laufzeit: 6 Monat
  • Einrichtung 89€
  • Link zum Produkt

Fazit zu Strato-Pro: leider nur mit 6 Monaten Laufzeit und dann noch nicht gerade die Spitzenhardware.

hosteurope.de

  • Produktname: Special Server 7
  • CPU: Intel® Dual Core Xeon® 3050 (2 mal 2,13 GHz)
  • Ram: 2 GB
  • Festplatte: 1 x 160 GB
  • Traffic: flat
  • Dell Hardware
  • Zugriff auf die Drac-Karte inklusive
  • IP v4: 1 inklusive
  • Preis: 49€/Monat
  • Laufzeit: 1 Monat
  • Einrichtung 49€
  • Link zum Produkt

Fazit zu hosteurope: Schwache Hardware (aber Marke), leider zu wenig Leistung

Videoschnitt unter Linux

Nachdem ein Cam-Corder angeschafft wurde, um manche Ereignisse auch per Video dokumentieren zu können, sollte es doch auch möglich sein, nur die gewünschten Szenen herauszuschneiden. Das schicke Gerät zeichnet in AVCHD auf SD-Karten auf.

Vorschau generieren

Leider haben die Video-Daten direkt vom Cam-Corder keinen Zeit-Index. Dieser ist für unser weiteres Vorgehen essentiell.

ffmpeg -i INPUT.MTS -r 30000/1001 -acodec pcm_s16le -vcodec mjpeg
       -s 360x240 -aspect 3:2 -y INPUT_preview.mov

Dieses Video ist deutlich kleiner, hat Ton und auch eine mitlaufende Zeit im VLC. Die Zeiten, die im Ergebnis zu sehen sein sollen bitte aufschreiben im Format:

hh:mm:ss

Das Generieren läuft auf einem Intel Core Duo @ 1.66 GHz bei knapp 18 fps recht langsam. Auf einem Intel Core i5 @ 2.67 GHz wird die Operation schon auf ca. 65 fps beschleunigt.

Schneiden

Wenn nun die gewünschten Sequenzen bekannt sind, können diese mit folgendem Kommando ausgeschnitten werden:

ffmpeg -ss START -t STOP -i INPUT.MTS -r 30000/1001 -acodec ac3
       -ab 256k -vcodec copy -s 1280x720 -strict experimental
       -y OUTPUT.m2t

Die Qualität wird durch diesen Schnitt nicht beeinflusst.

Zeitindex zum Ergebnis hinzufügen

Um auch im Ergebnisvideo einen Zeitindex zu haben, muss man noch mit mencoder nachhelfen:

mencoder -idx INPUT.m2t -o OUTPUT.m2t -oac copy -ovc x264

Anschließend hat man den gewünschten Ausschnitt in Ausgangqualität inklusive Zeitindex.

Installation der notwendigen Software

Debian basierte Distributionen

apt-get install ffmpeg mplayer

Fedora 15 (Lovelock)

Fedora 15 macht es dem Anwender einfach:

yum install ffmpeg mplayer

Service bei Subway…

Mal sehen ob der Service auf Mails zu antworten besser ist, als der vor Ort….

Meine Mail von 12.09.2011 14:45 über das Kontaktformular auf http://www.subway-sandwiches.de:

Sehr geehrte Damen und Herren,

am gestrigen Sonntag den 11.09.2011 habe ich kennen lernen dürfen, 
wie groß Service in ihrem Unternehmen geschrieben wird.

Der Toilettengang in ihrem Restaurant in Mannheim am Bahnhof glich
einer Katastrophe im Bereich Service. Zuerst: 1€ um die nicht gut
gepflegte Toilette betreten zu dürfen. Üblich sind zumindest an
Autobahnen ca 70 Cent mit 50 Cent Verzehrsanteil.
Also deutlich teurer!

Weiterhin war das stille Örtchen ungepflegt und sowohl
Toilettenpapier als auch Papierhandtücher waren aus. 

Auf meine Bitte, mir den 1 Euro für diese erbrachte "Leistung" zu
erstatten kamen von den anwesenden Mitarbeitern ihrer Kette nur
Ausflüchte. Die Motivation den Missstand zu beheben war leider 
nicht erkennbar. 

Alles in allem schreckt mich dieses Erlebnis von weiteren Besuchen
in ihren Restaurants deutlich ab.

Mit freundlichen Grüßen
Joachim

Über Antworten poste ich dann wieder hier.