Projewski’s Weblog

marzec 14, 2008

FOP Apache’a i polskie czcionki dla PDF’a

Kategoria wpisu: Java — projewski @ 3:00 pm

Ostatnio pobrałem sobie ze strony Apache’a pakiet fop-0.94. Warto wspomnieć, do czego takowy pakiet służy. Otóż wykonuje on, poprzez odmianę transformaty XSL, zwaną XSL-FO, generowanie dokumentu w wybranym formacie - najczęściej chodzi o PDF oraz o PS.

 Zadaniem, które sobie postawiłem było wygenerowanie pliku PDF z polskimi krzaczkami. Samo uruchomienie pakietu nie nastręcza kłopotów. Wystarzy rozpakować pobrany pakiet i uruchomić polecenie fop w systemie Linux’owym, lub fop.bat, jeżeli jest to Windows. Lista parametrów pięknie pokaże się naszym oczom. Standarodowe używanie programu polega na ładowaniu plików .fo i generowaniu powiedzmy .pdf. Lepszą zabawę uzyskujemy wykorzystując plik transformacji .xsl, który na bazie pliku z danymi .xml generuje nam plik typu .fo, z którego powstaje upragniony .pdf czy .ps.

Problem z jakim się napotkałem to oczywiście polskie czcionki, które, jakżeby inaczej, w domyślnej konfiguracji są niezbyt dostępne dla użytkownika. Zadanie to można zrealizować poprzez wykorzystanie pliku z czcionkami, które akceptuje fop. A akceptuje dwa dość popularne typy: TrueType oraz PostScript Type 1. Posiadając system Windows możemy odnaleźć czcionki TrueType z polską czcionką i spróbować je wykorzystać. Pliki posiadają rozszerzenie .ttf. Oczywiście polecam wcześniej przyjrzeć się, co takowy plik tak naprawdę zawiera.

Aby wykorzystać wybraną czcionkę powinniśmy w pierwszej kolejności wygenerować tak zwane font metrics, którymi FOP będzie się posługiwał. Poniżej zamieszczam kod skryptu sh, który używałem do generowania takowego pliku. Skrypt używa w tym celu klasy TTFReader, która dostarczona jest z FOP’em. Jeżeli import odbywa się z czcionek True Type 1, to należy wykorzystać klasę PMFReader.

#!/bin/sh
#
# sciezka do katalogu domowego Java
JAVA_HOME=”/opt/java”;
# sciezka do pliku fop.jar
FOP_PATH=”/opt/java/fop/build”;
# sciezka do jar’ow uzywanych przez fop’a
LIB_PATH=”/opt/java/fop/lib”;
#
$JAVA_HOME/bin/java -cp $FOP_PATH/fop.jar:$LIB_PATH/avalon-framework.jar:$LIB_PATH/xml-apis.jar:$LIB_PATH/xercesImpl.jar:$LIB_PATH/xalan.jar:$LIB_PATH/commons-logging-1.0.4.jar:$LIB_PATH/commons-io-1.3.1.jar org.apache.fop.fonts.apps.TTFReader $1 $1.xml

Jeżeli posiadamy czcionki bold oraz italic, to dla nich również generujemy pliki font metrics.

Teraz pliki czcionek oraz wygenerowane font metrics umieszczamy w jakimś miejscu na dysku, niech to będzie /usr/local/lib/fop. Potrzebny jest nam teraz plik konfiguracyjny, który pozwoli na podłączenie takich czcionek. Będzie on wyglądał tak:

<configuration>
<renderers>
<renderer mime=”application/pdf”>
<fonts>
<font metrics-url=”file:///usr/local/lib/fop/czcionka.ttf.xml” kerning=”yes” embed-url=”file:///usr/local/lib/fop/czcionka.ttf”>
<font-triplet name=”Czcionka” style=”normal” weight=”normal”/>
</font>
<font metrics-url=”file:///usr/local/lib/fop/czcionka-bold.ttf.xml” kerning=”yes” embed-url=”file:///usr/local/lib/fop/czcionka-bold.ttf”>
<font-triplet name=”Czcionka” style=”normal” weight=”bold”/>
</font>
<font metrics-url=”file:///usr/local/lib/fop/czcionka-italic.ttf.xml” kerning=”yes” embed-url=”file:///usr/local/lib/fop/czcionka-italic.ttf”>
<font-triplet name=”Czcionka” style=”italic” weight=”normal”/>
</font>
</fonts>
</renderer>
</renderers>
</configuration>

