« February 2009 | Main | May 2009 »

March 2009 Archives

March 22, 2009

advanced XML-Parser

Innerhalb unseres Projektes ist die Notwendigkeit entstanden, XML-Dokumente, die etwas umfangreicher als die Standard-Java-Deskriptoren sind, auf Gleichheit hin zu untersuchen.
Folgende XML-Strings sind gegeben:

A)
<items>
    <item name="a">
        <value>1</value>
    </item>
    <item name="b">
        <value>2</value>
    </item>
    <item name="c">
        <value>3</value>
    </item>
</items>

B)
<items>
    <item name="a">
        <value>1</value>
    </item>
    <item name="c">
        <value>3</value>
    </item>
    <item name="b">
        <value>2</value>
    </item>
</items>


Diese Untersuchung soll eine Aussagen über:
- Gleichheit: (2 Dateien enthalten das gleiche XML-Modell - sowohl in der gleichen Reihenfolgen A) , als auch in einer anderen Reihenfolge B) ).
- Veränderungen: welche Stellen sind verändert worden.

Während Forderung zwei sich noch mit einem einfachen String-Vergleich lösen lässt, ist Forderung eins nur durch das erkennen eines Modells lösbar.
Hierbei ist es notwendig, die einzelnen Knoten zu erkennen.
Zudem sind die zu-untersuchenden XML-Dateien > 5 MBb sodass viele - professionelle XML-Tools hier streiken müssen und mit Speicherfehlern aufgeben.

Der Ansatz der hier vorgestellt wird, setzt sich aus drei Stufen zusammen:


  1. SAX-basiertes Parsen der Datei und einlesen in eine Datenbank (aus Performance-Gründen wird hier H2 als inMemory Datenbank genutzt).

  2. Um schnelle Vergleiche zu ermöglichen wird ein Modell benutzt, welches u.a. auch in ZFS angewendet wird: Erkennen von Veränderungen anhand von Prüfsummen.
    Was bei ZFS dazu benutzt wird, um Änderungen innerhalb des Dateisystems zu erkennen, soll hier dazu dienen, Unterschieder zwischen zwei XML-Modellen schnell und zuverlässig zu erkennen.
    Hierzu wird für jeden Knoten eine Prüfsumme berechnet. Diese leitet sich jeweils aus den Prüfsummen seiner Kindsknoten, dem Inhalt seiner Attribute und dem Wert des Knotens ab.
    Momentan wird über diesen Gesamt-String ein SHA1-Hash gebildet. Eine weitere Prüfsumme wird benötigt, um den Knoten innerhalb des Modells zu lokalisieren (wir verwenden hier den XML-Path+Knotennummer):


    1. <--                   Hash des Pfades                   -->
      3a52ce780950d4d969792a2559cd519d7ee8c727 
      ./
      items/item/value           


    2. <--             Hash des Knotens item              -->
      481e6ff69a8402231a3b9c6e46a7fef4f09adbb3
      hash von: "item", attribute "name=b", hash von "value"


  3. Da sowohl eine Aussage über Unterschied im sortierten Zustand - die Reihenfolge der (Kinder-)Knoten ist wichtig - als auch im unsortierten Zustand (Die Reihenfolge der Kinder-)Knoten ist egal,
    wird vor dem Berechnen des Hashes des Kindes eines Knotens, die Kinder einmal unsortiert und einmal sortiert als Basis für den SHA1-Hash genommen.


Momentan ist das Datenmodell soweit vollständig, die Knotenwerden beim Parsen in die Datenbank eingelesen. Dieser Vorgang wird momentan noch hinsichtlicher Dauer und Speicherverbrauch optimiert. Auch eine aussagekräftige Fortschrittanzeige sollte eingebaut werden. Danach muss der Algorithmus zum Erkennen der unterschiedlichen Stellen implementiert werden.
Als letztes sollen diese Unterschiede in einer übersichtlichen und - für große Dokumente - gut navigierbaren GUI angezeigt werden.

Blogged with the Flock Browser

March 28, 2009

SortedProperties

