Softwaretechnik-Blog

Freitag, März 26, 2010

 

Tomcat-Admin über SSL/https aus Ant-Build (catalina-ant.jar) aufrufen

Ich habe ein SVN-Repository mit SSL abgesichert, so dass nur noch per https://server/svn/repo darauf zugegriffen werden konnte. Dafür habe ich u.a. ein SSL-Zertifikat selbst erzeugt und im Apache installiert. Das war (wie immer) unproblematisch und funktioniert gut.
Die Entwickler und Tester mussten lediglich beim ersten Aufruf der neuen SVN-URL das Zertifikat bestätigen. (Weil es selbst erzeugt war, galt es standardmäßig zunächst nicht als sicher.) Anschließend war die normale Arbeit wieder möglich.
Die Überraschung kam, als der nächtliche Build fehlschlug. Er meldete im [undeploy]-Target:

[undeploy] sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

 Die Meldung ist wenig benutzerfreundlich. Aber offensichtlich bestand ein Problem mit dem Zertifikat. Zu dieser Fehlermeldung findet man bei Google eine ganze Reihe von Möglichkeiten zur Behebung. Sie beziehen sich aber in der Regel auf den Einsatz mit dem Tomcat, nicht auf die Verwendung des catalina-ant.jar.
Was muss man tun, um diesen Fehler innerhalb des ant-Build zu beheben?

1. Prüfen, welche Java Version für den Build verwendet wird: Das klingt, als wäre das doch selbstverständlich. Wenn aber mehrere Java-Versionen auf dem Build-Server installiert sind, man muss genau diejenige finden, die auch tatsächlich verwendet wird.

2. Das Zertifikat bereitlegen, dass benutzt werden soll: Es liegt auf dem Apache-Server (z.B. unter /etc/apache2/ssl.crt/beispiel.crt) und muss ggf. auf den Build-Server kopiert werden.

3. Mit dem KeyTool das Zertifikat in einen vertrauenswürdigen Zertifikatspeicher laden:
> keytool -keystore /pfad/zum/java/jre/lib/security/meine-certs -import -alias mein.server.de -file beispiel.crt -trustcacerts

4. Die Umgebungsvariable ANT_OPTS setzen: Vor dem Aufruf von ant, muss die Umgebungsvariable ANT_OPTS so gesetzt werden, dass der neue Zertifikatsspeicher benutzt wird. Beispielsweise so:


...
export ANT_OPTS="-Djavax.net.ssl.trustStore=/pfad/zum/java/jre/lib/security/meine-certs"
..
ant -f mein-build.xml
...


5. Build starten: Das sollte jetzt funktionieren.

Mittwoch, März 17, 2010

 

Ankreuzfelder von XSL-FO nach PDF

Ankreuzfelder in XSL-FO einfügen ist über Unicode einfach möglich. Allerdings werden sie bei der Generierung von PDF nicht automatisch richtig übernommen. Das folgende XSL-FO liefert beispielsweise die nachfolgende PDF-Datei:

<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <fo:layout-master-set>
      <fo:simple-page-master master-name="A4" page-width="210mm" page-height="297mm">
         <fo:region-body region-name="region-body" margin="2cm"/>
      </fo:simple-page-master>
   </fo:layout-master-set>
   <fo:page-sequence master-reference="A4">
      <fo:flow flow-name="region-body">
         <fo:block>
           <fo:block>Boxes from XSL-FO to PDF</fo:block>
           <fo:block >&#x2610; Box</fo:block>
           <fo:block >&#x2611; Box checked</fo:block>
           <fo:block >&#x2612; Box x-marked</fo:block>
         </fo:block>
      </fo:flow>
   </fo:page-sequence>
</fo:root>



Die Ankreuzfelder fehlen im PDF-Dokument. Warum? Bei der PDF-Generierung wird auf die Standard-Schriftarten zurückgegriffen, die im PDF zur Verfügung stehen. Sie unterstützen allerdings kein Unicode und stellen deshalb die Ankreuzfelder ersatzweise durch das Zeichen # dar. Man kann sich die eingebetteten Schriftarten in dem Eigenschaften des PDF-Dokumentes auf der Registerkarte "Schriften" anzeigen lassen. (Im Adobe Reader unter Datei > Eigenschaften...)

Um die Unicode-Zeichen in PDF anzeigen zu können, muss also eine Unicode-Schriftart im PDF eingebettet werden. Das wirft zwei Fragen auf:

1. Frage: Wie schreibe ich in XSL-FO, dass eine Unicode-Schriftart verwendet werden soll?
2. Frage: Wie veranlasse ich FOP diese Schriftart in das PDF einzubetten?