Plik konfiguracyjny zawiera ścieżki, wskazujące na pliki czcionek oraz ich odpowiednie font metrics. Oczywiście konfiguracja może również zawierać inne dane konfiguracyjne, jakie używamy do fop’a. Te określone tutaj określają zestaw czcionek, używanych podczas renderowania dokumentu PDF - na co wskazuje atrybut mime=”application/pdf”, użyty dla elementu renderer. Aby użyć pliku konfiguracyjnego wykorzystujemy polecenie fop z parametrem -c nazwa-pliku-konfiguracyjnego.

To co jest jeszcze istotne to fakt, że podczas generowania pliku PDF/PS, fop automatycznie tworzy w katalogu domowym bieżącego użytkownika folder .fop, w którym zostaje zawarty cache dla czcionek, jakie są wykorzystywane. Warto o tym pamiętać w przypadku korzystania z tego narzędzia poprzez np. zestaw narzędzi apache + php, gdy mamy skonfigurowanego użytkownika dla aplikacji. Fop będzie wtedy próbował założyć folder w katalogu domowym takiego użytkownika - dobrze więc sprawdzić, czy użytkownik ma uprawnienia do zapisywania w takim katalogu. (Można również utworzyć samodzielnie folder .fop, w jego katalogu domowym i nadać na nim odpowiednie uprawnienia własności/zapisu).

Więcej na temat fop‘a znajdziemy na stonie domowej projektu Apache’a http://xmlgraphics.apache.org/fop/

styczeń 11, 2008

JBoss, EJB 3 i StreamCorruptedException

Kategoria wpisu: Java — projewski @ 10:36 przed południem

Ostatnio wykonywałem stawianie serwera JBoss 4.0.5 z pakietem patchującym jboss-EJB-3.0_RC9_Patch_1, który miał zapewnić mi rozszerzenie do funkcjonalności EJB 3. Uruchamiałem JBoss w konfiguracji default. Podczas uruchamiania otrzymałem komunikat, którego finałowym powodem był brak klasy org.jboss.cache.TreeCache. Klasę odnalazłem w pakiecie jboss-cache.jar znajdującą się w konfiguracji all. Poza tym jar’em okazało się również niezbędne dodanie jgroups.jar z podobnej konfiguracji. I teraz po uruchomieniu okazało się, że ustawicznie otrzymuje komunikat, wyglądający mniej więcej tak:

2007-05-29 19:31:15,453 WARN [org.jgroups.protocols.UDP] packet from /X.X.X.X :P has different version from ours
2007-05-29 19:31:27,671 ERROR [org.jgroups.protocols.UDP] exception=java.io.StreamCorruptedException: invalid stream header
at java.io.ObjectInputStream.readStreamHeader (ObjectInputStream.java:764)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:277)
at org.jgroups.protocols.UDP.handleIncomingUdpPacket(UDP.java:670)
at org.jgroups.protocols.UDP.run(UDP.java:249)
at java.lang.Thread.run(Thread.java:595)

Podczas poszukiwań w internecie próbowałem ustalić “Skąd się to diabła bierze ??” oraz “Jak to wyłączyć ?”. Dowiedziałem się, że głównym sprawcą zamieszania jest opcja grupowania w klastry (group clustering). Opcja ta oczywiście dostępne jest wyłącznie w dystrybucji all. Moje przeniesienie plików jar, w celu zniwelowania problemu przyczyniły się do powstania tego kłopotu.

Tak więc postanowiłem wykonać operację w drugą stronę i dowiedzieć się, co spowodowało narodzenie się wymagania klas typu TreeCache i JGroups. Przyczyną był oczywiście ów patch, który rejestrował dwa serwisy, korzystające z tej usługi. Usunąłem więc pliki, które są odpowiedzialne za taki stan rzeczy: ejb3_clustered_sfsbcache_service.xml oraz ejb3_entity_cache_service.xml (znajdujące się w folderze deploy). Oczywiście nie zapomniałem również o pozbyciu się jgroups.jar oraz jboss-cache.jar (z folderu lib). Po tych czystkach wszystko poszło pięknie i bez problemów.

Oczywistym jest, że zacząłem się zastanawiać nad sposobami zniwelowania problemu w przypadku, kiedy posiadam zainstalowany clustering. Okazało się, że powodem jest istnienie innych serwerów w lokalnej sieci, które mają inną wersję JBoss’a, a które próbują utworzyć ze mną wspólną grupę. Każda z takich grup używa swoją prywatną nazwę oraz określenie adresu i portu dla multicastingu. Z pomocą nad rozwikładniem zagadki przyszły mi poniższe dwa artykuły:

http://docs.jboss.org/jbossas/jboss4guide/r4/html/jbosscache.chapt.html , który opisuje sposób konfigurowania JGroups (i tu mała uwaga, opcja discard_incompatible_packets w mojej wersji nazywa się discard_incompatibe_packets z powodu literówki, która została później poprawiona w JBoss)

http://wiki.jboss.org/wiki/Wiki.jsp?page=TwoClustersSameNetwork , który opisuje jak skonfigurować dwa odrębne klastry w tej samej sieci - co sprawdziłem i stwierdzam, że funkcjonuje to poprawnie (plik cluster-service.xml jest dostępny w konfiguracji all). Problemem, jaki należy później jeszcze rozwiązać jest skonfigurowanie plików EJB 3, które usuwałem, tak, aby nie kolidowały z odpowiednikami, jakie znajdują się w naszej sieci lokalnej.

grudzień 20, 2007

Upgrade subversion i DB_VERSION_MISMATCH

Kategoria wpisu: Programowanie — projewski @ 10:56 przed południem

Po wykonaniu upgrade na subversion otrzymałem błąd o następującej treści, przy próbie wykonania jakiejkolwiek operacji (tu akurat przy użyciu programu svnadmin):

svnadmin: Berkeley DB error for filesystem ‘REPO/db’ while opening environment:
svnadmin: DB_VERSION_MISMATCH: Database environment version mismatch
svnadmin: bdb: Program version 4.3 doesn’t match environment version

Rozwiązanie okazało się banalnie proste. Wystarczy wykonać polecenie: svnadmin recover REPO, gdzie REPO to ścieżka do repozytowium.

Taka mała uwaga - parę razy przytrafiło mi się mieć poważne problemy z bazą Berkeley, które pojawiały się np. w przypadku, gdy było sporo rewizji i danych, które były przechowywane. Najczęściej chodziło o pokombinowanie z UUID oraz recover’em repozytorium. Jednak zamienienie bazy Berkeley na system plikowy uwolniło mnie od wszelkich kłopotów. Dlatego poniżej zamieszczam sposób, jaki pozwala na przejście z bazy Berkeley na bazę plikową.
1. Zakładam, że znajdujemy się w katalogu, który mieści folder naszego repozytorium o nazwie REPO.
2. Wykonujemy zachowanie konfiguracji: cp -r REPO/conf .
3. Wykonujemy zrzut z repozytorium: svnadmin dump --incremental REPO > REPO.dump
4. Usuwamy repozytorium: rm -rf REPO
5. Zakładamy na nowym systemie plikowym: svnadmin create --fs-type fsfs REPO
6. Usuwamy nowe pliki konfiguracyjne: rm -rf REPO/conf
7. Przywracamy stare dobre ustawienia: mv conf REPO
8. Przywracamy rewizje repozytorium: svnadmin load REPO < REPO.dump
9. Usuwamy niepotrzebny juz plik: rm -rf REPO.dump
10. Cieszymy się repozytorium opartym na systemie plików.

A co do robienia zrzutów bezpieczeństwa z posiadanych repozytoriów. Poniżej dołączam prosty skrypt napisany w bash do wykonywania takiej operacji. Można podpiąc go na przyklad pod cron. Nie jest doskonały - nie sprawdza na przykład, czy wszystko idzie zgodnie z oczekiwaniami, więc można sobie dopisać zrzucanie logów z działania oraz sprawdzanie kodów powrotu.