Angenommen, man braucht für ein Java Property Set ein geordnete Ausgabe - zum Beispiel um einem Übersetzer eine sortierte Liste mit zu übersetzenden String zu liefern.

Man erstellt eine Klasse (zum Beispiel SortedProperties) und lässt diese von Properties erben.
Bedingt durch die Kapselung ist es notwendig, dass die Methoden

private static char toHex(int nibble) ;
private String saveConvert(String theString, boolean escapeSpace);
private static void writeln(BufferedWriter bw, String s);

und Attribute

private static final char[] hexDigit;

in die neue Klasse kopiert werden müssen.

Wir überschreiben die Methode
public synchronized void store(OutputStream out, String comments)

Diese Methode ist für das eigentliche Speichern in eine Datei verantwortlich.

Der neue Inhalt entspricht bist auf eine zusätzliche Sortierung dem alten:


public synchronized void store(OutputStream out, String comments)
throws IOException {

TreeMap propTree = new TreeMap();

for (Enumeration e = keys(); e.hasMoreElements();) {
String key = (String) e.nextElement();
String value = (String) get(key);
key = saveConvert(key, true);
value = saveConvert(value, false);
propTree.put(key, value);
}
BufferedWriter awriter;
awriter = new BufferedWriter(new OutputStreamWriter(out, "8859_1"));
if (comments != null)
writeln(awriter, "#" + comments);
writeln(awriter, "#" + new Date().toString());
Set keys = propTree.keySet();
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
writeln(awriter, key + "=" + propTree.get(key));
}
awriter.flush();
}

Dies ist tatsächlich ein sehr einfacher Weg, um vorhandene Java-Methoden für eigene Zwecke anzupassen.

Blogged with the Flock Browser

GnuPG Java Wrapper API

Yaniv Yemini wrote a small GnuPG Java Wrapper API. Just had a small look over it. So to get it your version from here: http://www.macnews.co.il/mageworks/java/gnupg Here is just a small demo:
import javax.swing.JOptionPane;

import org.gpg.java.GnuPG;

public class Loader {

public static void main (String args[]){
	GnuPG pgp = new GnuPG ();
		
	String toolChain[] = {"sign", "clearsign", "signAndEncrypt", "encrypt", "decrypt"};
	String message = JOptionPane.showInputDialog(null, "Message you want to encrypt?", "Enter your message", JOptionPane.QUESTION_MESSAGE);
	String keyID = "0x56B69D6B";
	System.out.println("using message: "+message);
	System.out.println("using key ID: "+keyID);
	for(String tool : toolChain){
		System.out.println("running: "+tool);
		if(tool.equals("sign")){
			String passPhrase = enterPassPhrase(tool);
			pgp.sign (message, passPhrase);				
		}

		if(tool.equals("clearsign")){
			String passPhrase = enterPassPhrase(tool);
			pgp.clearSign (message, passPhrase);				
		}			
		if(tool.equals("signAndEncrypt")){
			String passPhrase = enterPassPhrase(tool);
			pgp.signAndEncrypt (message, keyID, passPhrase);				
		}
		if(tool.equals("encrypt")){
			pgp.encrypt (message, keyID);				
		}	
		if(tool.equals("decrypt")){
			String passPhrase = enterPassPhrase(tool);
			pgp.decrypt (message, passPhrase);				
		}				
		System.out.println("result: " + pgp.getGpg_result() + "\n\n");
		System.out.println("error: " + pgp.getGpg_err() + "\n\n");
		System.out.println("exit: " + pgp.getGpg_exitCode() + "\n\n");
	}
}
    
    public static String enterPassPhrase(String usage){
    	return JOptionPane.showInputDialog(null, "Please enter the Passphrase of your private Key for "+usage, "Passphrase", JOptionPane.QUESTION_MESSAGE);
    }

}
Unforntunetally there is a Problem with decrypting a message. It is possible to decrypt the String with the gpg CI Version, but within Java it does not work. So maybe the error is on my site :-).
Blogged with the Flock Browser

About March 2009

This page contains all entries posted to Philipps paper equivalent Blog in March 2009. They are listed from oldest to newest.

February 2009 is the previous archive.

May 2009 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.31