Antwort auf Frage 1:
Spontan würde man zunächst vielleicht auf "Arial Unicode MS Standard" zurückgreifen. Diese Schriftart ist auf vielen Windows-Betriebssystemen verfügbar, weil sie mit Microsoft Office ausgeliefert wird. Dann würde der XSL-FO Code wie folgt aussehen, um diese Schriftart festzulegen:

<fo:block>
  <fo:block>Boxes from XSL-FO to PDF</fo:block>
  <fo:block font-family="ArialUnicodeMS">&#x2610; Box</fo:block>
  <fo:block font-family="ArialUnicodeMS">&#x2611; Box checked</fo:block>
  <fo:block font-family="ArialUnicodeMS">&#x2612; Box x-marked</fo:block>
</fo:block>

Wenn dann die ArialUnicodeMS-Schriftart in die PDF-Datei mit eingebettet wird (siehe Antwort unten auf Frage 2), sieht das im Ergebnis so aus:



Das sieht doch prima aus: Die Ankreuzfelder sind da und die Schrift ist eingebettet. Das war noch keine große Überraschung, oder? Die Überraschung kommt aber jetzt, denn Arial Unicode MS unterliegt der Lizenz von Agfa Monotype Corp. und darf nicht frei kopiert werden (siehe http://www.fonts.com/FontServices/LicensingOptions.htm). Bei den Dateieigenschaften der ArialUni.ttf kann man diese Lizenzbedingung auch nachlesen:


Mein Verständnis von den Lizenzbedingungen ist, dass man Arial Unicode MS nicht in PDF-Dokumente einbetten und weitergeben darf. Um jedes derartige Lizenzproblem zu umgehen, sollte man also eine freie Alternative zu Arial Unicode MS finden.

Eine gute Alternative ist das Projekt "Free UCS Outline Fonts" (siehe http://savannah.gnu.org/projects/freefont). Unter der GNU General Public License v3 sind verschiedene Fonts verfügbar. Verwendet man die Schriftart FreeMono würde es in XSL-FO so aussehen:

<fo:block>
  <fo:block>Boxes from XSL-FO to PDF</fo:block>
  <fo:block font-family="FreeMono">&#x2610; Box</fo:block>
  <fo:block font-family="FreeMono">&#x2611; Box checked</fo:block>
  <fo:block font-family="FreeMono">&#x2612; Box x-marked</fo:block>
</fo:block> 
 
Wenn dann die FreeMono-Schriftart in die PDF-Datei mit eingebettet wird, sieht das im Ergebnis so aus:

Die Ankreuzfelder werden nun in der PDF-Datei angezeigt und die Freie Schriftart FreeMono ist eingebettet, so dass es keine Lizenzprobleme wie bei der Arial Unicode MS geben sollte. (Nachdem das geklärt ist, wird es langsam Zeit für die Antwort auf Frage 2.)

Antwort auf Frage 2:
Um die Schriftart FreeMono (oder eine andere) in das PDF einzubetten, sind die folgenden drei Schritte notwendig.


Schritt 1:
Aus der  True Type Font-Datei FreeMono.ttf muss eine Font Metrics-Datei erzeugt werden. Der folgende Aufruf erzeugt die entsprechende Datei freemono.xml:

java -cp %CLASSPATH% org.apache.fop.fonts.apps.TTFReader FreeMono.ttf freemono.xml

Schritt 2:
Die Font Metrics-Datei muss in eine FOP-Konfiguration eingebunden werden. Dazu geht das folgende Beispiel davon aus, dass unterhalb von .\lib das fop.jar, die nachfolgende Konfigurationsdatei, die True Type-Datei FreeMono.ttf und die Font Metrics-Datei freemono.xml liegen. Hier ein Beispiel für die Datei fop-config.xml:

<?xml version="1.0"?>
<fop version="1.0">
    <base>./lib</base>
    <source-resolution>72</source-resolution>
    <target-resolution>72</target-resolution>
    <default-page-settings height="297mm" width="210mm"/>
    <renderers>
        <renderer mime="application/pdf">
            <filterList>
                <value>flate</value>
            </filterList>                
                <!-- Hier werden Freie Unicode Fonts des Projektes Free UCS Outline Fonts verwendet (siehe 
                http://savannah.gnu.org/projects/freefont). -->
                <font metrics-url="fop-freemono.xml" kerning="yes" embed-url="FreeMono.ttf">
                    <font-triplet name="FreeMono" style="normal" weight="normal"/>
                </font>                
            </fonts>
        </renderer>
    </renderers>
</fop> 

Jetzt erklärt sich auch, woher bei der Antwort auf die Frage 1 der Namen der font-family stammte. Er ist in der name-Eigenschaft des font-triplet angegeben.

Schritt 3:
Um die FOP-Konfigurationsdatei zu verwenden, muss sie beim Aufruf von FOP als Parameter mit angegeben werden:

java -jar .\lib\fop.jar -c .\lib\fop-config.xml input-with-boxes.fo -pdf output-with-boxes.pdf

Weitere Details zur Antwort auf Frage 2 können unter http://xmlgraphics.apache.org/fop/0.94/fonts.html nachgelesen werden.

Samstag, Februar 13, 2010

 

Ankreuzfelder in XSL-FO

Ankreuzfelder in einem XSL-FO-Dokument können recht einfach mit dem Unicode der Symbole ☐ BALLOT BOX (U+2610), ☑ BALLOT BOX CHECKED (U+2611) und ☒ BALLOT BOX X-MARKED (U+2612) erzeugt werden. Der folgende Code resultiert in dem Ergebnis unten.

<fo:block height="9pt">
    <fo:inline margin-right="5pt">
        <fo:inline font-size="11pt">&#x2612;</fo:inline> männlich</fo:inline>
     <fo:inline>
        <fo:inline font-size="11pt">&#x2610;</fo:inline> weiblich</fo:inline>
   </fo:block>

Im Ergebnis sollte es in einem Browser, der Unicode unterstützt so aussehen:

männlich weiblich

Wenn Ihr Browser kein Unicode kennt (z.B. IE5) werden sie in der Zeile zuvor keine Ankreuzfelder gesehen haben. Eigentlich sollte es so aussehen:


Montag, Januar 25, 2010

 

Beim Zugriff auf Elemente eines Nodeset per [x] auf Datentyp von x achten

Manchmal verstecken sich Fehler sehr gut. Im folgendem Code hat sich ein solcher Fehler versteckt:

...
   <xsl:variable name="position">
      <xsl:value-of select="count(preceding::bar)+1"/>
   </xsl:variable>
   <xsl:apply-templates select="$my-node-set[$position]"/>
...

Der Code oben soll die Anzahl von bar-Elementen zählen und dann aus dem Nodeset $my-node-set das Element verarbeiten, dass an der Position steht, die der Anzahl bar-Elemente entspricht.

Von der Variablen "position" könnte man dabei zunächst annehmen, dass sie eine Zahlenangabe repräsentieren würde. Wie man beim Ausführen des Codes bemerken würde, ist dies allerdings nicht der Fall. Es wird aus der Variablen $my-node-set stets der erste Knoten gewählt.

Tatsächlich ist position vom Typ String und muss bevor er mit [] verwendet werden kann in eine Zahl transformiert werden. So ist es richtig:

...

   <xsl:variable name="position">
      <xsl:value-of select="count(preceding::bar)+1"/>
   </xsl:variable>
   <xsl:apply-templates select="$my-node-set[number($position)]"/>
...


Mit number() wird aus dem String eine Zahl und dann klappt der Zugriff auf den Knoten im Nodeset an der gewünschten Stelle.

Labels: , ,


Sonntag, Januar 24, 2010

 

Was tun, wenn xsl:attribute name="xmlns" nicht geht?

Man kann in einer XSLT einem Element kein namespace-Attribut zuweisen. Der folgende Versuch schlägt fehl: <xsl:attribute name="xmlns"> Warum dies so ist, erklärt Jeni Tennison (http://www.biglist.com/lists/xsl-list/archives/200102/msg00656.html).

Sie schlägt verschiedene Alternativen vor, erwähnt allerdings nicht die XSLT 2.0-Variante:

  <xsl:namespace name="bar" select="'http://bar.com/foo1'"/>
bzw.
  <xsl:namespace name="" select="'http://bar.com/foo'"/>

mit denen zum Wurzelelement des erzeugten Ergebnisdokumentes ein Default-Namespace xmlns="http://bar.com/foo" und der Namespace xmlns:bar="http://bar.com/foo1" erzeugt werden.

Labels: , ,


Archives

This page is powered by Blogger. Isn't yours?

Haftungsausschluss:
Alle Ausführungen und Inhalte auf dieser Website sind gewissenhaft erarbeitet worden. Dennoch kann weder die inhaltliche Richtigkeit, noch die Übereinstimmung mit den tatsächlichen Bedürfnissen des Nutzers der hier dargestellten Ausführungen und Inhalte garantiert werden. Der Nutzer der hier dargestellten Ausführungen und Inhalte verpflichtet sich, sie vor ihrer Verwendung inhaltlich auf Richtigkeit und auf Eignung für den konkreten Einsatzzweck zu prüfen. Es kann keine Gewährleistung für die rechtliche oder technische Wirksamkeit der Ausführungen und Inhalte übernommen werden - insbesondere können hieraus auch keine haftungsrelevanten Ansprüche hergeleitet werden.