#!/bin/sh
BACKUP_FOLDER=”/var/backup/svn”
REPOS_FOLDER=”/var/repos”
if test -d $BACKUP_FOLDER; then
echo “Backup folder: $BACKUP_FOLDER”;
for i in $REPOS_FOLDER/*; do
 if test -d $i; then
  if test -f $i/db/fs-type; then
  DATE=`date +%Y-%m-%d`;
  echo “Zrzut $i do $BACKUP_FOLDER/$i-$DATE.dump.gz”;
  svnadmin dump –incremental $i | gzip -9c > $BACKUP_FOLDER/$i-$DATE.dump.gz
  fi
 fi;
done;
else
echo “Nie odnaleziono folderu backup: $BACKUP_FOLDER”;
fi

listopad 23, 2007

Kryptografia - listy ARL

Kategoria wpisu: Programowanie — projewski @ 3:07 pm

Ostatnio “natknąłem się” na nurtujący temat list ARL. Cóż to takiego jest ? Wykonałem drobne rozpoznanie i oto czego się dowiedziałem.

Listy ARL są to zwykłe listy CRL, z tą drobną różnicą, iż zawierają jedynie odwołane certyfikaty centrów certyfikacji (CA - Certificate Authority). Normalna lista CRL zawiera certyfikaty końcowe użytkowników, dla których zostały one wystawione. Przykładem takiej formy listy ARL może być lista wystawiana przez Centrast (http://www.centrast.pl). Jest to nasze Narodowe Centrum Certyfikacji. Zostało ono powołane przez Ministerstwo w celu wystawiania certyfikatów dla urzędów certyfikacyjnych, które spełniają odpowiednie normy i zostały uznane za bezpieczne. Centrast wystawia swoją listę CRL, podpisaną swoim prywatnym kluczem, przy użyciu której odwołuje certyfikaty urzędów CA, dla których “stracił” zaufanie (przy odwołaniu jest podawany powód - najczęściej są to przedawnienia i zmiany certyfikatów).

Jaki jest wniosek. Podczas weryfikowania ścieżki certyfikacji na samym szczycie znajdujemy certyfikat centratu, który podpisał określony urząd i na jego liście CRL (zwaną ARL) wykonujemy weryfikację.

Co na ten temat mówi dokumentacja ?

Zgodnie z RFC 3280 (punkt 5.2.5) jest możliwe dodanie do wygenerowanej listy CRL rozszerzenia (Extension), które nazywane jest “Wystawienie punktu dystrybucji” (Issuing Distribution Point). Rozszerzenie to jest krytyczne i pozwala na określenie obszaru zastosowań listy CRL - jako lista odwołań tylko certyfikatów końcowych, tylko punktów CA, tylko certyfikatów atrybutów lub wypuszczenia zestawu powodów odwołań. Rozszerzenie, pomimo, ze jest krytyczne nie wymaga interpretacji w aplikacji docelowej.

Praktyka pokazuje, ze urzędy wystawiające listy ARL nie zawsze dołączaja do owych list to rozszerzenie. Równocześnie nazywają listę CRL listą ARL i nie stosują się w zupelności do tej formy (zamieszczają odwołania certyfikatów, które nie są urzędami CA, a np. slużą do podpisywania znacznika czasu).

Jako klasyczny przykład listy ARL podałbym fińską listę, dostępną pod adresem http://proxy.fineid.fi/arl/vrkroota.crl

listopad 16, 2007

LIBCMT.lib(crt0dat.obj) : error LNK2005: __osplatform already defined in atlmincrt.lib(atlinit.obj)

Kategoria wpisu: C i C++ — projewski @ 10:35 przed południem

Dziś natknąłem się na następujący problem z linkerem (MSVC 2005):

LIBCMT.lib(crt0dat.obj) : error LNK2005: __osplatform already defined in atlmincrt.lib(atlinit.obj)
LIBCMT.lib(crt0.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup

Oczywiście było parę innych spokrewnionych błędów. Problem pojawił się, gdy do tworzonej DLL’ki, która używa paru niewinnych rzeczy z ATL (COM) dodałem funkcjonalności STL’a. Zmiany ustawień w Project->Properties…->General dla opcji Use of ATL oraz Minimize CRT Use in ATL przysparzają więcej problemów niż rozwiązań.

Rozwiązaniem okazało się wykonanie wpisu w pliku StdAfx.h postaci
#undef _ATL_MIN_CRT
przed formami include do ATL.

październik 29, 2007

Strumień ByteArrayOutputStream

Kategoria wpisu: Java — projewski @ 11:15 przed południem

Oto, co dziś się dowiedziałem, a czego jeszcze nie przetestowałem:

Implementacja Apache strumienia ByteArrayOutputStream jest szybsza i zajmuje mniej pamięci od podobnej implementacji Sun’a. Dlatego znacznie lepszym pomysłem jest stosowanie klasy org.apache.commons.io.output.ByteArrayOutputStream niż klasy java.io.ByteArrayOutputStream. Z testów porównawczych, wykonanych na pliku o rozmiarze 90 MB, otrzymano następujące informacje:

Sun JDK wykonywał wczytanie w ciągu 2300 ms i zajął 210 MB pamięci
Apache wykonał wczytanie w ciagu 1300 ms i zajął 140 MB pamięci

Blog at WordPress.com.