gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r18411 - in gnunet-java: . .settings src/org/gnunet/constru


From: gnunet
Subject: [GNUnet-SVN] r18411 - in gnunet-java: . .settings src/org/gnunet/construct src/org/gnunet/construct/parsers src/org/gnunet/messages src/org/gnunet/service src/org/gnunet/util src/org/gnunet/util/datastructures test/org/gnunet/construct
Date: Thu, 1 Dec 2011 02:00:29 +0100

Author: dold
Date: 2011-12-01 02:00:29 +0100 (Thu, 01 Dec 2011)
New Revision: 18411

Added:
   gnunet-java/src/org/gnunet/construct/ByteFill.java
   gnunet-java/src/org/gnunet/construct/Fill.java
   gnunet-java/src/org/gnunet/construct/FixedSizeArray.java
   gnunet-java/src/org/gnunet/construct/FrameSize.java
   gnunet-java/src/org/gnunet/construct/Int16.java
   gnunet-java/src/org/gnunet/construct/Int32.java
   gnunet-java/src/org/gnunet/construct/Int64.java
   gnunet-java/src/org/gnunet/construct/Int8.java
   gnunet-java/src/org/gnunet/construct/Integer.java
   gnunet-java/src/org/gnunet/construct/Nested.java
   gnunet-java/src/org/gnunet/construct/UInt16.java
   gnunet-java/src/org/gnunet/construct/UInt32.java
   gnunet-java/src/org/gnunet/construct/UInt64.java
   gnunet-java/src/org/gnunet/construct/UInt8.java
   gnunet-java/src/org/gnunet/construct/VariableSizeArray.java
   gnunet-java/src/org/gnunet/construct/ZeroTerminatedString.java
   gnunet-java/src/org/gnunet/construct/parsers/
   gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java
   gnunet-java/src/org/gnunet/construct/parsers/FieldParser.java
   gnunet-java/src/org/gnunet/construct/parsers/FillParser.java
   gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java
   gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java
   gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java
   gnunet-java/src/org/gnunet/construct/parsers/Parser.java
   gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java
   gnunet-java/src/org/gnunet/construct/parsers/StringParser.java
   gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java
   gnunet-java/src/org/gnunet/messages/StringMessage.java
Removed:
   gnunet-java/src/org/gnunet/construct/FieldLocation.java
   gnunet-java/src/org/gnunet/construct/FillParser.java
   gnunet-java/src/org/gnunet/construct/FixedSizeArrayParser.java
   gnunet-java/src/org/gnunet/construct/Location.java
   gnunet-java/src/org/gnunet/construct/ObjectParser.java
   gnunet-java/src/org/gnunet/construct/Parser.java
   gnunet-java/src/org/gnunet/construct/RefLocation.java
   gnunet-java/src/org/gnunet/construct/SignedIntegerParser.java
   gnunet-java/src/org/gnunet/construct/StringParser.java
   gnunet-java/src/org/gnunet/construct/TotalSizeParser.java
   gnunet-java/src/org/gnunet/construct/UnsignedIntegerParser.java
   gnunet-java/src/org/gnunet/construct/VariableSizeArrayParser.java
   gnunet-java/src/org/gnunet/messages/ComplexTestMessage.java
   gnunet-java/src/org/gnunet/messages/StringTestMessage.java
   gnunet-java/src/org/gnunet/messages/TestMessage3.java
   gnunet-java/src/org/gnunet/messages/TestMessage4.java
Modified:
   gnunet-java/.settings/org.eclipse.jdt.ui.prefs
   gnunet-java/ISSUES
   gnunet-java/src/org/gnunet/construct/Construct.java
   gnunet-java/src/org/gnunet/messages/Message.java
   gnunet-java/src/org/gnunet/messages/MessageHeader.java
   gnunet-java/src/org/gnunet/messages/QueryMessage.java
   gnunet-java/src/org/gnunet/messages/RelativeTimeNBO.java
   gnunet-java/src/org/gnunet/messages/SimpleTestMessage.java
   gnunet-java/src/org/gnunet/messages/SimpleTestMessage2.java
   gnunet-java/src/org/gnunet/messages/SizeTestMessage.java
   gnunet-java/src/org/gnunet/service/StatisticsService.java
   gnunet-java/src/org/gnunet/util/AbsoluteTime.java
   gnunet-java/src/org/gnunet/util/Client.java
   gnunet-java/src/org/gnunet/util/Configuration.java
   gnunet-java/src/org/gnunet/util/MessageHandler.java
   gnunet-java/src/org/gnunet/util/Program.java
   gnunet-java/src/org/gnunet/util/Receiver.java
   gnunet-java/src/org/gnunet/util/RelativeTime.java
   gnunet-java/src/org/gnunet/util/Scheduler.java
   gnunet-java/src/org/gnunet/util/TransmitReadyNotify.java
   gnunet-java/src/org/gnunet/util/datastructures/BloomFilter.java
   gnunet-java/test/org/gnunet/construct/ConstructTest.java
Log:


Modified: gnunet-java/.settings/org.eclipse.jdt.ui.prefs
===================================================================
--- gnunet-java/.settings/org.eclipse.jdt.ui.prefs      2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/.settings/org.eclipse.jdt.ui.prefs      2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -1,4 +1,4 @@
-#Sun Nov 06 13:14:08 CET 2011
+#Mon Nov 28 16:34:22 CET 2011
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -12,9 +12,9 @@
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=false
 cleanup.always_use_this_for_non_static_method_access=false
-cleanup.convert_to_enhanced_for_loop=false
-cleanup.correct_indentation=false
-cleanup.format_source_code=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.correct_indentation=true
+cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
@@ -30,7 +30,7 @@
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
 cleanup.remove_private_constructors=true
-cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
 cleanup.remove_unnecessary_casts=true
@@ -41,11 +41,11 @@
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
-cleanup.sort_members=false
+cleanup.sort_members=true
 cleanup.sort_members_all=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
-cleanup.use_parentheses_in_expressions=false
+cleanup.use_parentheses_in_expressions=true
 cleanup.use_this_for_non_static_field_access=false
 cleanup.use_this_for_non_static_field_access_only_if_necessary=true
 cleanup.use_this_for_non_static_method_access=false

Modified: gnunet-java/ISSUES
===================================================================
--- gnunet-java/ISSUES  2011-11-30 15:21:36 UTC (rev 18410)
+++ gnunet-java/ISSUES  2011-12-01 01:00:29 UTC (rev 18411)
@@ -22,17 +22,6 @@
   * what about spaces in filenames? quotes in config values?
   * formal spec of syntax?
 
-* binary message parsing:
- * use DSL (eg. Xtext)
- * use hand-written parsers
- * use dynamically construct parsers at runtume from composable matchers (cf. 
pythons construct library)
-  * flexible
-  * slow
- * generate parsers from java files using annotations
-  * is java flexible enough for this?
-   * cannot generate interfaces / add new members
-   
-
 * error handling: what to do with io errors in some cases?
 
 * process priority
@@ -43,17 +32,6 @@
 
 
 
-* exception handling in statically used classes (scheduler)
- * solution: singleton? => static {} - blocks?
- 
- 
- 
- 
- * advantages of the "new" parsing/unparsing package
-  * parsers are decoupled from annotations
-    * => parsers could be pre-compiled
-  * parsers are only constructed once per class
- 
- 
-* what about TotalSize?
- 
\ No newline at end of file
+* exception hierarchy in Construct
+
+

Added: gnunet-java/src/org/gnunet/construct/ByteFill.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/ByteFill.java                          
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/ByteFill.java  2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,18 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Fills a byte array with the rest of the message in the current frame.
+ * 
+ * @author Florian Dold
+ * 
+ */
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface ByteFill {
+}
+

Modified: gnunet-java/src/org/gnunet/construct/Construct.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Construct.java 2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/construct/Construct.java 2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -1,14 +1,22 @@
 package org.gnunet.construct;
 
 import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
 import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.gnunet.construct.parsers.ByteFillParser;
+import org.gnunet.construct.parsers.FieldParser;
+import org.gnunet.construct.parsers.FixedSizeArrayParser;
+import org.gnunet.construct.parsers.IntegerParser;
+import org.gnunet.construct.parsers.NestedParser;
+import org.gnunet.construct.parsers.Parser;
+import org.gnunet.construct.parsers.SequenceParser;
+import org.gnunet.construct.parsers.StringParser;
+import org.gnunet.messages.Message;
+import org.grothoff.Runabout;
 
 /**
  * A version of Python's construct library for Java.
@@ -19,247 +27,196 @@
  *       annotations (int16, int32, uint64, etc.)
  * @TODO error handling (exceptions?), documentation
  * @TODO performance evaluation
- * @TODO add an Order(n) annotation if there's a java implementation out there
- *       that reorders fields
  */
 public class Construct {
-    private static final Logger logger = LoggerFactory
-            .getLogger(Construct.class);
 
-    /**
-     * Thrown if a parser requires more space in the buffer.
-     * 
-     * @author Florian Dold
-     * 
-     */
-    static class SizeError extends RuntimeException {
+    private static HashMap<Class<? extends Message>, Parser> parserCache = new 
HashMap<Class<? extends Message>, Parser>();
 
-    }
-
     /**
-     * Embed another constructable message.
+     * Given a byte array with a message, parse it into an object of type c. 
The
+     * fields of the class are expected to be annotated with annotations from
+     * the construct package.
      * 
-     * @author Florian Dold
-     * 
+     * @param data
+     *            serialized binary object data
+     * @param offset
+     *            where the message starts in data
+     * @param c
+     *            desired object type to return
+     * @return instance of the desired object type
+     * @throws RuntimeException
+     *             (ugh)
      */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface Nested {
-        boolean header() default false;
+    public static <T extends Message> T parseAs(byte[] data, int offset,
+            Class<T> c) {
+        Parser p = getParser(c);
+        T m;
+        try {
+            m = (T) c.newInstance();
+        } catch (InstantiationException e) {
+            throw new RuntimeException();
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException();
+        }
+        p.parse(data, offset, 0, m);
+        return m;
     }
 
+    
     /**
-     * Acceptable targets: byte, short, int, long, BigInteger.
      * 
-     * @author Florian Dold
      * 
+     * @param c
+     * @return
      */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface SignedInteger {
-        /**
-         * number of bits in this signed integer, only multiples of 8 are
-         * permitted.
-         */
-        int value() default 4;
-    }
+    public static Parser getParser(Class<? extends Message> c) {
 
-    /**
-     * Stores and retrieves the size of the enclosing message.
-     * 
-     * @author Florian Dold
-     * 
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface TotalSize {
+        if (parserCache.containsKey(c)) {
+            return parserCache.get(c);
+        }
 
-    }
+        Parser p = getParser(c, new ParserGenerator());
 
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface FixedSizeArray {
-        int length();
+        parserCache.put(c, p);
+
+        return p;
     }
 
-    /**
-     * Acceptable targets: byte, short, int, long, BigInteger.
-     * 
-     * @author Florian Dold
-     * 
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface UnsignedInteger {
-        int value() default 4;
+    public static Parser getParser(Class<? extends Message> c,
+            ParserGenerator pg) {
 
-        // if useSignBit is true, the sign bit may be used to store a bit
-        // of an unsigned number (this makes the number negative), if 
useSignBit
-        // is false
-        // an error is signaled if the sign of the target field is set
-        boolean useSignBit() default true;
-    }
+        SequenceParser parser = new SequenceParser(null);
 
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface VariableSizeArray {
-        // set to empty string to make the array extend to fill the available
-        // space
-        String lengthField();
-    }
+        Field[] fs = c.getFields();
+        for (Field f : fs) {
+            Annotation[] as = f.getAnnotations();
+            if (as.length == 0) {
+                continue;
+            }
+            pg.field = f;
+            pg.annotations = as;
+            pg.annotationsIdx = 0;
 
-    /**
-     * Parse and unparse a zero-terminated string with the specified encoding.
-     * 
-     * @author Florian Dold
-     * 
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    public @interface ZeroTerminatedString {
+            pg.visitAppropriate(as[0]);
 
-        String charset() default "UTF-8";
-    }
+            parser.add(pg.parser);
 
-    /**
-     * Fills a byte array with the rest of the message in the buffer.
-     * 
-     * @author Florian Dold
-     * 
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface Fill {
-    }
+        }
 
-    public static <T> T parseWith(Parser p, byte[] data, int offset) {
-        RefLocation rl = new RefLocation();
-        Location[] locs = { rl };
-        p.parse(data, offset, locs);
-        return (T) rl.get();
+        return parser;
     }
 
-    public static Parser makeParser(Class cls) {
-        // TODO: caching
+    public static class ParserGenerator extends Runabout {
 
-        ObjectParser op = new ObjectParser(cls);
+        Field field;
+        Annotation[] annotations;
+        int annotationsIdx;
 
-        // adds the size of the child parser's object so specific locations
-        TotalSizeParser tsp = new TotalSizeParser(op);
+        FieldParser parser;
 
-        for (Field f : cls.getDeclaredFields()) {
-            Annotation[] anns = f.getAnnotations();
-            if (anns.length == 0) {
-                continue;
-            }
+        List<Field> total_size_path;
 
-            if (anns[0] instanceof TotalSize) {
-                Parser child = getFieldParser(f.getType(), anns, 1);
-                tsp.addSizeField(child, f);
-                op.add(child, f);
-            } else if (anns[0] instanceof VariableSizeArray) {
-                VariableSizeArray ann = (VariableSizeArray) anns[0];
-                Parser child = getFieldParser(f.getType().getComponentType(), 
anns, 1);
-                Parser p = new VariableSizeArrayParser(child);
-                
-                try {
-                    op.add(p, f, cls.getDeclaredField(ann.lengthField()));
-                } catch (SecurityException e) {
-                   throw new RuntimeException();
-                } catch (NoSuchFieldException e) {
-                    throw new RuntimeException();
-                }
-                
-            } else {
-                Parser p = getFieldParser(f.getType(), anns, 0);
-                op.add(p, f);
+        List<Field> path = new LinkedList<Field>();
+
+        private ParserGenerator() {
+        }
+
+        public void visitDefault(Object o) {
+            throw new RuntimeException("unexpected annotation");
+        }
+
+        public void visit(FrameSize ts) {
+            // set total_size_path to path
+
+            total_size_path = new LinkedList<Field>(path);
+            total_size_path.add(field);
+
+            annotationsIdx++;
+            if (annotationsIdx >= annotations.length) {
+                throw new RuntimeException();
             }
+            visitAppropriate(annotations[annotationsIdx]);
 
         }
-        return tsp;
-    }
 
-    /**
-     * get a "simple" parser that only writes to the field in question and has
-     * no other arguments
-     * 
-     * @param f
-     * @param anns
-     * @param start
-     * @return
-     */
-    public static Parser getFieldParser(Class cls, Annotation[] anns, int 
start) {
-        for (int i = start; i < anns.length; ++i) {
-            Annotation ann = anns[i];
-            if (ann instanceof SignedInteger) {
-                if (i != anns.length - 1) {
-                    throw new RuntimeException(
-                            "Further annotations are forbidden after 
@SignedInteger");
-                }
-                SignedInteger a = (SignedInteger) ann;
-                return new SignedIntegerParser(a.value());
-            } else if (ann instanceof UnsignedInteger) {
-                if (i != anns.length - 1) {
-                    throw new RuntimeException(
-                            "Further annotations are forbidden after 
@UnignedInteger");
-                }
-                UnsignedInteger a = (UnsignedInteger) ann;
-                return new UnsignedIntegerParser(a.value());
-            } else if (ann instanceof ZeroTerminatedString) {
-                if (i != anns.length - 1) {
-                    throw new RuntimeException(
-                            "Further annotations are forbidden after 
@ZeroTerminatedString");
-                }
-                ZeroTerminatedString a = (ZeroTerminatedString) ann;
-                return new StringParser();
-            } else if (ann instanceof TotalSize) {
-                throw new UnsupportedOperationException(
-                        "total size not yet implemented");
+        // Integer Types
 
-            } else if (ann instanceof Nested) {
-                // this needs to be the last annotation
-                if (i != anns.length - 1) {
-                    throw new RuntimeException(
-                            "Futher annotations are forbidden after @Nested");
-                }
-                Parser child = makeParser(cls);
-                return child;
+        public void visit(UInt8 i) {
+            parser = new IntegerParser(1, IntegerParser.UNSIGNED, field);
+        }
 
-            } else if (ann instanceof FixedSizeArray) {
-                FixedSizeArray a = (FixedSizeArray) ann;
-                Parser fp = getFieldParser(cls.getComponentType(), anns,
-                        start + 1);
-                return new FixedSizeArrayParser(a.length(), fp);
-            } else if (ann instanceof Fill) {
-                Parser fp = getFieldParser(cls.getComponentType(), anns,
-                        start + 1);
-                return new FillParser(fp);
-            } else {
-                throw new RuntimeException("unknown construct annotation: "
-                        + ann.getClass());
+        public void visit(UInt16 i) {
+            parser = new IntegerParser(2, IntegerParser.UNSIGNED, field);
+        }
+
+        public void visit(UInt32 i) {
+            parser = new IntegerParser(4, IntegerParser.UNSIGNED, field);
+        }
+
+        public void visit(UInt64 i) {
+            parser = new IntegerParser(8, IntegerParser.UNSIGNED, field);
+        }
+
+        public void visit(Int8 i) {
+            parser = new IntegerParser(1, IntegerParser.SIGNED, field);
+        }
+
+        public void visit(Int16 i) {
+            parser = new IntegerParser(2, IntegerParser.SIGNED, field);
+        }
+
+        public void visit(Int32 i) {
+            parser = new IntegerParser(4, IntegerParser.SIGNED, field);
+        }
+
+        public void visit(Int64 i) {
+            parser = new IntegerParser(8, IntegerParser.SIGNED, field);
+        }
+
+        public void visit(Integer i) {
+            parser = new IntegerParser(i.byteSize(), i.signed(), field);
+        }
+
+        public void visit(ZeroTerminatedString zts) {
+            parser = new StringParser("UTF-8", field);
+        }
+
+        public void visit(Nested n) {
+
+            Class<? extends Message> ct = (Class<? extends Message>) field
+                    .getType();
+
+            Field old_f = field;
+
+            List<Field> old_path = new ArrayList<Field>(path);
+
+            path.add(field);
+
+            Parser p = getParser(ct, this);
+
+            path = old_path;
+            parser = new NestedParser(p, old_f);
+        }
+
+        public void visit(ByteFill bf) {
+            if (total_size_path == null) {
+                throw new RuntimeException(
+                        "no total size found before variable size element");
             }
+
+            parser = new ByteFillParser(total_size_path, field);
         }
-        throw new RuntimeException("unreachable");
-    }
 
-    /**
-     * Given a byte array with a message, parse it into an object of type c. 
The
-     * fields of the class are expected to be annotated with annotations from
-     * the construct package.
-     * 
-     * @param data
-     *            serialized binary object data
-     * @param offset
-     *            where the message starts in data
-     * @param c
-     *            desired object type to return
-     * @return instance of the desired object type
-     * @throws RuntimeException
-     *             (ugh)
-     */
-    public static <T> T parse(byte[] data, int offset, Class<T> cls) {
-        Parser p = makeParser(cls);
+        public void visit(FixedSizeArray fsa) {
+            Field f = field;
+            int elemNumber = fsa.length();
 
-        return Construct.parseWith(p, data, offset);
+            getParser((Class<? extends Message>) field.getType()
+                    .getComponentType(), this);
+
+            parser = new FixedSizeArrayParser(elemNumber, parser, f);
+        }
+
     }
 
     /**
@@ -267,7 +224,7 @@
      * the object are expected to be annotated with annotations from the
      * construct package.
      * 
-     * @param obj
+     * @param o
      *            object to serialize
      * @param data
      *            where to write the binary object data
@@ -275,26 +232,32 @@
      *            where to start writing data
      * @return number of bytes written to data, -1 on error
      */
-    public static int writeTo(Object obj, byte[] data, int offset) {
-        Parser p = makeParser(obj.getClass());
-        return p.unparse(data, offset, RefLocation.makeLocationsWith(obj));
+    public static int write(Message o, byte[] data, int offset) {
+        Parser p = getParser(o.getClass());
+        return p.write(data, offset, o);
     }
 
     /**
-     * Compute the size of a serialized message object.
+     * Compute the size of a serialized message.
      * 
      * @param o
      *            object to serialize
      * @return number of bytes required, -1 on error
      */
-    public static int estimateSize(Object obj) {
-        Parser p = makeParser(obj.getClass());
-        return p.estimateSize(RefLocation.makeLocationsWith(obj));
+    public static int getSize(Message m) {
+        Parser p = getParser(m.getClass());
+        return p.getSize(m);
     }
 
-    public static byte[] unparse(Object obj) {
-        byte[] data = new byte[estimateSize(obj)];
-        writeTo(obj, data, 0);
-        return data;
+    public static byte[] toBinary(Message m) {
+        byte[] a = new byte[getSize(m)];
+        write(m, a, 0);
+        return a;
     }
+
+    public static void patchSizeFields(Message m) {
+        Parser p = getParser(m.getClass());
+        p.patchSizeFields(m, p.getSize(m));
+    }
+
 }

Deleted: gnunet-java/src/org/gnunet/construct/FieldLocation.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/FieldLocation.java     2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/FieldLocation.java     2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,42 +0,0 @@
-package org.gnunet.construct;
-
-import java.lang.reflect.Field;
-
-public class FieldLocation implements Location {
-    private Field f;
-    private Object o;
-    
-    public FieldLocation(Field f, Object o) {
-        assert f != null;
-        this.f = f;
-        this.o = o;
-    }
-
-    @Override
-    public void put(Object v) {
-        try {
-            f.set(o, v);
-        } catch (IllegalArgumentException e) {
-            throw new RuntimeException();
-        } catch (IllegalAccessException e) {
-            throw new RuntimeException();
-        }
-    }
-
-    @Override
-    public Class getType() {
-        return f.getType();
-    }
-
-    @Override
-    public Object get() {
-        try {
-            return f.get(o);
-        } catch (IllegalArgumentException e) {
-            throw new RuntimeException();
-        } catch (IllegalAccessException e) {
-            throw new RuntimeException();
-        }
-    }
-
-}

Added: gnunet-java/src/org/gnunet/construct/Fill.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Fill.java                              
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Fill.java      2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,17 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Fills a byte array with the rest of the message in the buffer.
+ * 
+ * @author Florian Dold
+ * 
+ */
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Fill {
+}

Deleted: gnunet-java/src/org/gnunet/construct/FillParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/FillParser.java        2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/FillParser.java        2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,90 +0,0 @@
-package org.gnunet.construct;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Parse an array that takes up all the available space.
- * 
- * @author Florian Dold
- * 
- */
-public class FillParser implements Parser {
-    Parser p;
-
-    public FillParser(Parser p) {
-        this.p = p;
-    }
-
-    @Override
-    public int parse(byte[] src_data, int offset, Location[] dst) {
-        assert dst.length == 1;
-        Location loc = dst[0];
-        
-        assert loc.getType().isArray();
-        
-        int parsed = 0;
-        
-        
-        List<Object> lst = new ArrayList<Object>();
-        
-        while (true) {
-            RefLocation rl = new RefLocation(loc.getType().getComponentType());
-            Location[] locs = {rl};
-            
-            try {
-            parsed += p.parse(src_data, offset+parsed, locs);
-            } catch (Construct.SizeError e) {
-                break;
-            }
-            
-            lst.add(rl.get());
-        }
-        
-        Object arr = Array.newInstance(loc.getType().getComponentType(), 
lst.size());
-        
-        for (int i = 0; i < lst.size(); ++i) {
-            Array.set(arr, i, lst.get(i));
-        }
-        
-        loc.put(arr);
-        
-        return parsed;
-    }
-
-    @Override
-    public int unparse(byte[] dst_data, int offset, Location[] src) {
-        assert src.length == 1;
-
-        Object arr = src[0].get();
-        int parsed = 0;
-
-        for (int i = 0; i < Array.getLength(arr); ++i) {
-            RefLocation rl = new 
RefLocation(arr.getClass().getComponentType());
-            rl.put(Array.get(arr, i));
-            Location[] locs = { rl };
-            parsed += p.unparse(dst_data, offset, locs);
-            offset += p.parse(dst_data, offset, locs);
-        }
-
-        return parsed;
-    }
-
-    @Override
-    public int estimateSize(Location[] args) {
-        assert args.length == 1;
-        int accum = 0;
-        Object arr = args[0].get();
-        for (int i = 0; i < Array.getLength(arr); ++i) {
-            RefLocation rl = new RefLocation();
-            rl.put(Array.get(arr, i));
-            Location[] locs = { rl };
-            accum += p.estimateSize(locs);
-        }
-        return accum;
-
-    }
-
-}

Added: gnunet-java/src/org/gnunet/construct/FixedSizeArray.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/FixedSizeArray.java                    
        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/FixedSizeArray.java    2011-12-01 
01:00:29 UTC (rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface FixedSizeArray {
+    int length();
+}

Deleted: gnunet-java/src/org/gnunet/construct/FixedSizeArrayParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/FixedSizeArrayParser.java      
2011-11-30 15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/FixedSizeArrayParser.java      
2011-12-01 01:00:29 UTC (rev 18411)
@@ -1,67 +0,0 @@
-package org.gnunet.construct;
-
-import java.lang.reflect.Array;
-
-public class FixedSizeArrayParser implements Parser {
-    
-    private Parser p;
-    private int size;
-    
-    public FixedSizeArrayParser(int size, Parser p) {
-        this.p = p;
-        this.size = size;
-    }
-
-    @Override
-    public int parse(byte[] src_data, int offset, Location[] dst) {
-        assert dst.length == 1;
-        Location loc = dst[0];
-        
-        assert loc.getType().isArray();
-        
-        int parsed = 0;
-        
-        Object array = Array.newInstance(loc.getType().getComponentType(), 
size);
-        
-        for (int i = 0; i < size; ++i) {
-            RefLocation rl = new RefLocation(loc.getType().getComponentType());
-            Location[] locs = {rl};
-            parsed += p.parse(src_data, offset+parsed, locs);
-            Array.set(array, i, rl.get());
-        }
-        
-        return parsed;
-    }
-
-    @Override
-    public int unparse(byte[] dst_data, int offset, Location[] src) {
-        assert src.length == 1;
-        
-        Object arr = src[0].get();
-        int parsed = 0;
-        
-        for (int i = 0; i < size; ++i) {
-            RefLocation rl = new 
RefLocation(arr.getClass().getComponentType());
-            rl.put(Array.get(arr, i));
-            Location[] locs = {rl};
-            parsed += p.unparse(dst_data, offset, locs);
-            offset += p.parse(dst_data, offset, locs);
-        }
-        
-        return parsed;
-    }
-
-    @Override
-    public int estimateSize(Location[] args) {
-        assert args.length == 1;
-        int accum = 0;
-        Object arr = args[0].get();
-        for (int i = 0; i < size; ++i) {
-            RefLocation rl = new RefLocation();
-            rl.put(Array.get(arr, i));
-            Location[] locs = {rl};
-            accum += p.estimateSize(locs);
-        }
-        return accum;
-    }
-}

Added: gnunet-java/src/org/gnunet/construct/FrameSize.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/FrameSize.java                         
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/FrameSize.java 2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,18 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 
+ * 
+ * @author Florian Dold
+ * 
+ */
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface FrameSize {
+
+}

Added: gnunet-java/src/org/gnunet/construct/Int16.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Int16.java                             
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Int16.java     2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Int16 {
+
+}

Added: gnunet-java/src/org/gnunet/construct/Int32.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Int32.java                             
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Int32.java     2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Int32 {
+
+}

Added: gnunet-java/src/org/gnunet/construct/Int64.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Int64.java                             
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Int64.java     2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Int64 {
+
+}

Added: gnunet-java/src/org/gnunet/construct/Int8.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Int8.java                              
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Int8.java      2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Int8 {
+
+}

Added: gnunet-java/src/org/gnunet/construct/Integer.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Integer.java                           
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Integer.java   2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,14 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Integer {
+    int byteSize();
+
+    boolean signed();
+}

Deleted: gnunet-java/src/org/gnunet/construct/Location.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Location.java  2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/construct/Location.java  2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -1,15 +0,0 @@
-package org.gnunet.construct;
-
-/**
- *
- * 
- * @author dold
- *
- */
-public interface Location {
-    void put(Object o);
-
-    Object get();
-
-    Class getType();
-}

Added: gnunet-java/src/org/gnunet/construct/Nested.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Nested.java                            
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Nested.java    2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,18 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Embed another constructable message.
+ * 
+ * @author Florian Dold
+ * 
+ */
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Nested {
+    boolean newFrame() default false;
+}
\ No newline at end of file

Deleted: gnunet-java/src/org/gnunet/construct/ObjectParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/ObjectParser.java      2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/ObjectParser.java      2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,155 +0,0 @@
-package org.gnunet.construct;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.gnunet.construct.Construct.UnsignedInteger;
-
-public class ObjectParser implements Parser {
-
-    static class ParserRecord {
-        Parser p;
-        Field[] args;
-
-        public ParserRecord(Parser p, Field... args) {
-            this.p = p;
-            this.args = args;
-        }
-    }
-
-    /*
-     * 
-     * 
-     * class TotalSizeParser implements Parser { }
-     * 
-     * 
-     * // the object parser stores the total size in the parsers before
-     * unparsing. // TotalSize parsers do not affect parsing, except maybe for
-     * consistency checks List<TotalSizeParser> total_size_parsers;
-     */
-
-    // parser with arguments
-    List<ParserRecord> parser_records = new LinkedList<ParserRecord>();
-
-    List<Field> size_fields = new LinkedList<Field>();
-
-    private Class cls;
-
-    public ObjectParser(Class cls) {
-        this.cls = cls;
-    }
-
-    public void add(Parser p, Field... fields) {
-        parser_records.add(new ParserRecord(p, fields));
-    }
-
-    /**
-     * Create locations from the Object's fields we are interested in
-     * 
-     * @param pr
-     * @param obj
-     * @return
-     */
-    private Location[] getLocs(Field[] fs, Object obj) {
-        assert obj != null;
-        Location[] locs = new Location[fs.length];
-        for (int i = 0; i < locs.length; ++i) {
-            locs[i] = new FieldLocation(fs[i], obj);
-        }
-        return locs;
-    }
-
-    public int parse(byte[] data, int offset, Location[] dest) {
-        assert dest.length == 1;
-
-        Location loc = dest[0];
-
-        int parsed = 0;
-        // create new object
-        Object obj;
-        try {
-            obj = cls.newInstance();
-        } catch (IllegalAccessException iae) {
-            throw new RuntimeException(iae);
-        } catch (InstantiationException ie) {
-            throw new RuntimeException(ie);
-        }
-
-        for (ParserRecord pr : this.parser_records) {
-            // create locations from record
-            Location[] locs = getLocs(pr.args, obj);
-            int x = pr.p.parse(data, offset + parsed, locs);
-            assert x >= 0;
-            parsed += x;
-        }
-
-        loc.put(obj);
-
-        return parsed;
-    }
-
-    public int unparse(byte[] data, int offset, Location[] dest) {
-        assert dest.length == 1;
-        Object obj = dest[0].get();
-        assert obj != null;
-
-        int size = Construct.estimateSize(obj);
-
-        int parsed = 0;
-
-        for (ParserRecord pr : this.parser_records) {
-
-            parsed += pr.p
-                    .unparse(data, offset + parsed, getLocs(pr.args, obj));
-        }
-        return parsed;
-    }
-
-    @Override
-    public int estimateSize(Location[] args) {
-
-        assert args.length == 1;
-        Object obj = args[0].get();
-
-        if (obj == null) {
-            throw new RuntimeException(
-                    "cannot deserialize null-reference as object");
-        }
-
-        int size = 0;
-        for (ParserRecord pr : this.parser_records) {
-            // create locations from record
-            Location[] locs = getLocs(pr.args, obj);
-            int x = pr.p.estimateSize(locs);
-            assert x >= 0;
-            size += x;
-        }
-        return size;
-    }
-    
-    public int getParserOffset(Location[] args, Parser p) {
-        assert args.length == 1;
-        Object obj = args[0].get();
-
-        if (obj == null) {
-            throw new RuntimeException(
-                    "cannot deserialize null-reference as object");
-        }
-
-        int size = 0;
-        for (ParserRecord pr : this.parser_records) {
-            if (pr.p == p) {
-                return size;
-            }
-            // create locations from record
-            Location[] locs = getLocs(pr.args, obj);
-            int x = pr.p.estimateSize(locs);
-            assert x >= 0;
-            size += x;
-
-        }
-        throw new RuntimeException("parser not found");
-    }
-}

Deleted: gnunet-java/src/org/gnunet/construct/Parser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Parser.java    2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/construct/Parser.java    2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -1,39 +0,0 @@
-package org.gnunet.construct;
-
-public interface Parser {
-
-    
-    /**
-     * 
-     * 
-     * @param src_data
-     * @param offset
-     * @param dst
-     * @return number of bytes parsed
-     */
-    public int parse(byte[] src_data, int offset, Location[] dst);
-    // public int parse(byte[] src_data, int offset, Object dst); // Field 'f' 
is part of parser instance
-    
-    
-
-    /**
-     * 
-     * @param dst_data
-     * @param offset
-     * @param src
-     * @return number of bytes unparsed
-     */
-    // 'write'? 'serialize'? 
-    public int unparse(byte[] dst_data, int offset, Location[] src);
-    // public int write(byte[] src_data, int offset, Object src); // Field 'f' 
is part of parser instance
-    
-    
-    /**
-     * 
-     * @param args
-     * @return
-     */
-    public int estimateSize(Location[] args); // not estimate! calculate! 
-    // public int sizeof(Object src); // Field 'f' is part of parser instance
-
-}

Deleted: gnunet-java/src/org/gnunet/construct/RefLocation.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/RefLocation.java       2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/RefLocation.java       2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,37 +0,0 @@
-package org.gnunet.construct;
-
-public class RefLocation implements Location {
-    private Object obj;
-    private Class cls;
-    
-    public RefLocation() {
-        this.cls = Object.class;
-    }
-    
-    public RefLocation(Class cls) {
-        this.cls = cls;
-    }
-
-    @Override
-    public void put(Object o) {
-        this.obj = o;
-    }
-
-    @Override
-    public Object get() {
-        return obj;
-    }
-
-    @Override
-    public Class getType() {
-        return cls;
-    }
-    
-    public static Location[] makeLocationsWith(Object obj) {
-        RefLocation rl = new RefLocation(obj.getClass());
-        rl.put(obj);
-        return new Location[]{rl};
-    }
-
-
-}

Deleted: gnunet-java/src/org/gnunet/construct/SignedIntegerParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/SignedIntegerParser.java       
2011-11-30 15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/SignedIntegerParser.java       
2011-12-01 01:00:29 UTC (rev 18411)
@@ -1,98 +0,0 @@
-package org.gnunet.construct;
-
-import java.math.BigInteger;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SignedIntegerParser implements Parser {
-    private static final Logger logger = LoggerFactory
-            .getLogger(SignedIntegerParser.class);
-
-    private final int byte_size;
-
-    public SignedIntegerParser(int byte_size) {
-        this.byte_size = byte_size;
-    }
-
-
-    public int parse(byte[] data, int offset, Location[] dest) {
-        assert dest.length == 1;
-        
-        
-        
-        if (offset + byte_size > data.length) {
-            throw new Construct.SizeError();
-        }
-        
-        
-
-        Location loc = dest[0];
-
-        byte[] num_data = new byte[byte_size];
-
-        System.arraycopy(data, offset, num_data, 0, byte_size);
-        offset += byte_size;
-
-        BigInteger num = new BigInteger(num_data);
-
-        if (loc.getType().equals(BigInteger.class)) {
-            loc.put(num);
-        } else {
-
-            int bit_size;
-            if (loc.getType().equals(Integer.TYPE)) {
-                loc.put(num.intValue());
-                bit_size = 32;
-            } else if (loc.getType().equals(Long.TYPE)) {
-                loc.put(num.longValue());
-                bit_size = 64;
-            } else if (loc.getType().equals(Short.TYPE)) {
-                loc.put(num.shortValue());
-                bit_size = 16;
-            } else if (loc.getType().equals(Byte.TYPE)) {
-                loc.put(num.byteValue());
-                bit_size = 8;
-            } else {
-                throw new RuntimeException(
-                        "construct: target type not supported");
-            }
-
-            if (num.bitLength() > bit_size) {
-                logger.warn("construct: number truncated");
-            }
-        }
-        return byte_size;
-    }
-
-    @Override
-    public int unparse(byte[] dst_data, int offset, Location[] src) {
-        assert src.length == 1;
-        Object obj = src[0].get();
-        BigInteger num;
-        
-        if (obj instanceof BigInteger) {
-            num = (BigInteger) obj;
-        } else if (obj instanceof Number) {
-            num = BigInteger.valueOf(((Number) obj).longValue());
-        } else {
-            throw new RuntimeException("invalid number type");
-        }
-        
-        // +1 for the sign
-        if ((num.bitLength() + 1) > byte_size * 8) {
-            throw new RuntimeException("value to large for serialization");
-        }
-        
-        byte[] buf = num.toByteArray();
-        
-        System.arraycopy(buf, 0, dst_data, offset, byte_size);
-        
-        return byte_size;
-    }
-
-    @Override
-    public int estimateSize(Location[] args) {
-        return byte_size;
-    }
-}

Deleted: gnunet-java/src/org/gnunet/construct/StringParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/StringParser.java      2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/StringParser.java      2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,72 +0,0 @@
-package org.gnunet.construct;
-
-import java.io.UnsupportedEncodingException;
-
-public class StringParser implements Parser {
-    
-    String cset;
-    
-    public StringParser() {
-        this.cset = "UTF-8";
-    }
-    
-    public StringParser(String charset) {
-        this.cset = charset;
-    }
-
-    @Override
-    public int parse(byte[] src_data, int offset, Location[] dst) {
-        assert dst.length == 1;
-        Location loc = dst[0];
-        int length = 0;
-        while (src_data[offset+length] != 0) {
-            length++;
-        }
-        
-        byte[] str_data = new byte[length];
-        
-        System.arraycopy(src_data, offset, str_data, 0, length);
-        
-        String str;
-        try {
-            str = new String(str_data, cset);
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException();
-        }
-        loc.put(str);
-        
-        return length;
-    }
-
-    @Override
-    public int unparse(byte[] dst_data, int offset, Location[] src) {
-        String s = (String) src[0].get();
-        byte[] b;
-        try {
-            b = s.getBytes(cset);
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException();
-        }
-        
-        System.arraycopy(b, 0, dst_data, offset, b.length);
-        
-        dst_data[b.length] = (byte) 0;
-        
-        
-        // +1 for the 0-byte
-        return b.length + 1;  
-    }
-
-    @Override
-    public int estimateSize(Location[] args) {
-        String s = (String) args[0].get();
-        try {
-            byte[] b = s.getBytes(cset);
-            return b.length + 1;
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException();
-        }
-    }
-
-
-}

Deleted: gnunet-java/src/org/gnunet/construct/TotalSizeParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/TotalSizeParser.java   2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/TotalSizeParser.java   2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,69 +0,0 @@
-package org.gnunet.construct;
-
-import java.lang.reflect.Field;
-import java.util.LinkedList;
-import java.util.List;
-
-class ParserWithField {
-    Parser p;
-    Field f;
-}
-
-
-public class TotalSizeParser implements Parser {
-
-    ObjectParser op;
-
-    List<ParserWithField> size_fields = new LinkedList<ParserWithField>();
-
-    public TotalSizeParser(ObjectParser op) {
-        this.op = op;
-    }
-
-    @Override
-    public int parse(byte[] src_data, int offset, Location[] dst) {
-        // the easy case, just set all size_fields to size
-        int size = op.parse(src_data, offset, dst);
-        
-        Object o = dst[0].get();
-        
-        for (ParserWithField pwf : size_fields) {
-            try {
-                pwf.f.set(o, size);
-            } catch (IllegalArgumentException e) {
-                throw new RuntimeException();
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException();
-            }
-        }
-        
-        // TODO: do sanity check on size / consistency
-        return size;
-    }
-
-    @Override
-    public int unparse(byte[] dst_data, int offset, Location[] src) {
-        int size = estimateSize(src);
-        
-        int ret = op.unparse(dst_data, offset, src);
-        
-        for (ParserWithField pwf : size_fields) {
-            int os = op.getParserOffset(src, pwf.p);
-            pwf.p.unparse(dst_data, offset+os, 
RefLocation.makeLocationsWith(size));
-        }
-        return ret;
-    }
-
-    @Override
-    public int estimateSize(Location[] args) {
-        return op.estimateSize(args);
-    }
-
-    public void addSizeField(Parser p, Field f) {
-        ParserWithField pwf = new ParserWithField();
-        pwf.p = p;
-        pwf.f = f;
-        size_fields.add(pwf);
-    }
-
-}

Added: gnunet-java/src/org/gnunet/construct/UInt16.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UInt16.java                            
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/UInt16.java    2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface UInt16 {
+
+}

Added: gnunet-java/src/org/gnunet/construct/UInt32.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UInt32.java                            
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/UInt32.java    2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface UInt32 {
+
+}

Added: gnunet-java/src/org/gnunet/construct/UInt64.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UInt64.java                            
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/UInt64.java    2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface UInt64 {
+
+}

Added: gnunet-java/src/org/gnunet/construct/UInt8.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UInt8.java                             
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/UInt8.java     2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface UInt8 {
+
+}

Deleted: gnunet-java/src/org/gnunet/construct/UnsignedIntegerParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UnsignedIntegerParser.java     
2011-11-30 15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/UnsignedIntegerParser.java     
2011-12-01 01:00:29 UTC (rev 18411)
@@ -1,125 +0,0 @@
-package org.gnunet.construct;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class UnsignedIntegerParser implements Parser {
-    private static final Logger logger = LoggerFactory
-            .getLogger(SignedIntegerParser.class);
-
-    private final int byte_size;
-
-    private boolean allow_sign = true;
-
-    public UnsignedIntegerParser(int byte_size) {
-        this.byte_size = byte_size;
-    }
-
-    public UnsignedIntegerParser(int byte_size, boolean allow_sign) {
-        this.byte_size = byte_size;
-        this.allow_sign = allow_sign;
-    }
-
-    public int parse(byte[] data, int offset, Location[] dest) {
-        assert dest.length == 1;
-
-        if (offset + byte_size > data.length) {
-            throw new Construct.SizeError();
-        }
-
-        Location loc = dest[0];
-
-        // prepend zero, if data has the sign bit set
-        byte[] num_data = new byte[byte_size + 1];
-
-        System.arraycopy(data, offset, num_data, 1, byte_size);
-        offset += byte_size;
-
-        BigInteger num = new BigInteger(num_data);
-
-        if (loc.getType().equals(BigInteger.class)) {
-            loc.put(num);
-        } else {
-
-            int bit_size;
-            
-            if (loc.getType().equals(Integer.TYPE)) {
-                loc.put(num.intValue());
-                bit_size = 32;
-            } else if (loc.getType().equals(Long.TYPE)) {
-                loc.put(num.longValue());
-                bit_size = 64;
-            } else if (loc.getType().equals(Short.TYPE)) {
-                loc.put(num.shortValue());
-                bit_size = 16;
-            } else if (loc.getType().equals(Character.TYPE)) {
-                loc.put((char) num.intValue());
-                bit_size = 16;
-                allow_sign = true; // data type is signed...
-            } else if (loc.getType().equals(Byte.TYPE)) {
-                loc.put(num.byteValue());
-                bit_size = 8;
-            } else {
-                throw new RuntimeException(
-                        "construct: target type not supported: "
-                                + loc.getType());
-            }
-
-            if (allow_sign) {
-                if (num.bitLength() > bit_size) {
-                    logger.warn("construct: number truncated");
-                }
-            } else {
-                // +1 is because java has only signed numbers
-                if (num.bitLength() + 1 > bit_size) {
-                    logger.warn("construct: number truncated");
-                }
-            }
-        }
-        return byte_size;
-    }
-
-    @Override
-    public int unparse(byte[] dst_data, int offset, Location[] src) {
-        assert src.length == 1;
-        Object obj = src[0].get();
-        assert obj != null;
-
-        BigInteger num;
-
-        if (obj instanceof BigInteger) {
-            num = (BigInteger) obj;
-        } else if (obj instanceof Number) {
-            num = BigInteger.valueOf(((Number) obj).longValue());
-        } else {
-            throw new RuntimeException("invalid number type");
-        }
-
-        if (num.signum() == -1) {
-            throw new RuntimeException(
-                    "negative value not allowed for unsigned integer");
-        }
-
-        if (num.bitLength() > byte_size * 8) {
-            throw new RuntimeException("value to large for serialization");
-        }
-
-        byte[] buf = num.toByteArray();
-
-        int dst_pos = offset + (byte_size - buf.length);
-
-        System.arraycopy(buf, 0, dst_data, dst_pos, buf.length);
-
-        Arrays.fill(dst_data, offset, dst_pos, (byte) 0);
-
-        return byte_size;
-    }
-
-    @Override
-    public int estimateSize(Location[] args) {
-        return byte_size;
-    }
-}

Added: gnunet-java/src/org/gnunet/construct/VariableSizeArray.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/VariableSizeArray.java                 
        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/VariableSizeArray.java 2011-12-01 
01:00:29 UTC (rev 18411)
@@ -0,0 +1,14 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface VariableSizeArray {
+    // set to empty string to make the array extend to fill the available
+    // space
+    String lengthField();
+}

Deleted: gnunet-java/src/org/gnunet/construct/VariableSizeArrayParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/VariableSizeArrayParser.java   
2011-11-30 15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/construct/VariableSizeArrayParser.java   
2011-12-01 01:00:29 UTC (rev 18411)
@@ -1,34 +0,0 @@
-package org.gnunet.construct;
-
-public class VariableSizeArrayParser implements Parser {
-    private Parser p;
-    
-    public VariableSizeArrayParser(Parser p) {
-        this.p = p;
-    }
-
-    @Override
-    public int parse(byte[] src_data, int offset, Location[] dst) {
-        assert dst.length == 2;
-        Location loc = dst[0];
-        int size = ((Integer) dst[1].get()).intValue();
-        
-        
-        
-        return 0;
-    }
-
-    @Override
-    public int unparse(byte[] dst_data, int offset, Location[] src) {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int estimateSize(Location[] args) {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-    
-
-}

Added: gnunet-java/src/org/gnunet/construct/ZeroTerminatedString.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/ZeroTerminatedString.java              
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/ZeroTerminatedString.java      
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,16 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Parse and unparse a zero-terminated string with the specified encoding.
+ * 
+ * @author Florian Dold
+ * 
+ */
address@hidden(RetentionPolicy.RUNTIME)
+public @interface ZeroTerminatedString {
+
+    String charset() default "UTF-8";
+}

Added: gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java            
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java    
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,111 @@
+package org.gnunet.construct.parsers;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.util.List;
+
+import org.gnunet.messages.Message;
+
+/**
+ * Parse an array that takes up all the available space.
+ * 
+ * @author Florian Dold
+ * 
+ */
+public class ByteFillParser extends FieldParser {
+    FieldParser p;
+
+    List<Field> totalSizePath;
+
+    public ByteFillParser(List<Field> totalSizePath, Field field) {
+        super(field);
+        this.totalSizePath = totalSizePath;
+    }
+
+    @Override
+    public int getSize(final Message src) {
+        return Array.getLength(getFieldValue(src));
+    }
+
+    public int getSizeFieldValue(Message m) {
+        Object obj = m;
+        for (Field f : totalSizePath) {
+
+            try {
+                obj = f.get(obj);
+            } catch (IllegalArgumentException e) {
+                throw new RuntimeException();
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException();
+            }
+        }
+        return ((Number) obj).intValue();
+    }
+
+    @Override
+    public int parse(final byte[] srcData, final int offset, int frameOffset,
+            final Message dst) {
+        if (frameOffset < 0) {
+            throw new RuntimeException(
+                    "cannot determine remaining message size");
+        }
+
+        int remaining = getSizeFieldValue(dst) - frameOffset;
+
+        byte[] a = new byte[remaining];
+
+        System.arraycopy(srcData, offset, a, 0, remaining);
+
+        setFieldValue(dst, a);
+
+        return frameOffset;
+    }
+
+    @Override
+    public int write(final byte[] dst_data, final int offset, final Message 
src) {
+        byte[] a = (byte[]) getFieldValue(src);
+        System.arraycopy(a, 0, dst_data, offset, a.length);
+        return a.length;
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+        Object obj = m;
+
+        for (int i = 0; i < totalSizePath.size() - 1; ++i) {
+
+            try {
+                obj = totalSizePath.get(i).get(obj);
+            } catch (IllegalArgumentException e) {
+                throw new RuntimeException();
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException();
+            }
+
+        }
+        
+        Field f = totalSizePath.get(totalSizePath.size() - 1);
+
+        try {
+            if (f.getType().equals(Long.TYPE)){
+                f.setLong(obj, frameSize);
+            } else if (f.getType().equals(Integer.TYPE)){
+                f.setInt(obj, frameSize);
+            } else if (f.getType().equals(Short.TYPE)){
+                f.setShort(obj, (short) frameSize);
+            } else if (f.getType().equals(Long.TYPE)){
+                f.setLong(obj, frameSize);
+            } else {
+                throw new RuntimeException("unexpected target type");
+            }
+            
+
+        } catch (IllegalArgumentException e) {
+            throw new RuntimeException(e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException();
+        }
+
+    }
+
+}

Copied: gnunet-java/src/org/gnunet/construct/parsers/FieldParser.java (from rev 
18233, gnunet-java/src/org/gnunet/construct/Parser.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FieldParser.java               
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/FieldParser.java       
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,55 @@
+package org.gnunet.construct.parsers;
+
+import java.lang.reflect.Field;
+
+import org.gnunet.messages.Message;
+
+/**
+ * Convenience super class for all parsers that store their result in the 
field 
+ * of an object.
+ * 
+ * @author Florian Dold
+ * 
+ */
+public abstract class FieldParser implements Parser {
+
+    protected final Field field;
+
+    public FieldParser(final Field f) {
+        this.field = f;
+    }
+
+    public Class getFieldType() {
+        return field.getType();
+    }
+
+    public Object getFieldValue(final Object obj) {
+        try {
+            return field.get(obj);
+        } catch (final IllegalArgumentException e) {
+            throw new RuntimeException();
+        } catch (final IllegalAccessException e) {
+            throw new RuntimeException();
+        }
+    }
+    
+    public Object getFieldValueLong(final Object obj) {
+        try {
+            return field.getLong(obj);
+        } catch (final IllegalArgumentException e) {
+            throw new RuntimeException();
+        } catch (final IllegalAccessException e) {
+            throw new RuntimeException();
+        }
+    }
+    
+    public void setFieldValue(final Object obj, final Object val) {
+        try {
+            field.set(obj, val);
+        } catch (final IllegalArgumentException e) {
+            throw new RuntimeException(e);
+        } catch (final IllegalAccessException e) {
+            throw new RuntimeException();
+        }
+    }
+}

Copied: gnunet-java/src/org/gnunet/construct/parsers/FillParser.java (from rev 
18230, gnunet-java/src/org/gnunet/construct/FillParser.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FillParser.java                
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/FillParser.java        
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,48 @@
+package org.gnunet.construct.parsers;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+import org.gnunet.messages.Message;
+
+/**
+ * Parse an array that takes up all the available space.
+ * 
+ * @author Florian Dold
+ * 
+ */
+public class FillParser extends FieldParser {
+    Parser p;
+
+    public FillParser(final Parser p, final Field f) {
+        super(f);
+        this.p = p;
+
+    }
+
+    @Override
+    public int getSize(final Message src) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int parse(final byte[] src_data, final int offset,
+            int frameOffset, final Message dst) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int write(final byte[] dst_data, final int offset, final Message 
src) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+        // TODO Auto-generated method stub
+        
+    }
+
+}

Copied: gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java 
(from rev 18228, gnunet-java/src/org/gnunet/construct/FixedSizeArrayParser.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java      
                        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java      
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,85 @@
+package org.gnunet.construct.parsers;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+
+import org.gnunet.messages.Message;
+
+public class FixedSizeArrayParser extends FieldParser {
+
+    private final FieldParser elemParser;
+
+    private final int elemNumber;
+
+    public FixedSizeArrayParser(final int elemNumber,
+            final FieldParser elemParser, final Field f) {
+        super(f);
+        this.elemNumber = elemNumber;
+        this.elemParser = elemParser;
+    }
+
+    @Override
+    public int getSize(final Message srcObj) {
+        int size = 0;
+        final Object arr = getFieldValue(srcObj);
+        
+        if (arr == null) {
+            throw new RuntimeException("array not initialized");
+        }
+        
+        for (int i = 0; i < Array.getLength(arr); ++i) {
+            size += elemParser.getSize((Message) Array.get(arr, i));
+        }
+        return size;
+    }
+
+    @Override
+    public int parse(final byte[] srcData, final int offset, int frameOffset,
+            final Message dstObj) {
+        int size = 0;
+
+        final Object arr = Array.newInstance(getFieldType().getComponentType(),
+                elemNumber);
+        setFieldValue(dstObj, arr);
+
+        for (int i = 0; i < elemNumber; ++i) {
+            Message elemObj;
+            try {
+                elemObj = (Message) getFieldType().getComponentType()
+                        .newInstance();
+            } catch (final InstantiationException e) {
+                throw new RuntimeException();
+            } catch (final IllegalAccessException e) {
+                throw new RuntimeException();
+            }
+            
+            Array.set(arr, i, elemObj);
+            
+            size += elemParser.parse(srcData, offset + size,
+                    frameOffset - size, elemObj);
+        }
+
+        return size;
+    }
+
+    @Override
+    public int write(final byte[] dstData, final int offset,
+            final Message srcObj) {
+        int size = 0;
+        final Object arr = getFieldValue(srcObj);
+        for (int i = 0; i < Array.getLength(arr); ++i) {
+            size += elemParser.write(dstData, offset + size,
+                    (Message) Array.get(arr, i));
+        }
+        return size;
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+        final Object arr = getFieldValue(m);
+        for (int i = 0; i < Array.getLength(arr); ++i) {
+            elemParser.patchSizeFields((Message) Array.get(arr, i), frameSize);
+        }
+
+    }
+}

Added: gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java             
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java     
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,123 @@
+package org.gnunet.construct.parsers;
+
+import java.lang.reflect.Field;
+import java.math.BigInteger;
+
+import org.gnunet.messages.Message;
+
+public class IntegerParser extends FieldParser {
+    private final int byteSize;
+    
+    public static final boolean UNSIGNED = false;
+    public static final boolean SIGNED = true;
+    
+    private final boolean isSigned;
+
+    static enum FieldType {
+        BIGNUM, BYTE_PRIM, SHORT_PRIM, INT_PRIM, LONG_PRIM
+    }
+
+    private FieldType ft;
+
+    public IntegerParser(final int byteSize, final boolean isSigned,
+            final Field f) {
+        super(f);
+        this.byteSize = byteSize;
+        this.isSigned = isSigned;
+
+        if (f.getType().equals(BigInteger.class)) {
+            ft = FieldType.BIGNUM;
+        } else if (f.getType().equals(Long.TYPE)) {
+            ft = FieldType.LONG_PRIM;
+        } else if (f.getType().equals(Short.TYPE)) {
+            ft = FieldType.SHORT_PRIM;
+        } else if (f.getType().equals(Integer.TYPE)) {
+            ft = FieldType.INT_PRIM;
+        } else {
+            throw new RuntimeException("target type not supported");
+        }
+    }
+
+    @Override
+    public int getSize(final Message srcObj) {
+        return byteSize;
+    }
+
+    @Override
+    public int parse(final byte[] srcData, int offset, int frameOffset, final 
Message dstObj) {
+        byte[] numData;
+
+        if (isSigned) {
+            numData = new byte[byteSize];
+            System.arraycopy(srcData, offset, numData, 0, byteSize);
+        } else {
+            numData = new byte[byteSize + 1];
+            System.arraycopy(srcData, offset, numData, 1, byteSize);
+        }
+        offset += byteSize;
+
+        final BigInteger num = new BigInteger(numData);
+
+        try {
+
+            switch (ft) {
+            case SHORT_PRIM:
+                field.setShort(dstObj, num.shortValue());
+                break;
+            case INT_PRIM:
+                field.setInt(dstObj, num.intValue());
+                break;
+            case LONG_PRIM:
+                field.setLong(dstObj, num.longValue());
+                break;
+            default:
+                throw new RuntimeException("invalid member type");
+            }
+
+        } catch (IllegalArgumentException e) {
+            throw new RuntimeException();
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException();
+        }
+
+        return byteSize;
+    }
+
+    @Override
+    public int write(final byte[] dstData, final int offset,
+            final Message srcObj) {
+        BigInteger num;
+
+        try {
+            switch (ft) {
+            case INT_PRIM:
+                num = BigInteger.valueOf(field.getInt(srcObj));
+                break;
+            case SHORT_PRIM:
+                num = BigInteger.valueOf(field.getShort(srcObj));
+                break;
+            case LONG_PRIM:
+                num = BigInteger.valueOf(field.getLong(srcObj));
+                break;
+            default:
+                throw new RuntimeException("invalid member type: ");
+            }
+        } catch (IllegalArgumentException e) {
+            throw new RuntimeException();
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException();
+        }
+
+        final byte[] numData = num.toByteArray();
+
+        System.arraycopy(numData, 0, dstData, offset
+                + (byteSize - numData.length), numData.length);
+
+        return byteSize;
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+        return;
+    }
+}

Added: gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java              
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java      
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,48 @@
+package org.gnunet.construct.parsers;
+
+import java.lang.reflect.Field;
+
+import org.gnunet.messages.Message;
+
+public class NestedParser extends FieldParser {
+    private final Parser nestedParser;
+
+    public NestedParser(final Parser p, final Field f) {
+        super(f);
+        this.nestedParser = p;
+    }
+
+    @Override
+    public int getSize(final Message src) {
+        return nestedParser.getSize((Message) getFieldValue(src));
+    }
+
+    @Override
+    public int parse(final byte[] src_data, final int offset,
+            int frameOffset, final Message dstObj) {
+        try {
+            setFieldValue(dstObj, getFieldType().newInstance());
+        } catch (InstantiationException e) {
+            throw new RuntimeException();
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException();
+        }
+
+        return nestedParser.parse(src_data, offset, frameOffset,
+                (Message) getFieldValue(dstObj));
+    }
+
+    @Override
+    public int write(final byte[] dst_data, final int offset, final Message 
src) {
+        return nestedParser.write(dst_data, offset,
+                (Message) getFieldValue(src));
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+        // todo: nested/opaque frames
+        nestedParser.patchSizeFields(m, frameSize);
+        
+    }
+
+}

Added: gnunet-java/src/org/gnunet/construct/parsers/Parser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/Parser.java                    
        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/Parser.java    2011-12-01 
01:00:29 UTC (rev 18411)
@@ -0,0 +1,37 @@
+package org.gnunet.construct.parsers;
+
+import org.gnunet.messages.Message;
+
+
+public interface Parser {
+    /**
+     * Compute the exact size of the object's binary representation in bytes.
+     * 
+     * @param srcObj
+     * @return
+     */
+    public int getSize(Message srcObj);
+
+    /**
+     * 
+     * @param srcData
+     * @param offset
+     * @param frameOffset
+     * @param dstObj
+     * @return
+     */
+    public int parse(byte[] srcData, int offset, int frameOffset, Message 
dstObj);
+
+
+    /**
+     * 
+     * @param dstData
+     * @param offset
+     * @param srcObj
+     * @return
+     */
+    public int write(byte[] dstData, int offset, Message srcObj);
+
+    public void patchSizeFields(Message m, int frameSize);
+
+}

Copied: gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java (from 
rev 18228, gnunet-java/src/org/gnunet/construct/ObjectParser.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java            
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java    
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,56 @@
+package org.gnunet.construct.parsers;
+
+import java.lang.reflect.Field;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.gnunet.messages.Message;
+
+public class SequenceParser extends FieldParser {
+
+    private final List<FieldParser> childParsers = new 
LinkedList<FieldParser>();
+
+    public SequenceParser(final Field f) {
+        super(f);
+    }
+
+    public void add(final FieldParser p) {
+        childParsers.add(p);
+    }
+
+    @Override
+    public int getSize(final Message src) {
+        int size = 0;
+        for (final FieldParser p : childParsers) {
+            size += p.getSize(src);
+        }
+        return size;
+    }
+
+    @Override
+    public int parse(final byte[] src_data, final int offset, int frameOffset,
+            final Message dst) {
+        int size = 0;
+        for (final FieldParser p : childParsers) {
+            size += p.parse(src_data, offset + size, frameOffset + size, dst);
+        }
+        return size;
+    }
+
+    @Override
+    public int write(final byte[] dst_data, final int offset, final Message 
src) {
+        int size = 0;
+        for (final FieldParser p : childParsers) {
+            size += p.write(dst_data, offset + size, src);
+        }
+        return size;
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+        for (final FieldParser p : childParsers) {
+            p.patchSizeFields(m, frameSize);
+        }
+        
+    }
+}

Copied: gnunet-java/src/org/gnunet/construct/parsers/StringParser.java (from 
rev 18228, gnunet-java/src/org/gnunet/construct/StringParser.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/StringParser.java              
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/StringParser.java      
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,77 @@
+package org.gnunet.construct.parsers;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+
+import org.gnunet.messages.Message;
+
+public class StringParser extends FieldParser {
+
+    String cset;
+
+    public StringParser(final String charset, final Field f) {
+        super(f);
+        this.cset = charset;
+    }
+
+    @Override
+    public int getSize(final Message srcObj) {
+        final String s = (String) getFieldValue(srcObj);
+        try {
+            final byte[] b = s.getBytes(cset);
+            return b.length + 1;
+        } catch (final UnsupportedEncodingException e) {
+            throw new RuntimeException();
+        }
+    }
+
+    @Override
+    public int parse(final byte[] srcData, final int offset, int frameOffset, 
final Message dstObj) {
+        int length = 0;
+        while (srcData[offset + length] != 0) {
+            length++;
+        }
+
+
+        final byte[] stringData = new byte[length];
+
+        System.arraycopy(srcData, offset, stringData, 0, length);
+
+        String str;
+        try {
+            str = new String(stringData, cset);
+        } catch (final UnsupportedEncodingException e) {
+            throw new RuntimeException();
+        }
+
+        setFieldValue(dstObj, str);
+
+        return length + 1;
+    }
+
+    @Override
+    public int write(final byte[] dstData, final int offset, final Message 
srcObj) {
+        final String s = (String) getFieldValue(srcObj);
+        byte[] b;
+        try {
+            b = s.getBytes(cset);
+        } catch (final UnsupportedEncodingException e) {
+            throw new RuntimeException();
+        }
+
+        System.arraycopy(b, 0, dstData, offset, b.length);
+        
+        System.out.println(b.length);
+
+        dstData[offset + b.length] = (byte) 0;
+
+        // +1 for the 0-byte
+        return b.length + 1;
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+        return;
+    }
+
+}

Copied: 
gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java (from 
rev 18223, gnunet-java/src/org/gnunet/construct/VariableSizeArrayParser.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java   
                        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java   
2011-12-01 01:00:29 UTC (rev 18411)
@@ -0,0 +1,89 @@
+package org.gnunet.construct.parsers;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+
+import org.gnunet.messages.Message;
+
+public class VariableSizeArrayParser extends FieldParser {
+    private final FieldParser elemParser;
+    private Field sizeField;
+
+
+    public VariableSizeArrayParser(final FieldParser elemParser, Field 
sizeField, Field arrayField) {
+        super(arrayField);
+        this.elemParser = elemParser;
+        this.sizeField = sizeField;
+    }
+
+    @Override
+    public int getSize(final Message src) {
+        int size = 0;
+        final Object arr = getFieldValue(src);
+        
+        if (arr == null) {
+            throw new RuntimeException("array not initialized");
+        }
+        
+        
+        for (int i = 0; i < Array.getLength(arr); ++i) {
+            size += elemParser.getSize((Message) Array.get(arr, i));
+        }
+        return size;
+    }
+
+    @Override
+    public int parse(final byte[] srcData, final int offset, int frameOffset, 
final Message dstObj) {
+        int elemNumber;
+        try {
+            elemNumber = ((Number) sizeField.get(dstObj)).intValue();
+        } catch (IllegalArgumentException e1) {
+            throw new RuntimeException();
+        } catch (IllegalAccessException e1) {
+            throw new RuntimeException();
+        }
+        
+        int size = 0;
+
+        final Object arr = Array.newInstance(getFieldType().getComponentType(),
+                elemNumber);
+        setFieldValue(dstObj, arr);
+
+        for (int i = 0; i < elemNumber; ++i) {
+            Message elemObj;
+            try {
+                elemObj = (Message) getFieldType().getComponentType()
+                        .newInstance();
+            } catch (final InstantiationException e) {
+                throw new RuntimeException();
+            } catch (final IllegalAccessException e) {
+                throw new RuntimeException();
+            }
+            
+            Array.set(arr, i, elemObj);
+            
+            size += elemParser.parse(srcData, offset + size,
+                    frameOffset - size, elemObj);
+        }
+
+        return size;
+    }
+
+    @Override
+    public int write(final byte[] dstData, final int offset, final Message 
src) {
+        int size = 0;
+        final Object arr = getFieldValue(src);
+        for (int i = 0; i < Array.getLength(arr); ++i) {
+            size += elemParser.write(dstData, offset + size,
+                    (Message) Array.get(arr, i));
+        }
+        return size;
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+        //XXX: should this patch the length field, too?
+        return;
+    }
+
+}

Deleted: gnunet-java/src/org/gnunet/messages/ComplexTestMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/ComplexTestMessage.java 2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/ComplexTestMessage.java 2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,92 +0,0 @@
-package org.gnunet.messages;
-
-import org.gnunet.construct.Construct.FixedSizeArray;
-import org.gnunet.construct.Construct.Nested;
-import org.gnunet.construct.Construct.TotalSize;
-import org.gnunet.construct.Construct.UnsignedInteger;
-import org.gnunet.construct.Construct.VariableSizeArray;
-import org.gnunet.construct.Construct.ZeroTerminatedString;
-import org.gnunet.construct.FixedSizeArrayParser;
-import org.gnunet.construct.ObjectParser;
-import org.gnunet.construct.StringParser;
-import org.gnunet.construct.UnsignedIntegerParser;
-import org.gnunet.construct.VariableSizeArrayParser;
-
-public class ComplexTestMessage implements Message  {
-
-    @UnsignedInteger(2)
-    int someNumber;
-
-    @FixedSizeArray(length = 5)    
-    @UnsignedInteger(2) // BAD!
-    int[] someArray;
-
-    // @FixedSizeArrayUint32_t(length = 5)
-    int[] someArray3;
-
-    
-    @FixedSizeArray(length = 5)    
-    UnsignedIntegerBox[] someArray2;
-    
-    static class UnsignedIntegerBox implements Message {
-        @UnsignedInteger(2)
-        int my_value;
-    }
-    
-    @FixedSizeArray(length = 5)    
-    SimpleTestMessage[] someArray5;
-    
-    
-    @Nested
-    SimpleTestMessage msg;
-    
-    
-    @UnsignedInteger(2)
-    int stringTableSize;
-
-    @VariableSizeArray(lengthField = "stringTableSize")
-    @ZeroTerminatedString(charset = "UTF-8")
-    String[] stringTable;
-    
-
-    @TotalSize
-    int mySize;
-
-    @TotalSize
-    @UnsignedInteger(2)
-    int storedMySize;
-       
-    
-
-    // this should work fully automatic
-    public static ObjectParser makeParser() throws SecurityException,
-            NoSuchFieldException {
-        
-        ObjectParser p = new ObjectParser(ComplexTestMessage.class);
-
-        p.add(new UnsignedIntegerParser(2),
-                ComplexTestMessage.class.getField("someNumber"));
-
-        FixedSizeArrayParser ap = new FixedSizeArrayParser(5,
-                new UnsignedIntegerParser(2));
-
-        p.add(ap, ComplexTestMessage.class.getField("someArray"));
-
-        VariableSizeArrayParser lp = new VariableSizeArrayParser(
-                new StringParser());
-
-        // arguments: resulting array, array length
-        p.add(lp, ComplexTestMessage.class.getField("stringTable"),
-                ComplexTestMessage.class.getField("stringTableSize"));
-
-        //p.addSizeField(ComplexTestMessage.class.getField("mySize"));
-
-        p.add(new UnsignedIntegerParser(2),
-                ComplexTestMessage.class.getField("storedMySize"));
-
-        //p.addSizeField(ComplexTestMessage.class.getField("storedMySize"));
-
-        return p;
-    }
-
-}

Modified: gnunet-java/src/org/gnunet/messages/Message.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/Message.java    2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/messages/Message.java    2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -1,8 +1,9 @@
 package org.gnunet.messages;
 
 /**
- * Base interface for all messages (anything that 'Construct' can serialize or 
deserialize).
- * Really just an annotation, but also for sanity checking by the compiler.
+ * Base interface for all messages (anything that 'Construct' can serialize or
+ * deserialize). Really just an annotation, but also for sanity checking by the
+ * compiler.
  */
 public interface Message {
 }

Modified: gnunet-java/src/org/gnunet/messages/MessageHeader.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/MessageHeader.java      2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/MessageHeader.java      2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,20 +1,15 @@
 package org.gnunet.messages;
 
-import org.gnunet.construct.Construct.TotalSize;
-import org.gnunet.construct.Construct.UnsignedInteger;
+import org.gnunet.construct.FrameSize;
+import org.gnunet.construct.UInt16;
 
 public class MessageHeader implements Message {
 
-    @TotalSize
-       // @UnsignedInteger(2)
-       public int size;
-       
-    @UnsignedInteger(2)
+    @FrameSize
+    @UInt16
+    public int size;
+
+    @UInt16
     public int type;
-    
-    
-    // @Fill
-    // @UnsignedInteger(1)
-    // public byte[] body;
-       
+
 }

Modified: gnunet-java/src/org/gnunet/messages/QueryMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/QueryMessage.java       2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/QueryMessage.java       2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,35 +1,17 @@
 package org.gnunet.messages;
 
-import org.gnunet.construct.Construct.Fill;
-import org.gnunet.construct.Construct.Nested;
-import org.gnunet.construct.Construct.UnsignedInteger;
+import org.gnunet.construct.ByteFill;
+import org.gnunet.construct.Nested;
+import org.gnunet.construct.UInt8;
 
 public class QueryMessage implements Message {
-    
-    @Nested(header = true)
-    MessageHeader header;
-    
-    @UnsignedInteger(2)
-    int query;
 
     @Nested
-    MessageBar embedded;
+    public MessageHeader header;
 
-    @Fill    
-    public char[] varsize;
- 
-    
-    static class MessageBar implements Message 
-    {
+    @UInt8
+    public int query;
 
-        @Nested(header = true)
-        MessageHeader header;
-        
-        @UnsignedInteger(2)
-        int query;
-
-        @Fill    
-        public char[] varsize;
-
-    }
+    @ByteFill
+    public byte[] varsize;
 }

Modified: gnunet-java/src/org/gnunet/messages/RelativeTimeNBO.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/RelativeTimeNBO.java    2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/RelativeTimeNBO.java    2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,22 +1,22 @@
 package org.gnunet.messages;
 
-import org.gnunet.construct.Construct.UnsignedInteger;
+import org.gnunet.construct.UInt8;
 import org.gnunet.util.RelativeTime;
 
-public class RelativeTimeNBO implements Message  {
+public class RelativeTimeNBO implements Message {
 
     /**
      * Value__ still in Java-byte order, needs to be converted to Network byte
      * order by the Construct class.
      */
-    @UnsignedInteger(8)
+    @UInt8
     public long value__;
 
-    public RelativeTimeNBO(long value) {
+    public RelativeTimeNBO(final long value) {
         this.value__ = value;
     }
-    
-    public RelativeTimeNBO(RelativeTime t) {
+
+    public RelativeTimeNBO(final RelativeTime t) {
         if (t.equals(RelativeTime.FOREVER)) {
             this.value__ = -1;
         } else {

Modified: gnunet-java/src/org/gnunet/messages/SimpleTestMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/SimpleTestMessage.java  2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/SimpleTestMessage.java  2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,29 +1,20 @@
 package org.gnunet.messages;
 
-import org.gnunet.construct.Construct.Nested;
-import org.gnunet.construct.Construct.SignedInteger;
-import org.gnunet.construct.Construct.UnsignedInteger;
+import org.gnunet.construct.FixedSizeArray;
+import org.gnunet.construct.Nested;
+import org.gnunet.construct.UInt8;
 
-public class SimpleTestMessage {
-    
-    @UnsignedInteger(2)
+public class SimpleTestMessage implements Message {
+
+    @UInt8
     public short v1;
-    
-    @SignedInteger(2)
+
+    @UInt8
     public short v2;
-    
+
     @Nested
     public SimpleTestMessage2 mn;
     
-    
-    
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof SimpleTestMessage)) {
-            return false;
-        }
-        SimpleTestMessage other = (SimpleTestMessage) obj;
-        
-        return v1 == other.v1 && v2 == other.v2 && mn.equals(other.mn);
-    }
+    @FixedSizeArray(length=5)
+    public SimpleTestMessage2[] mns;
 }

Modified: gnunet-java/src/org/gnunet/messages/SimpleTestMessage2.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/SimpleTestMessage2.java 2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/SimpleTestMessage2.java 2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,23 +1,11 @@
 package org.gnunet.messages;
 
-import org.gnunet.construct.Construct.UnsignedInteger;
+import org.gnunet.construct.UInt32;
+import org.gnunet.construct.ZeroTerminatedString;
 
-public class SimpleTestMessage2 {
-    
-    @UnsignedInteger(4)
+public class SimpleTestMessage2 implements Message {
+
+    @UInt32
     public long value;
-    
-    //@VariableSizeArray("v1")
-    //int[] arr;
-    
-    
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof SimpleTestMessage2)) {
-            return false;
-        }
-        SimpleTestMessage2 stm2 = (SimpleTestMessage2) obj;
-        return value == stm2.value;
-    }
 
 }

Modified: gnunet-java/src/org/gnunet/messages/SizeTestMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/SizeTestMessage.java    2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/SizeTestMessage.java    2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,15 +1,18 @@
 package org.gnunet.messages;
 
-import org.gnunet.construct.Construct.TotalSize;
-import org.gnunet.construct.Construct.UnsignedInteger;
+import org.gnunet.construct.ByteFill;
+import org.gnunet.construct.FrameSize;
+import org.gnunet.construct.UInt16;
 
-public class SizeTestMessage {
+public class SizeTestMessage implements Message {
+
+    @FrameSize
+    @UInt16
+    public long totalSize;
+
+    @UInt16
+    public long someValue;
     
-    @TotalSize
-    @UnsignedInteger(2)
-    public long total_size;
-    
-    @UnsignedInteger
-    public long someValue;
-
+    @ByteFill
+    public byte[] rest;
 }

Added: gnunet-java/src/org/gnunet/messages/StringMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/StringMessage.java                      
        (rev 0)
+++ gnunet-java/src/org/gnunet/messages/StringMessage.java      2011-12-01 
01:00:29 UTC (rev 18411)
@@ -0,0 +1,15 @@
+package org.gnunet.messages;
+
+import org.gnunet.construct.UInt8;
+import org.gnunet.construct.ZeroTerminatedString;
+
+public class StringMessage implements Message {
+    @UInt8
+    public int num;
+    
+    @ZeroTerminatedString
+    public String str;
+    
+    @UInt8
+    public int num2;
+}

Deleted: gnunet-java/src/org/gnunet/messages/StringTestMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/StringTestMessage.java  2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/StringTestMessage.java  2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,9 +0,0 @@
-package org.gnunet.messages;
-
-import org.gnunet.construct.Construct.ZeroTerminatedString;
-
-
-public class StringTestMessage {
-    @ZeroTerminatedString
-    public String s;
-}

Deleted: gnunet-java/src/org/gnunet/messages/TestMessage3.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/TestMessage3.java       2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/TestMessage3.java       2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,11 +0,0 @@
-package org.gnunet.messages;
-
-import org.gnunet.construct.Construct.FixedSizeArray;
-import org.gnunet.construct.Construct.UnsignedInteger;
-
-public class TestMessage3 {
-
-    @FixedSizeArray(length=10)
-    @UnsignedInteger(2)
-    public int[] arr;
-}

Deleted: gnunet-java/src/org/gnunet/messages/TestMessage4.java
===================================================================
--- gnunet-java/src/org/gnunet/messages/TestMessage4.java       2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/messages/TestMessage4.java       2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,16 +0,0 @@
-package org.gnunet.messages;
-
-import org.gnunet.construct.Construct.FixedSizeArray;
-import org.gnunet.construct.Construct.Nested;
-import org.gnunet.construct.Construct.UnsignedInteger;
-
-public class TestMessage4 {
-
-    @UnsignedInteger(2)
-    public int value;
-    
-    @FixedSizeArray(length=3)
-    @Nested
-    public TestMessage3[] tm3s;
-    
-}

Modified: gnunet-java/src/org/gnunet/service/StatisticsService.java
===================================================================
--- gnunet-java/src/org/gnunet/service/StatisticsService.java   2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/service/StatisticsService.java   2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,4 +1,3 @@
-
 /*
  * The stuff below does nothing whatsoever, first milestone of
  * this project is to implement the StatisticsService api
@@ -16,117 +15,119 @@
 
 public class StatisticsService {
 
-       interface Iterator {
-               public int call(String subsystem, String name, int value, 
boolean is_persistent);
-       }
+    enum ActionType {
+        GET, SET, WATCH, UPDATE
+    }
 
-       interface Callback {
-               
-       }
-       
-       enum ActionType {GET,SET,WATCH,UPDATE};
+    interface Callback {
 
-       class GetHandle {
-               private StatisticsService sh;
-               private String subsystem;
-               private String name;
-               private Callback cont;
-               private Iterator proc;
-               private AbsoluteTime timeout;
-               private ActionType type;
-               private int msize;
-               void cancel() {
-                       throw new UnsupportedOperationException();
-               }
-       }
-       
-       private class WatchEntry {
-               String subssytem;
-               String name;
-               Iterator proc;
-               public WatchEntry(String subssytem, String name, Iterator proc) 
{
-                       this.subssytem = subssytem;
-                       this.name = name;
-                       this.proc = proc;
-               }
-       }
-       
-       
-       
-       private Client client;
-       private RelativeTime backoff;
-       
-       private String subsystem;
-       private Configuration cfg;
-       
-       LinkedList<WatchEntry> watches;
-       
-       LinkedList<GetHandle> actions;
-       
-       GetHandle currentAction;
-       
-       Client.TransmitHandle th;
-       
+    }
 
-       public StatisticsService(String subsystem, Configuration cfg) {
-               this.backoff = new RelativeTime(1);
-               this.subsystem = subsystem;
-               this.cfg = cfg;
-               this.client = new Client("statistics", cfg);
-               this.watches = new LinkedList<StatisticsService.WatchEntry>();
-               this.actions = new LinkedList<StatisticsService.GetHandle>();
-       }
-       
+    class GetHandle {
+        private StatisticsService sh;
+        private String subsystem;
+        private String name;
+        private Callback cont;
+        private Iterator proc;
+        private AbsoluteTime timeout;
+        private ActionType type;
+        private int msize;
 
-       public void watch(String subsystem, String name, Iterator cb) {
-               throw new UnsupportedOperationException();
-               /*
-               WatchEntry w = new WatchEntry(subsystem, name, cb);
-               this.watches.add(w);
-               scheduleWatchRequest(w);
-               */
-       }
+        void cancel() {
+            throw new UnsupportedOperationException();
+        }
+    };
 
-       
-       
+    interface Iterator {
+        public int call(String subsystem, String name, int value,
+                boolean is_persistent);
+    }
 
-       public GetHandle get(String subsystem, String name, RelativeTime 
timeout,
-                       Callback cb, Iterator it) {
-               GetHandle h = new GetHandle();
-               h.sh = this;
-               h.subsystem = subsystem;
-               h.name = name;
-               h.cont = cb;
-               h.proc = it;
-               h.type = ActionType.GET;
-               insertGetHandle(h);
-               return h;
-       }
-       
-       private void insertGetHandle(GetHandle h) {
-               actions.add(h);
-               if (h == actions.getFirst()) {
-                       scheduleAction();
-               }
-       }
-       
-       private void scheduleAction() {
-               if (currentAction != null) {
-                       return;
-               }
-               // XXX: What about reconnect stuff?
-               currentAction = actions.removeFirst();
-               // XXX: what about destruction?
-               this.th = client.notifyTransmitReady(currentAction.msize, 
/*XXX:dummy*/ null, true, /*XXX:dummy*/ null);
-               
-               // XXX totally incomplete
-       }
+    private class WatchEntry {
+        String subssytem;
+        String name;
+        Iterator proc;
 
-       public void set(String name, int value, boolean make_persistent) {
-               throw new UnsupportedOperationException();
-       }
+        public WatchEntry(final String subssytem, final String name,
+                final Iterator proc) {
+            this.subssytem = subssytem;
+            this.name = name;
+            this.proc = proc;
+        }
+    }
 
-       public void update(String name, int delta, boolean make_persistent) {
-               throw new UnsupportedOperationException();
-       }
+    private final Client client;
+    private final RelativeTime backoff;
+
+    private final String subsystem;
+    private final Configuration cfg;
+
+    LinkedList<WatchEntry> watches;
+
+    LinkedList<GetHandle> actions;
+
+    GetHandle currentAction;
+
+    Client.TransmitHandle th;
+
+    public StatisticsService(final String subsystem, final Configuration cfg) {
+        this.backoff = new RelativeTime(1);
+        this.subsystem = subsystem;
+        this.cfg = cfg;
+        this.client = new Client("statistics", cfg);
+        this.watches = new LinkedList<StatisticsService.WatchEntry>();
+        this.actions = new LinkedList<StatisticsService.GetHandle>();
+    }
+
+    public GetHandle get(final String subsystem, final String name,
+            final RelativeTime timeout, final Callback cb, final Iterator it) {
+        final GetHandle h = new GetHandle();
+        h.sh = this;
+        h.subsystem = subsystem;
+        h.name = name;
+        h.cont = cb;
+        h.proc = it;
+        h.type = ActionType.GET;
+        insertGetHandle(h);
+        return h;
+    }
+
+    private void insertGetHandle(final GetHandle h) {
+        actions.add(h);
+        if (h == actions.getFirst()) {
+            scheduleAction();
+        }
+    }
+
+    private void scheduleAction() {
+        if (currentAction != null) {
+            return;
+        }
+        // XXX: What about reconnect stuff?
+        currentAction = actions.removeFirst();
+        // XXX: what about destruction?
+        this.th = client.notifyTransmitReady(currentAction.msize, /* XXX:dummy 
*/
+                null, true, /* XXX:dummy */null);
+
+        // XXX totally incomplete
+    }
+
+    public void set(final String name, final int value,
+            final boolean make_persistent) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void update(final String name, final int delta,
+            final boolean make_persistent) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void watch(final String subsystem, final String name,
+            final Iterator cb) {
+        throw new UnsupportedOperationException();
+        /*
+         * WatchEntry w = new WatchEntry(subsystem, name, cb);
+         * this.watches.add(w); scheduleWatchRequest(w);
+         */
+    }
 }

Modified: gnunet-java/src/org/gnunet/util/AbsoluteTime.java
===================================================================
--- gnunet-java/src/org/gnunet/util/AbsoluteTime.java   2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/util/AbsoluteTime.java   2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -16,14 +16,13 @@
      along with GNUnet; see the file COPYING.  If not, write to the
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
-*/
+ */
 
 package org.gnunet.util;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 /**
  * A specific point in time.
  * 
@@ -38,7 +37,14 @@
 
     private static long offset = 0;
 
-    private final long abs_value;
+    /**
+     * Gets the current time.
+     * 
+     * @return the current time
+     */
+    public static AbsoluteTime now() {
+        return new AbsoluteTime(System.currentTimeMillis() + offset);
+    }
 
     /**
      * Sets the timestamp offset for this instance.
@@ -50,51 +56,31 @@
         AbsoluteTime.offset = offset;
     }
 
-    /**
-     * Gets the current time.
-     * 
-     * @return the current time
-     */
-    public static AbsoluteTime now() {
-        return new AbsoluteTime(System.currentTimeMillis() + offset);
-    }
+    private final long abs_value;
 
     public AbsoluteTime(final long abs_value) {
         this.abs_value = abs_value;
     }
 
-    
     /**
-     * Returns the milliseconds since some fixed point of reference.
+     * Adds a relative time value to an absolute time.
      * 
-     * @return the absolute time in milliseconds
+     * @param duration
+     * @return this + duration
      */
-    public long getMilliseconds() {
-        return abs_value;
+    public AbsoluteTime add(final RelativeTime duration) {
+        if (abs_value == Long.MAX_VALUE
+                || duration.getMilliseconds() == Long.MAX_VALUE) {
+            return this;
+        }
+        if (abs_value + duration.getMilliseconds() < abs_value) {
+            logger.warn("time overflow");
+            return AbsoluteTime.FOREVER;
+        }
+        return new AbsoluteTime(abs_value + duration.getMilliseconds());
     }
 
     /**
-     * Returns the minimum of two time values.
-     * 
-     * @param other
-     * @return min(this,other)
-     */
-    public AbsoluteTime min(final AbsoluteTime other) {
-        return (abs_value <= other.abs_value) ? this : other;
-    }
-
-    /**
-     * Returns the maximum of two time values.
-     * 
-     * @param other
-     * @return max(this,other)
-     */
-    public AbsoluteTime max(final AbsoluteTime other) {
-        return (abs_value >= other.abs_value) ? this : other;
-
-    }
-
-    /**
      * Calculates the estimate time of arrival/completion for an operation.
      * 
      * @param start
@@ -115,11 +101,17 @@
             return RelativeTime.FOREVER;
         }
         final RelativeTime dur = start.getDuration();
-        final double exp = ((double) dur.getMilliseconds()) * ((double) total)
+        final double exp = (double) dur.getMilliseconds() * (double) total
                 / finished;
         return new RelativeTime((long) exp);
     }
 
+    @Override
+    public int compareTo(final Object o) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
     /**
      * Calculates the difference between two absolute times.
      * 
@@ -148,6 +140,15 @@
     }
 
     /**
+     * Returns the milliseconds since some fixed point of reference.
+     * 
+     * @return the absolute time in milliseconds
+     */
+    public long getMilliseconds() {
+        return abs_value;
+    }
+
+    /**
      * Calculates the remaining time relative to now.
      * 
      * @return future - now
@@ -157,24 +158,27 @@
     }
 
     /**
-     * Adds a relative time value to an absolute time.
+     * Returns the maximum of two time values.
      * 
-     * @param duration
-     * @return this + duration
+     * @param other
+     * @return max(this,other)
      */
-    public AbsoluteTime add(final RelativeTime duration) {
-        if (abs_value == Long.MAX_VALUE
-                || duration.getMilliseconds() == Long.MAX_VALUE) {
-            return this;
-        }
-        if (abs_value + duration.getMilliseconds() < abs_value) {
-            logger.warn("time overflow");
-            return AbsoluteTime.FOREVER;
-        }
-        return new AbsoluteTime(abs_value + duration.getMilliseconds());
+    public AbsoluteTime max(final AbsoluteTime other) {
+        return abs_value >= other.abs_value ? this : other;
+
     }
 
     /**
+     * Returns the minimum of two time values.
+     * 
+     * @param other
+     * @return min(this,other)
+     */
+    public AbsoluteTime min(final AbsoluteTime other) {
+        return abs_value <= other.abs_value ? this : other;
+    }
+
+    /**
      * Subtracts a relative time value to an absolute time
      * 
      * @param duration
@@ -189,10 +193,4 @@
         }
         return new AbsoluteTime(abs_value - duration.getMilliseconds());
     }
-
-    @Override
-    public int compareTo(Object o) {
-        // TODO Auto-generated method stub
-        return 0;
-    }
 }

Modified: gnunet-java/src/org/gnunet/util/Client.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Client.java 2011-11-30 15:21:36 UTC (rev 
18410)
+++ gnunet-java/src/org/gnunet/util/Client.java 2011-12-01 01:00:29 UTC (rev 
18411)
@@ -16,130 +16,138 @@
      along with GNUnet; see the file COPYING.  If not, write to the
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
-*/
+ */
 
-
 package org.gnunet.util;
 
 import org.gnunet.messages.MessageHeader;
 import org.gnunet.util.Scheduler.Task;
 
-
 /**
  * Represents a connection to a service.
  */
 public class Client {
-       interface MessageHandler {
+    interface MessageHandler {
 
-       }
+    }
 
-       public static class TransmitHandle {
-               /**
-                * Cancel a request for notification.
-                */
-               void cancel() {
-                       throw new UnsupportedOperationException();
-               }
+    public static class TransmitHandle {
+        /**
+         * Cancel a request for notification.
+         */
+        void cancel() {
+            throw new UnsupportedOperationException();
+        }
 
-       }
+    }
 
-       /**
-        * Get a connection with a service.
-        * 
-        * @param service_name
-        *            name of the service
-        * @param cfg
-        *            configuration to use
-        */
-       public Client(String service_name, Configuration c) {
-               throw new UnsupportedOperationException();
-       }
+    /**
+     * Wait until the service is running.
+     * 
+     * @param service
+     *            name of the service to wait for
+     * @param cfg
+     *            configuration to use
+     * @param timeout
+     *            how long to wait at most in ms
+     * @param task
+     *            task to run if service is running (reason will be
+     *            "PREREQ_DONE" (service running) or "TIMEOUT" (service not
+     *            known to be running))
+     */
 
-       /**
-        * Read from the service.
-        * 
-        * @param handler
-        *            function to call with the message
-        * @param timeout
-        *            how long to wait until timing out
-        */
+    public static void serviceTest(final String service_name,
+            final Configuration cfg, final RelativeTime timeout, final Task t) 
{
+        throw new UnsupportedOperationException();
+    }
 
-       public void receive(MessageHandler handler, RelativeTime timeout) {
-               throw new UnsupportedOperationException();
-       }
+    /**
+     * Get a connection with a service.
+     * 
+     * @param service_name
+     *            name of the service
+     * @param cfg
+     *            configuration to use
+     */
+    public Client(final String service_name, final Configuration c) {
+        throw new UnsupportedOperationException();
+    }
 
-       /**
-        * Ask the client to call us once the specified number of bytes are 
free in
-        * the transmission buffer. May call the notify method immediately if 
enough
-        * space is available.
-        * 
-        * @param sock
-        *            connection to the service
-        * @param size
-        *            number of bytes to send
-        * @param timeout
-        *            after how long should we give up (and call notify with buf
-        *            NULL and size 0)?
-        * @param auto_retry
-        *            if the connection to the service dies, should we 
automatically
-        *            re-connect and retry (within the timeout period) or 
should we
-        *            immediately fail in this case? Pass GNUNET_YES if the 
caller
-        *            does not care about temporary connection errors, for 
example
-        *            because the protocol is stateless
-        * @param notify
-        *            function to call
-        * @param notify_cls
-        *            closure for notify
-        * @return NULL if someone else is already waiting to be notified 
non-NULL
-        *         if the notify callback was queued (can be used to cancel 
using
-        *         GNUNET_CONNECTION_notify_transmit_ready_cancel)
-        */
-       public TransmitHandle notifyTransmitReady(int size, RelativeTime 
timeout,
-                       boolean auto_retry, TransmitReadyNotify cb) {
-               throw new UnsupportedOperationException();
-       }
+    /**
+     * Ask the client to call us once the specified number of bytes are free in
+     * the transmission buffer. May call the notify method immediately if 
enough
+     * space is available.
+     * 
+     * @param sock
+     *            connection to the service
+     * @param size
+     *            number of bytes to send
+     * @param timeout
+     *            after how long should we give up (and call notify with buf
+     *            NULL and size 0)?
+     * @param auto_retry
+     *            if the connection to the service dies, should we 
automatically
+     *            re-connect and retry (within the timeout period) or should we
+     *            immediately fail in this case? Pass GNUNET_YES if the caller
+     *            does not care about temporary connection errors, for example
+     *            because the protocol is stateless
+     * @param notify
+     *            function to call
+     * @param notify_cls
+     *            closure for notify
+     * @return NULL if someone else is already waiting to be notified non-NULL
+     *         if the notify callback was queued (can be used to cancel using
+     *         GNUNET_CONNECTION_notify_transmit_ready_cancel)
+     */
+    public TransmitHandle notifyTransmitReady(final int size,
+            final RelativeTime timeout, final boolean auto_retry,
+            final TransmitReadyNotify cb) {
+        throw new UnsupportedOperationException();
+    }
 
-       
-       /**
-        * Convenience API that combines sending a request
-        * to the service and waiting for a response.
-        * If either operation times out, the callback
-        * will be called with a "NULL" response (in which
-        * case the connection should probably be destroyed).
-        *
-        * @param sock connection to use
-        * @param hdr message to transmit
-        * @param timeout when to give up (for both transmission
-        *         and for waiting for a response)
-        * @param auto_retry if the connection to the service dies, should we
-        *        automatically re-connect and retry (within the timeout period)
-        *        or should we immediately fail in this case?  Pass GNUNET_YES
-        *        if the caller does not care about temporary connection errors,
-        *        for example because the protocol is stateless
-        * @param rn function to call with the response
-        * @param rn_cls closure for rn
-        * @return GNUNET_OK on success, GNUNET_SYSERR if a request
-        *         is already pending
-        */
-       //XXX return type bool vs. exceptions
-       public boolean transmitAndGetResponse(MessageHeader m, RelativeTime 
timeout,
-                       boolean autoRetry, MessageHandler handler) {
-               throw new UnsupportedOperationException();
-       }
-       
-       
-       /**
-        * Wait until the service is running.
-        *
-        * @param service name of the service to wait for
-        * @param cfg configuration to use
-        * @param timeout how long to wait at most in ms
-        * @param task task to run if service is running
-        *        (reason will be "PREREQ_DONE" (service running)
-        *         or "TIMEOUT" (service not known to be running))
-        */
+    /**
+     * Read from the service.
+     * 
+     * @param handler
+     *            function to call with the message
+     * @param timeout
+     *            how long to wait until timing out
+     */
 
-       public static void serviceTest(String service_name, Configuration cfg, 
RelativeTime timeout, Task t) {
-               throw new UnsupportedOperationException();
-       }
+    public void receive(final MessageHandler handler, final RelativeTime 
timeout) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Convenience API that combines sending a request to the service and
+     * waiting for a response. If either operation times out, the callback will
+     * be called with a "NULL" response (in which case the connection should
+     * probably be destroyed).
+     * 
+     * @param sock
+     *            connection to use
+     * @param hdr
+     *            message to transmit
+     * @param timeout
+     *            when to give up (for both transmission and for waiting for a
+     *            response)
+     * @param auto_retry
+     *            if the connection to the service dies, should we 
automatically
+     *            re-connect and retry (within the timeout period) or should we
+     *            immediately fail in this case? Pass GNUNET_YES if the caller
+     *            does not care about temporary connection errors, for example
+     *            because the protocol is stateless
+     * @param rn
+     *            function to call with the response
+     * @param rn_cls
+     *            closure for rn
+     * @return GNUNET_OK on success, GNUNET_SYSERR if a request is already
+     *         pending
+     */
+    // XXX return type bool vs. exceptions
+    public boolean transmitAndGetResponse(final MessageHeader m,
+            final RelativeTime timeout, final boolean autoRetry,
+            final MessageHandler handler) {
+        throw new UnsupportedOperationException();
+    }
 }

Modified: gnunet-java/src/org/gnunet/util/Configuration.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Configuration.java  2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/util/Configuration.java  2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -43,12 +43,23 @@
  * @author Florian Dold
  */
 public class Configuration {
+    @SuppressWarnings("serial")
+    public static class ParsingError extends Error {
+        ParsingError(final String msg) {
+            super(msg);
+        }
+
+        ParsingError(final String msg, final Throwable t) {
+            super(msg, t);
+        }
+    }
+
     private static final Logger logger = LoggerFactory
             .getLogger(Configuration.class);
-
     private static Pattern section = Pattern.compile("\\[(.*?)\\]");
     private static Pattern tag = Pattern.compile("(\\S+?) =( ?.*?)");
     private static Pattern comment = Pattern.compile("\\s*[%#].*\n?");
+
     private static Pattern delim = Pattern.compile("\\s*\\n\\s*");
 
     private final Map<String, Map<String, String>> sections = new 
LinkedHashMap<String, Map<String, String>>();
@@ -59,138 +70,97 @@
     public Configuration() {
     }
 
+    public boolean appendValueFilename(final String section,
+            final String option, final String value) {
+        throw new UnsupportedOperationException();
+    }
+
     /**
-     * Parse a configuration file, add all of the options in the file to the
-     * configuration environment.
+     * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where
+     * either in the "PATHS" section or the environment "FOO" is set to
+     * "DIRECTORY".
      * 
-     * @param filename
-     *            name of the configuration file
-     * @throws ParsingError
+     * @param orig
+     *            string to $-expand
+     * @return $-expanded string
      */
-    public void parse(String filename) {
-        Scanner sc;
-        try {
-            sc = new Scanner(new File(filename)).useDelimiter(delim);
-        } catch (FileNotFoundException e) {
-            throw new ParsingError("Configuration file \"" + filename
-                    + "\" not found");
+    public String expandDollar(String orig) {
+        final Map<String, String> env = System.getenv();
+        for (final Map.Entry<String, String> e : env.entrySet()) {
+            orig = orig.replace("$" + e.getKey(), e.getValue());
         }
 
-        String current_section = "";
-
-        while (true) {
-            if (sc.hasNext(comment)) {
-                sc.next(comment);
-            } else if (sc.hasNext(section)) {
-                sc.next(section);
-                current_section = sc.match().group(1).trim();
-            } else if (sc.hasNext(tag)) {
-                sc.next(tag);
-                String option = sc.match().group(1).trim();
-                String value = sc.match().group(2).trim();
-
-                if (value.length() != 0 && value.charAt(0) == '"') {
-                    int pos = value.indexOf('"', 1);
-                    if (pos == -1) {
-                        logger.warn("incorrecly quoted config value");
-                        continue;
-                    }
-                    value = value.substring(1, pos);
-                }
-                setValueString(current_section, option, value);
-            } else if (!sc.hasNext()) {
-                break;
-            } else {
-                logger.warn("skipped unreadable configuration line");
-                sc.next();
+        if (sections.containsKey("PATHS")) {
+            for (final Map.Entry<String, String> e : sections.get("PATHS")
+                    .entrySet()) {
+                orig = orig.replace("$" + e.getKey(), e.getValue());
             }
         }
+        return orig;
     }
 
     /**
-     * Start with defaults, the parse configuration file.
-     */
-    public boolean load(String filename) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Test if there are configuration options that were changed since the last
-     * save.
-     */
-    public boolean isDirty() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Write configuration file.
+     * Returns all configuration options in a section.
      * 
-     * @param filename
-     *            where to write the configuration
-     * @throws IOException
+     * @param s
+     *            the section of interest
+     * @return an unmodifiable view of the section.
      */
-    public void write(String filename) throws IOException {
-        BufferedWriter w = new BufferedWriter(
-                new FileWriter(new File(filename)));
-        for (Map.Entry<String, Map<String, String>> s : sections.entrySet()) {
-            w.write(s.getKey());
-            w.newLine();
-            for (Map.Entry<String, String> e : s.getValue().entrySet()) {
-                w.write(e.getKey() + " = " + e.getValue());
-                w.newLine();
-            }
+    public Map<String, String> getSection(final String s) {
+        final Map<String, String> m = sections.get(s);
+        if (m == null) {
+            throw new ParsingError("configuration section not found");
         }
-        w.close();
+        return Collections.unmodifiableMap(m);
     }
 
     /**
-     * Remove the given section and all options in it.
-     */
-    public void removeSection(String section) {
-        sections.remove(section);
-    }
-
-    /**
-     * Write only configuration entries that have been changed to configuration
-     * file.
+     * Returns the names of all non-empty sections
      * 
-     * @param cfgNew
-     *            new configuration
-     * 
-     * @param filename
-     *            where to write the configuration diff between default and new
+     * @return set of non-empty section names
      */
-    public void writeDiffs(Configuration cfgNew, String filename) {
-        throw new UnsupportedOperationException();
+    public Set<String> getSections() {
+        return sections.keySet();
     }
 
     /**
-     * Set an option to a string value in a section.
+     * Get a configuration value that should be in a set of predefined strings
      * 
      * @param section
+     *            section of interest
      * @param option
-     * @param value
+     *            option of interest
+     * @param choices
+     *            list of legal values
+     * @return matching value from choices
+     * @throws ParsingError
      */
-    public void setValueString(String section, String option, String value) {
-        Map<String, String> table = sections.get(section);
-        if (table == null) {
-            table = new LinkedHashMap<String, String>();
-            sections.put(section, table);
+    public String getValueChoice(final String section, final String option,
+            final Iterable<String> choices) {
+        final String value = getValueString(section, option);
+        if (value == null) {
+            throw new ParsingError(String.format(
+                    "Failure in configuration section %s: value not found",
+                    section));
         }
-        table.put(option, value);
+        for (final String c : choices) {
+            if (c.equals(value)) {
+                return value;
+            }
+        }
+        throw new ParsingError(String.format(
+                "Failure in configuration section %s: invalid value", 
section));
     }
 
-    /**
-     * Set an option to a string value in a section.
-     * 
-     * @param section
-     * @param option
-     * @param value
-     */
-    public void setValueNumber(String section, String option, long value) {
-        setValueString(section, option, "" + value);
+    public String getValueFileName(final String section, final String option) {
+        throw new UnsupportedOperationException();
     }
 
+    public List<String> getValueFilenames(final String section,
+            final String option) {
+        throw new UnsupportedOperationException();
+    }
+
     /**
      * Get a configuration value that should be a number
      * 
@@ -198,15 +168,15 @@
      * @param option
      * @return null if value not in configuration, the option's value otherwise
      */
-    public long getValueNumer(String section, String option) {
-        String num_str = getValueString(section, option);
+    public long getValueNumer(final String section, final String option) {
+        final String num_str = getValueString(section, option);
         if (num_str == null) {
             throw new ParsingError("Failure in configuration section "
                     + section + " option " + option + ": value empty");
         }
         try {
             return Long.parseLong(num_str);
-        } catch (NumberFormatException e) {
+        } catch (final NumberFormatException e) {
             throw new ParsingError("Failure in configuration section "
                     + section + " option " + option + ": " + e.getMessage(), 
e);
         }
@@ -219,7 +189,7 @@
      * @param option
      * @throws ParsingError
      */
-    public String getValueString(String section, String option) {
+    public String getValueString(final String section, final String option) {
         if (!sections.containsKey(section)) {
             throw new ParsingError(String.format(
                     "Failure in configuration section %s: option %s not found",
@@ -235,38 +205,35 @@
      * @param option
      * @return null if option not found
      */
-    public RelativeTime getValueTime(String section, String option) {
+    public RelativeTime getValueTime(final String section, final String 
option) {
         throw new UnsupportedOperationException();
     }
 
     /**
-     * Get a configuration value that should be in a set of predefined strings
+     * Gets a configuration value that should be in a set of {"YES","NO"}.
      * 
      * @param section
      *            section of interest
      * @param option
      *            option of interest
-     * @param choices
-     *            list of legal values
-     * @return matching value from choices
-     * @throws ParsingError
+     * @return true, false, null
      */
-    public String getValueChoice(String section, String option,
-            Iterable<String> choices) {
-        String value = getValueString(section, option);
-        if (value == null) {
+    public boolean getValueYesNo(final String section, final String option) {
+        final String v = getValueChoice(section, option,
+                Arrays.asList("YES", "NO"));
+        if (v == null) {
             throw new ParsingError(String.format(
-                    "Failure in configuration section %s: value not found",
-                    section));
+                    "Failure in configuration section %s: option %s not found",
+                    section, option));
         }
-        for (String c : choices) {
-            if (c.equals(value)) {
-                return value;
-            }
+        if (v.equals("YES")) {
+            return true;
         }
-        throw new ParsingError(String.format(
-                "Failure in configuration section %s: invalid value",
-                section));
+        if (v.equals("NO")) {
+            return false;
+        }
+        throw new ParsingError(
+                "Configuration error: value not recognized as YES or NO");
     }
 
     /**
@@ -279,110 +246,149 @@
      * @return true if so, false of not
      * 
      */
-    public boolean haveValue(String section, String option) {
+    public boolean haveValue(final String section, final String option) {
         return sections.containsKey(section)
                 && sections.get(section).containsKey(option);
     }
 
     /**
-     * Gets a configuration value that should be in a set of {"YES","NO"}.
-     * 
-     * @param section
-     *            section of interest
-     * @param option
-     *            option of interest
-     * @return true, false, null
+     * Test if there are configuration options that were changed since the last
+     * save.
      */
-    public boolean getValueYesNo(String section, String option) {
-        String v = getValueChoice(section, option, Arrays.asList("YES", "NO"));
-        if (v == null) {
-            throw new ParsingError(String.format(
-                    "Failure in configuration section %s: option %s not found",
-                    section, option));
-        }
-        if (v.equals("YES")) {
-            return true;
-        }
-        if (v.equals("NO")) {
-            return false;
-        }
-        throw new ParsingError("Configuration error: value not recognized as 
YES or NO");
+    public boolean isDirty() {
+        throw new UnsupportedOperationException();
     }
 
     /**
-     * Returns all configuration options in a section.
-     * 
-     * @param s
-     *            the section of interest
-     * @return an unmodifiable view of the section.
+     * Start with defaults, the parse configuration file.
      */
-    public Map<String, String> getSection(String s) {
-        Map<String, String> m = sections.get(s);
-        if (m == null) {
-            throw new ParsingError("configuration section not found");
-        }
-        return Collections.unmodifiableMap(m);
+    public boolean load(final String filename) {
+        throw new UnsupportedOperationException();
     }
 
     /**
-     * Returns the names of all non-empty sections
+     * Parse a configuration file, add all of the options in the file to the
+     * configuration environment.
      * 
-     * @return set of non-empty section names
+     * @param filename
+     *            name of the configuration file
+     * @throws ParsingError
      */
-    public Set<String> getSections() {
-        return sections.keySet();
-    }
-
-    /**
-     * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where
-     * either in the "PATHS" section or the environment "FOO" is set to
-     * "DIRECTORY".
-     * 
-     * @param orig
-     *            string to $-expand
-     * @return $-expanded string
-     */
-    public String expandDollar(String orig) {
-        Map<String, String> env = System.getenv();
-        for (Map.Entry<String, String> e : env.entrySet()) {
-            orig = orig.replace("$" + e.getKey(), e.getValue());
+    public void parse(final String filename) {
+        Scanner sc;
+        try {
+            sc = new Scanner(new File(filename)).useDelimiter(delim);
+        } catch (final FileNotFoundException e) {
+            throw new ParsingError("Configuration file \"" + filename
+                    + "\" not found");
         }
 
-        if (sections.containsKey("PATHS")) {
-            for (Map.Entry<String, String> e : 
sections.get("PATHS").entrySet()) {
-                orig = orig.replace("$" + e.getKey(), e.getValue());
+        String current_section = "";
+
+        while (true) {
+            if (sc.hasNext(comment)) {
+                sc.next(comment);
+            } else if (sc.hasNext(section)) {
+                sc.next(section);
+                current_section = sc.match().group(1).trim();
+            } else if (sc.hasNext(tag)) {
+                sc.next(tag);
+                final String option = sc.match().group(1).trim();
+                String value = sc.match().group(2).trim();
+
+                if (value.length() != 0 && value.charAt(0) == '"') {
+                    final int pos = value.indexOf('"', 1);
+                    if (pos == -1) {
+                        logger.warn("incorrecly quoted config value");
+                        continue;
+                    }
+                    value = value.substring(1, pos);
+                }
+                setValueString(current_section, option, value);
+            } else if (!sc.hasNext()) {
+                break;
+            } else {
+                logger.warn("skipped unreadable configuration line");
+                sc.next();
             }
         }
-        return orig;
     }
 
-    public String getValueFileName(String section, String option) {
-        throw new UnsupportedOperationException();
+    /**
+     * Remove the given section and all options in it.
+     */
+    public void removeSection(final String section) {
+        sections.remove(section);
     }
 
-    public List<String> getValueFilenames(String section, String option) {
+    public boolean removeValueFilename(final String section,
+            final String option, final String value) {
         throw new UnsupportedOperationException();
     }
 
-    public boolean appendValueFilename(String section, String option,
-            String value) {
-        throw new UnsupportedOperationException();
+    /**
+     * Set an option to a string value in a section.
+     * 
+     * @param section
+     * @param option
+     * @param value
+     */
+    public void setValueNumber(final String section, final String option,
+            final long value) {
+        setValueString(section, option, "" + value);
     }
 
-    public boolean removeValueFilename(String section, String option,
-            String value) {
-        throw new UnsupportedOperationException();
+    /**
+     * Set an option to a string value in a section.
+     * 
+     * @param section
+     * @param option
+     * @param value
+     */
+    public void setValueString(final String section, final String option,
+            final String value) {
+        Map<String, String> table = sections.get(section);
+        if (table == null) {
+            table = new LinkedHashMap<String, String>();
+            sections.put(section, table);
+        }
+        table.put(option, value);
     }
 
-    @SuppressWarnings("serial")
-    public static class ParsingError extends Error {
-        ParsingError(String msg, Throwable t) {
-            super(msg, t);
+    /**
+     * Write configuration file.
+     * 
+     * @param filename
+     *            where to write the configuration
+     * @throws IOException
+     */
+    public void write(final String filename) throws IOException {
+        final BufferedWriter w = new BufferedWriter(new FileWriter(new File(
+                filename)));
+        for (final Map.Entry<String, Map<String, String>> s : sections
+                .entrySet()) {
+            w.write(s.getKey());
+            w.newLine();
+            for (final Map.Entry<String, String> e : s.getValue().entrySet()) {
+                w.write(e.getKey() + " = " + e.getValue());
+                w.newLine();
+            }
         }
+        w.close();
+    }
 
-        ParsingError(String msg) {
-            super(msg);
-        }
+    /**
+     * Write only configuration entries that have been changed to configuration
+     * file.
+     * 
+     * @param cfgNew
+     *            new configuration
+     * 
+     * @param filename
+     *            where to write the configuration diff between default and new
+     */
+    public void writeDiffs(final Configuration cfgNew, final String filename) {
+        throw new UnsupportedOperationException();
     }
 
 }

Modified: gnunet-java/src/org/gnunet/util/MessageHandler.java
===================================================================
--- gnunet-java/src/org/gnunet/util/MessageHandler.java 2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/util/MessageHandler.java 2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -16,25 +16,23 @@
      along with GNUnet; see the file COPYING.  If not, write to the
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
-*/
+ */
 
-
 package org.gnunet.util;
 
 import org.gnunet.messages.MessageHeader;
 
-
 /**
  * 
  * @author Florian Dold
- *
+ * 
  */
 public interface MessageHandler {
     /**
-     * Method to call when we receive a message
-     * from the service.
-     *
-     * @param msg message received, NULL on timeout or fatal error
+     * Method to call when we receive a message from the service.
+     * 
+     * @param msg
+     *            message received, NULL on timeout or fatal error
      */
     public void handle(MessageHeader msg);
 }

Modified: gnunet-java/src/org/gnunet/util/Program.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Program.java        2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/util/Program.java        2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -1,7 +1,5 @@
 package org.gnunet.util;
 
 public class Program {
-    
-   
 
 }

Modified: gnunet-java/src/org/gnunet/util/Receiver.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Receiver.java       2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/util/Receiver.java       2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -16,23 +16,23 @@
      along with GNUnet; see the file COPYING.  If not, write to the
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
-*/
+ */
 
-
-
 package org.gnunet.util;
 
 import java.net.SocketAddress;
 
-
 public interface Receiver {
     /**
      * Callback function for data received from the network.
      * 
-     * @param buf received data
-     * @param sockaddr address of the sender
-     * @param errCode XXX errno? really?! should this be an IO exception?
+     * @param buf
+     *            received data
+     * @param sockaddr
+     *            address of the sender
+     * @param errCode
+     *            XXX errno? really?! should this be an IO exception?
      */
-       public void receive(byte[] buf, SocketAddress sockaddr, int errCode);
-       
-}
\ No newline at end of file
+    public void receive(byte[] buf, SocketAddress sockaddr, int errCode);
+
+}

Modified: gnunet-java/src/org/gnunet/util/RelativeTime.java
===================================================================
--- gnunet-java/src/org/gnunet/util/RelativeTime.java   2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/util/RelativeTime.java   2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -16,9 +16,8 @@
      along with GNUnet; see the file COPYING.  If not, write to the
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
-*/
+ */
 
-
 package org.gnunet.util;
 
 import org.gnunet.messages.RelativeTimeNBO;
@@ -53,31 +52,50 @@
     }
 
     /**
-     * Returns the amount of time in milliseconds.
+     * Add relative times together.
      * 
-     * @return the amount of time in milliseconds
+     * @param other
+     *            the other timestamp
+     * 
+     * @return this + other
      */
-    public long getMilliseconds() {
-        return rel_value;
+    public RelativeTime add(final RelativeTime other) {
+        if (this.rel_value == Long.MAX_VALUE
+                || other.rel_value == Long.MAX_VALUE) {
+            return RelativeTime.FOREVER;
+        }
+        final long new_rel_value = this.rel_value + other.rel_value;
+        // check for numeric overflow
+        if (new_rel_value < this.rel_value) {
+            logger.warn("time overflow");
+            return RelativeTime.FOREVER;
+        }
+        return new RelativeTime(new_rel_value);
     }
 
     /**
-     * Converts relative time to an absolute time in the future.
+     * Divide relative time by a given factor.
      * 
-     * @return timestamp that is in the future, or FOREVER if this=FOREVER (or
-     *         if we would overflow)
+     * @param rel
+     *            some duration
+     * @param factor
+     *            integer to divide by
+     * @return FOREVER if this=FOREVER or factor=0; otherwise this/factor
      */
-    public AbsoluteTime toAbsolute() {
-        return AbsoluteTime.now().add(this);
+    public RelativeTime divide(final int factor) {
+        if (factor == 0 || this.rel_value == Long.MAX_VALUE) {
+            return RelativeTime.FOREVER;
+        }
+        return new RelativeTime(this.rel_value / factor);
     }
 
     /**
-     * Return the minimum of two relative time values.
+     * Returns the amount of time in milliseconds.
      * 
-     * @return min(this, other)
+     * @return the amount of time in milliseconds
      */
-    public RelativeTime min(final RelativeTime other) {
-        return (rel_value <= other.rel_value) ? this : other;
+    public long getMilliseconds() {
+        return rel_value;
     }
 
     /**
@@ -86,10 +104,19 @@
      * @return max(this, other)
      */
     public RelativeTime max(final RelativeTime other) {
-        return (rel_value >= other.rel_value) ? this : other;
+        return rel_value >= other.rel_value ? this : other;
     }
 
     /**
+     * Return the minimum of two relative time values.
+     * 
+     * @return min(this, other)
+     */
+    public RelativeTime min(final RelativeTime other) {
+        return rel_value <= other.rel_value ? this : other;
+    }
+
+    /**
      * Multiply relative time by a given factor.
      * 
      * @return FOREVER if this=FOREVER or on overflow; otherwise this*factor
@@ -108,53 +135,6 @@
     }
 
     /**
-     * Divide relative time by a given factor.
-     * 
-     * @param rel
-     *            some duration
-     * @param factor
-     *            integer to divide by
-     * @return FOREVER if this=FOREVER or factor=0; otherwise this/factor
-     */
-    public RelativeTime divide(final int factor) {
-        if (factor == 0 || this.rel_value == Long.MAX_VALUE) {
-            return RelativeTime.FOREVER;
-        }
-        return new RelativeTime(this.rel_value / factor);
-    }
-
-    /**
-     * Add relative times together.
-     * 
-     * @param other
-     *            the other timestamp
-     * 
-     * @return this + other
-     */
-    public RelativeTime add(final RelativeTime other) {
-        if (this.rel_value == Long.MAX_VALUE
-                || other.rel_value == Long.MAX_VALUE) {
-            return RelativeTime.FOREVER;
-        }
-        final long new_rel_value = this.rel_value + other.rel_value;
-        // check for numeric overflow
-        if (new_rel_value < this.rel_value) {
-            logger.warn("time overflow");
-            return RelativeTime.FOREVER;
-        }
-        return new RelativeTime(new_rel_value);
-    }
-       
-    public RelativeTimeNBO toNBO()
-    {
-        long rval = this.rel_value;
-        assert (rval >= 0);
-        if (rval == FOREVER.rel_value)
-            rval = -1L; /* 0xFFFFFFFFFFFFFFFF for network format! */
-        return new RelativeTimeNBO(rval);
-    }
-
-    /**
      * Subtract relative timestamp from the other.
      * 
      * @param other
@@ -171,4 +151,23 @@
             return new RelativeTime(this.rel_value - other.rel_value);
         }
     }
+
+    /**
+     * Converts relative time to an absolute time in the future.
+     * 
+     * @return timestamp that is in the future, or FOREVER if this=FOREVER (or
+     *         if we would overflow)
+     */
+    public AbsoluteTime toAbsolute() {
+        return AbsoluteTime.now().add(this);
+    }
+
+    public RelativeTimeNBO toNBO() {
+        long rval = this.rel_value;
+        assert rval >= 0;
+        if (rval == FOREVER.rel_value) {
+            rval = -1L; /* 0xFFFFFFFFFFFFFFFF for network format! */
+        }
+        return new RelativeTimeNBO(rval);
+    }
 }

Modified: gnunet-java/src/org/gnunet/util/Scheduler.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Scheduler.java      2011-11-30 15:21:36 UTC 
(rev 18410)
+++ gnunet-java/src/org/gnunet/util/Scheduler.java      2011-12-01 01:00:29 UTC 
(rev 18411)
@@ -44,9 +44,6 @@
  * @author Florian Dold
  */
 public class Scheduler {
-    private static final Logger logger = LoggerFactory
-            .getLogger(Scheduler.class);
-
     public enum Priority {
         IDLE, BACKGROUND, DEFAULT, HIGH, UI, URGENT, SHUTDOWN, _COUNT;
         static public final Priority KEEP = null;
@@ -56,48 +53,7 @@
         STARTUP, SHUTDOWN, TIMEOUT, READ_READY, WRITE_READY, PREREQ_DONE
     }
 
-    // tasks that are waiting for a delay to pass, will be moved to 'pending'
-    // eventually
-    private static Queue<TimeoutTask> pending_timeout = new 
PriorityQueue<TimeoutTask>();
-
-    // tasks that may be waiting for an event
-    private static List<TaskIdentifier> pending = new 
LinkedList<TaskIdentifier>();
-
-    // only valid while a task is executing
-    private static TaskIdentifier active_task;
-    
-    
-    static Priority current_priority;
-    static boolean current_liveness;
-
-    
-    // number of tasks in the ready queue
-    private static int ready_count = 0;
-
-    // for every priority, there is a list of tasks that is definitely ready to
-    // run
-    private static ArrayList<LinkedList<TaskIdentifier>> ready = new 
ArrayList<LinkedList<TaskIdentifier>>(
-            Priority._COUNT.ordinal());
-    static {
-        for (int i = 0; i < ready.size(); ++i) {
-            ready.set(i, new LinkedList<TaskIdentifier>());
-        }
-    }
-
-    private static Selector selector;
-    static {
-        try {
-            selector = SelectorProvider.provider().openSelector();
-        } catch (IOException e) {
-            // what to do here?
-            logger.error("fatal: cannot create selector");
-            System.exit(-1);
-        }
-    }
-
     public static interface Task {
-        public void run(Context ctx);
-
         // the context of a task is set in the task identifier once a task is
         // moved into the ready queue
         public static class Context {
@@ -105,37 +61,33 @@
             Set<Channel> readableSet = null;
             Set<Channel> writeableSet = null;
         }
+
+        public void run(Context ctx);
     }
 
-    final public static Task NO_TASK = new Task() {
-        @Override
-        public void run(Context ctx) {
-        }
-    };
-
     public static class TaskIdentifier {
         private final Task task;
         private final TaskIdentifier prereq;
-        private Task.Context ctx = new Task.Context();
+        private final Task.Context ctx = new Task.Context();
         boolean liveness;
         Priority priority;
 
-        TaskIdentifier(Task t, Priority priority, boolean liveness,
-                TaskIdentifier prereq) {
+        TaskIdentifier(final Task t, final Priority priority,
+                final boolean liveness, final TaskIdentifier prereq) {
             this.task = t;
-            this.priority = (priority == null) ? active_task.priority : 
priority;
+            this.priority = priority == null ? active_task.priority : priority;
             this.liveness = liveness;
             this.prereq = prereq;
         }
 
+        public void cancel() {
+            pending.remove(this);
+        }
+
         void run() {
             active_task = this;
             task.run(ctx);
         }
-
-        public void cancel() {
-            pending.remove(this);
-        }
     }
 
     static class TimeoutTask extends TaskIdentifier implements
@@ -143,8 +95,8 @@
         final AbsoluteTime timeout;
         boolean selected = false;
 
-        TimeoutTask(Task t, Priority p, boolean liveness,
-                TaskIdentifier prereq, RelativeTime delay) {
+        TimeoutTask(final Task t, final Priority p, final boolean liveness,
+                final TaskIdentifier prereq, final RelativeTime delay) {
             super(t, p, liveness, prereq);
             timeout = delay.toAbsolute();
         }
@@ -156,61 +108,107 @@
         }
 
         @Override
-        public int compareTo(TimeoutTask o) {
-            return (new Long(this.timeout.getMilliseconds())
-                    .compareTo(o.timeout.getMilliseconds()));
+        public int compareTo(final TimeoutTask o) {
+            return new Long(this.timeout.getMilliseconds()).compareTo(o.timeout
+                    .getMilliseconds());
         }
     }
 
-    /**
-     * Schedule a new task to be run as soon as possible. The task will be run
-     * with the priority of the calling task.
-     * 
-     * @param task
-     *            main function of the task
-     * @param task_cls
-     *            closure of task
-     * @return unique task identifier for the job only valid until "task" is
-     *         started!
-     */
-    public static TaskIdentifier addNow(Task task) {
-        return addSelect(Priority.KEEP, null, RelativeTime.ZERO, null, null,
-                task);
+    private static final Logger logger = LoggerFactory
+            .getLogger(Scheduler.class);
+
+    // tasks that are waiting for a delay to pass, will be moved to 'pending'
+    // eventually
+    private static Queue<TimeoutTask> pending_timeout = new 
PriorityQueue<TimeoutTask>();
+    // tasks that may be waiting for an event
+    private static List<TaskIdentifier> pending = new 
LinkedList<TaskIdentifier>();
+
+    // only valid while a task is executing
+    private static TaskIdentifier active_task;
+
+    static Priority current_priority;
+    static boolean current_liveness;
+
+    // number of tasks in the ready queue
+    private static int ready_count = 0;
+    // for every priority, there is a list of tasks that is definitely ready to
+    // run
+    private static ArrayList<LinkedList<TaskIdentifier>> ready = new 
ArrayList<LinkedList<TaskIdentifier>>(
+            Priority._COUNT.ordinal());
+
+    static {
+        for (int i = 0; i < ready.size(); ++i) {
+            ready.set(i, new LinkedList<TaskIdentifier>());
+        }
     }
 
-    public static TaskIdentifier addDelayed(RelativeTime delay, Task task) {
-        return addSelect(Priority.KEEP, null, delay, null, null, task);
+    private static Selector selector;
+
+    static {
+        try {
+            selector = SelectorProvider.provider().openSelector();
+        } catch (final IOException e) {
+            // what to do here?
+            logger.error("fatal: cannot create selector");
+            System.exit(-1);
+        }
     }
 
+    final public static Task NO_TASK = new Task() {
+        @Override
+        public void run(final Context ctx) {
+        }
+    };
+
+    public static TaskIdentifier addAfter(final TaskIdentifier prereq,
+            final Task t) {
+        return addSelect(Priority.KEEP, prereq, RelativeTime.ZERO, null, null,
+                t);
+    }
+
     /**
      * Run the task regardless of any prerequisites, before any other task of
      * the same priority.
      */
-    public static void addContinuation(Task task, EnumSet<Reason> reason) {
+    public static void addContinuation(final Task task,
+            final EnumSet<Reason> reason) {
         assert active_task == null || active_task.priority != null;
-        TaskIdentifier tid = new TaskIdentifier(task, Priority.KEEP,
+        final TaskIdentifier tid = new TaskIdentifier(task, Priority.KEEP,
                 current_liveness, null);
         queueReady(tid);
     }
 
-    public static TaskIdentifier addAfter(TaskIdentifier prereq, Task t) {
-        return addSelect(Priority.KEEP, prereq, RelativeTime.ZERO, null, null,
-                t);
+    public static TaskIdentifier addDelayed(final RelativeTime delay,
+            final Task task) {
+        return addSelect(Priority.KEEP, null, delay, null, null, task);
     }
 
-    public static TaskIdentifier addWithPriority(Priority prio, Task t) {
-        return addSelect(prio, null, RelativeTime.ZERO, null, null, t);
+    /**
+     * Schedule a new task to be run as soon as possible. The task will be run
+     * with the priority of the calling task.
+     * 
+     * @param task
+     *            main function of the task
+     * @param task_cls
+     *            closure of task
+     * @return unique task identifier for the job only valid until "task" is
+     *         started!
+     */
+    public static TaskIdentifier addNow(final Task task) {
+        return addSelect(Priority.KEEP, null, RelativeTime.ZERO, null, null,
+                task);
     }
 
     // should register the channels with the selector
-    public static TaskIdentifier addSelect(Priority p, TaskIdentifier prereq,
-            RelativeTime delay, Set<SelectableChannel> rs,
-            Set<SelectableChannel> ws, Task t) {
+    public static TaskIdentifier addSelect(final Priority p,
+            final TaskIdentifier prereq, final RelativeTime delay,
+            final Set<SelectableChannel> rs, final Set<SelectableChannel> ws,
+            final Task t) {
         if (rs != null) {
-            for (SelectableChannel s : rs) {
+            for (final SelectableChannel s : rs) {
                 try {
                     s.register(selector, SelectionKey.OP_READ, null);
-                } catch (ClosedChannelException e) {
+                } catch (final ClosedChannelException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
@@ -218,10 +216,10 @@
 
         }
         if (ws != null) {
-            for (SelectableChannel s : ws) {
+            for (final SelectableChannel s : ws) {
                 try {
                     s.register(selector, SelectionKey.OP_WRITE, null);
-                } catch (ClosedChannelException e) {
+                } catch (final ClosedChannelException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
@@ -229,47 +227,61 @@
 
         }
 
-        TimeoutTask tid = new TimeoutTask(t, p, active_task.liveness, prereq, 
delay);
+        final TimeoutTask tid = new TimeoutTask(t, p, active_task.liveness,
+                prereq, delay);
 
         return tid;
 
     }
 
-    /**
-     * Request the shutdown of a scheduler. Marks all currently pending tasks 
as
-     * ready because of shutdown. This will cause all tasks to run (as soon as
-     * possible, respecting priorities and prerequisite tasks). Note that tasks
-     * scheduled AFTER this call may still be delayed arbitrarily.
-     */
-    public static void shutdown() {
-        throw new UnsupportedOperationException();
+    public static TaskIdentifier addWithPriority(final Priority prio,
+            final Task t) {
+        return addSelect(prio, null, RelativeTime.ZERO, null, null, t);
     }
 
     /**
-     * Get information about the current load of this scheduler. Use this
-     * function to determine if an elective task should be added or simply
-     * dropped (if the decision should be made based on the number of tasks
-     * ready to run).
+     * Check if the system is still life. Trigger shutdown if we have tasks, 
but
+     * none of them give us lifeness.
      * 
-     * * @param p priority-level to query, use KEEP to query the level of the
-     * current task, use COUNT to get the sum over all priority levels
-     * 
-     * @return number of tasks pending right now
+     * @return true to continue the main loop, false to exit
      */
-    public int getLoad(Priority p) {
-        throw new UnsupportedOperationException();
+    private static boolean checkLiveness() {
+        if (ready_count > 0) {
+            return true;
+        }
+
+        for (final TaskIdentifier t : pending) {
+            if (t.liveness) {
+                return true;
+            }
+        }
+
+        for (final TaskIdentifier t : pending_timeout) {
+            if (t.liveness) {
+                return true;
+            }
+        }
+
+        if (!pending.isEmpty() || pending_timeout.isEmpty()) {
+            shutdown();
+            return true;
+        }
+
+        return false;
     }
 
-    /**
-     * Obtain the reason code for why the current task was started. Will return
-     * the same value as the GNUNET_SCHEDULER_TaskContext's reason field.
-     * 
-     * * @return reason(s) why the current task is run
-     */
-    public EnumSet<Reason> getReason() {
-        return active_task.ctx.reasons;
+    private static void queueReady(final TaskIdentifier tid) {
+        assert tid.priority != null;
+        ready.get(tid.priority.ordinal()).add(tid);
+        ready_count++;
     }
 
+    private static void register(final TimeoutTask t) {
+        // register with selector
+        throw new UnsupportedOperationException();
+
+    }
+
     /**
      * Initialize and run scheduler. This function will return when all tasks
      * have completed. On systems with signals, receiving a SIGTERM (and other
@@ -284,7 +296,7 @@
      *            task to run immediately
      * @throws IOException
      */
-    public static void run(Task task) throws IOException {
+    public static void run(final Task task) throws IOException {
         current_priority = Priority.DEFAULT;
         current_liveness = true;
 
@@ -300,10 +312,10 @@
                 timeout = RelativeTime.FOREVER;
             }
 
-            AbsoluteTime now = AbsoluteTime.now();
+            final AbsoluteTime now = AbsoluteTime.now();
 
             while (true) {
-                TimeoutTask t = pending_timeout.peek();
+                final TimeoutTask t = pending_timeout.peek();
 
                 if (t == null || t.timeout.compareTo(now) < 0) {
                     break;
@@ -316,9 +328,9 @@
 
             selector.select(timeout.getMilliseconds());
 
-            for (SelectionKey sk : selector.selectedKeys()) {
+            for (final SelectionKey sk : selector.selectedKeys()) {
                 sk.cancel();
-                TimeoutTask tid = (TimeoutTask) sk.attachment();
+                final TimeoutTask tid = (TimeoutTask) sk.attachment();
                 if (!tid.selected) {
                     queueReady(tid);
                 } else {
@@ -330,18 +342,6 @@
         }
     }
 
-    private static void register(TimeoutTask t) {
-        // register with selector
-        throw new UnsupportedOperationException();
-
-    }
-
-    private static void queueReady(TaskIdentifier tid) {
-        assert tid.priority != null;
-        ready.get(tid.priority.ordinal()).add(tid);
-        ready_count++;
-    }
-
     /*-
      * Execute tasks until there either
      * - there are no ready tasks
@@ -355,7 +355,7 @@
 
             // in contrast to the c implementation, p<=0 right here
             for (int p = Priority._COUNT.ordinal(); p <= 0; p--) {
-                TaskIdentifier tid = ready.get(p).pollFirst();
+                final TaskIdentifier tid = ready.get(p).pollFirst();
                 if (tid == null) {
                     break;
                 } else {
@@ -368,34 +368,38 @@
     }
 
     /**
-     * Check if the system is still life. Trigger shutdown if we have tasks, 
but
-     * none of them give us lifeness.
+     * Request the shutdown of a scheduler. Marks all currently pending tasks 
as
+     * ready because of shutdown. This will cause all tasks to run (as soon as
+     * possible, respecting priorities and prerequisite tasks). Note that tasks
+     * scheduled AFTER this call may still be delayed arbitrarily.
+     */
+    public static void shutdown() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get information about the current load of this scheduler. Use this
+     * function to determine if an elective task should be added or simply
+     * dropped (if the decision should be made based on the number of tasks
+     * ready to run).
      * 
-     * @return true to continue the main loop, false to exit
+     * * @param p priority-level to query, use KEEP to query the level of the
+     * current task, use COUNT to get the sum over all priority levels
+     * 
+     * @return number of tasks pending right now
      */
-    private static boolean checkLiveness() {
-        if (ready_count > 0) {
-            return true;
-        }
+    public int getLoad(final Priority p) {
+        throw new UnsupportedOperationException();
+    }
 
-        for (TaskIdentifier t : pending) {
-            if (t.liveness) {
-                return true;
-            }
-        }
-
-        for (TaskIdentifier t : pending_timeout) {
-            if (t.liveness) {
-                return true;
-            }
-        }
-
-        if (!pending.isEmpty() || pending_timeout.isEmpty()) {
-            shutdown();
-            return true;
-        }
-
-        return false;
+    /**
+     * Obtain the reason code for why the current task was started. Will return
+     * the same value as the GNUNET_SCHEDULER_TaskContext's reason field.
+     * 
+     * * @return reason(s) why the current task is run
+     */
+    public EnumSet<Reason> getReason() {
+        return active_task.ctx.reasons;
     }
 
 }

Modified: gnunet-java/src/org/gnunet/util/TransmitReadyNotify.java
===================================================================
--- gnunet-java/src/org/gnunet/util/TransmitReadyNotify.java    2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/util/TransmitReadyNotify.java    2011-12-01 
01:00:29 UTC (rev 18411)
@@ -16,9 +16,8 @@
      along with GNUnet; see the file COPYING.  If not, write to the
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
-*/
+ */
 
-
 package org.gnunet.util;
 
 import java.nio.ByteBuffer;
@@ -34,5 +33,5 @@
     // (buffer is initially at mark, data up to limit can be send at once,
     // capacity may not be exceeded
     public void transmit(ByteBuffer buf);
-    
+
 }

Modified: gnunet-java/src/org/gnunet/util/datastructures/BloomFilter.java
===================================================================
--- gnunet-java/src/org/gnunet/util/datastructures/BloomFilter.java     
2011-11-30 15:21:36 UTC (rev 18410)
+++ gnunet-java/src/org/gnunet/util/datastructures/BloomFilter.java     
2011-12-01 01:00:29 UTC (rev 18411)
@@ -25,140 +25,101 @@
 /**
  * Implementation of a Bloom-filter, as described here:
  * http://en.wikipedia.org/wiki/Bloom_filter
- *
+ * 
  * For updates and bugfixes, see http://github.com/magnuss/java-bloomfilter
- *
+ * 
  * Inspired by the SimpleBloomFilter-class written by Ian Clarke. This
- * implementation provides a more evenly distributed Hash-function by
- * using a proper digest instead of the Java RNG. Many of the changes
- * were proposed in comments in his blog:
- * 
http://blog.locut.us/2008/01/12/a-decent-stand-alone-java-bloom-filter-implementation/
- *
- * @param <E> Object type that is to be inserted into the Bloom filter, e.g. 
String or Integer.
+ * implementation provides a more evenly distributed Hash-function by using a
+ * proper digest instead of the Java RNG. Many of the changes were proposed in
+ * comments in his blog:
+ * http://blog.locut.us/2008/01/12/a-decent-stand-alone-java
+ * -bloom-filter-implementation/
+ * 
+ * @param <E>
+ *            Object type that is to be inserted into the Bloom filter, e.g.
+ *            String or Integer.
  * @author Magnus Skjegstad <address@hidden>
  */
 public class BloomFilter<E> implements Serializable {
     private BitSet bitset;
     private int bitSetSize;
     private double bitsPerElement;
-    private int expectedNumberOfFilterElements; // expected (maximum) number 
of elements to be added
-    private int numberOfAddedElements; // number of elements actually added to 
the Bloom filter
+    private int expectedNumberOfFilterElements; // expected (maximum) number of
+                                                // elements to be added
+    private int numberOfAddedElements; // number of elements actually added to
+                                       // the Bloom filter
     private int k; // number of hash functions
 
-    static final Charset charset = Charset.forName("UTF-8"); // encoding used 
for storing hash values as strings
+    static final Charset charset = Charset.forName("UTF-8"); // encoding used
+                                                             // for storing 
hash
+                                                             // values as
+                                                             // strings
 
-    static final String hashName = "MD5"; // MD5 gives good enough accuracy in 
most circumstances. Change to SHA1 if it's needed
+    static final String hashName = "MD5"; // MD5 gives good enough accuracy in
+                                          // most circumstances. Change to SHA1
+                                          // if it's needed
     static final MessageDigest digestFunction;
     static { // The digest method is reused between instances
         MessageDigest tmp;
         try {
             tmp = java.security.MessageDigest.getInstance(hashName);
-        } catch (NoSuchAlgorithmException e) {
+        } catch (final NoSuchAlgorithmException e) {
             tmp = null;
         }
         digestFunction = tmp;
     }
 
     /**
-      * Constructs an empty Bloom filter. The total length of the Bloom filter 
will be
-      * c*n.
-      *
-      * @param c is the number of bits used per element.
-      * @param n is the expected number of elements the filter will contain.
-      * @param k is the number of hash functions used.
-      */
-    public BloomFilter(double c, int n, int k) {
-      this.expectedNumberOfFilterElements = n;
-      this.k = k;
-      this.bitsPerElement = c;
-      this.bitSetSize = (int)Math.ceil(c * n);
-      numberOfAddedElements = 0;
-      this.bitset = new BitSet(bitSetSize);
-    }
-
-    /**
-     * Constructs an empty Bloom filter. The optimal number of hash functions 
(k) is estimated from the total size of the Bloom
-     * and the number of expected elements.
-     *
-     * @param bitSetSize defines how many bits should be used in total for the 
filter.
-     * @param expectedNumberOElements defines the maximum number of elements 
the filter is expected to contain.
-     */
-    public BloomFilter(int bitSetSize, int expectedNumberOElements) {
-        this(bitSetSize / (double)expectedNumberOElements,
-             expectedNumberOElements,
-             (int) Math.round((bitSetSize / (double)expectedNumberOElements) * 
Math.log(2.0)));
-    }
-
-    /**
-     * Constructs an empty Bloom filter with a given false positive 
probability. The number of bits per
-     * element and the number of hash functions is estimated
-     * to match the false positive probability.
-     *
-     * @param falsePositiveProbability is the desired false positive 
probability.
-     * @param expectedNumberOfElements is the expected number of elements in 
the Bloom filter.
-     */
-    public BloomFilter(double falsePositiveProbability, int 
expectedNumberOfElements) {
-        this(Math.ceil(-(Math.log(falsePositiveProbability) / Math.log(2))) / 
Math.log(2), // c = k / ln(2)
-             expectedNumberOfElements,
-             (int)Math.ceil(-(Math.log(falsePositiveProbability) / 
Math.log(2)))); // k = ceil(-log_2(false prob.))
-    }
-
-    /**
-     * Construct a new Bloom filter based on existing Bloom filter data.
-     *
-     * @param bitSetSize defines how many bits should be used for the filter.
-     * @param expectedNumberOfFilterElements defines the maximum number of 
elements the filter is expected to contain.
-     * @param actualNumberOfFilterElements specifies how many elements have 
been inserted into the <code>filterData</code> BitSet.
-     * @param filterData a BitSet representing an existing Bloom filter.
-     */
-    public BloomFilter(int bitSetSize, int expectedNumberOfFilterElements, int 
actualNumberOfFilterElements, BitSet filterData) {
-        this(bitSetSize, expectedNumberOfFilterElements);
-        this.bitset = filterData;
-        this.numberOfAddedElements = actualNumberOfFilterElements;
-    }
-
-    /**
-     * Generates a digest based on the contents of a String.
-     *
-     * @param val specifies the input data.
-     * @param charset specifies the encoding of the input data.
+     * Generates a digest based on the contents of an array of bytes.
+     * 
+     * @param data
+     *            specifies input data.
      * @return digest as long.
      */
-    public static int createHash(String val, Charset charset) {
-        return createHash(val.getBytes(charset));
+    public static int createHash(final byte[] data) {
+        return createHashes(data, 1)[0];
     }
 
     /**
      * Generates a digest based on the contents of a String.
-     *
-     * @param val specifies the input data. The encoding is expected to be 
UTF-8.
+     * 
+     * @param val
+     *            specifies the input data. The encoding is expected to be
+     *            UTF-8.
      * @return digest as long.
      */
-    public static int createHash(String val) {
+    public static int createHash(final String val) {
         return createHash(val, charset);
     }
 
     /**
-     * Generates a digest based on the contents of an array of bytes.
-     *
-     * @param data specifies input data.
+     * Generates a digest based on the contents of a String.
+     * 
+     * @param val
+     *            specifies the input data.
+     * @param charset
+     *            specifies the encoding of the input data.
      * @return digest as long.
      */
-    public static int createHash(byte[] data) {
-        return createHashes(data, 1)[0];
+    public static int createHash(final String val, final Charset charset) {
+        return createHash(val.getBytes(charset));
     }
 
     /**
-     * Generates digests based on the contents of an array of bytes and splits 
the result into 4-byte int's and store them in an array. The
-     * digest function is called until the required number of int's are 
produced. For each call to digest a salt
-     * is prepended to the data. The salt is increased by 1 for each call.
-     *
-     * @param data specifies input data.
-     * @param hashes number of hashes/int's to produce.
+     * Generates digests based on the contents of an array of bytes and splits
+     * the result into 4-byte int's and store them in an array. The digest
+     * function is called until the required number of int's are produced. For
+     * each call to digest a salt is prepended to the data. The salt is
+     * increased by 1 for each call.
+     * 
+     * @param data
+     *            specifies input data.
+     * @param hashes
+     *            number of hashes/int's to produce.
      * @return array of int-sized hashes
      */
-    public static int[] createHashes(byte[] data, int hashes) {
-        int[] result = new int[hashes];
+    public static int[] createHashes(final byte[] data, final int hashes) {
+        final int[] result = new int[hashes];
 
         int k = 0;
         byte salt = 0;
@@ -167,14 +128,14 @@
             synchronized (digestFunction) {
                 digestFunction.update(salt);
                 salt++;
-                digest = digestFunction.digest(data);                
+                digest = digestFunction.digest(data);
             }
-        
-            for (int i = 0; i < digest.length/4 && k < hashes; i++) {
+
+            for (int i = 0; i < digest.length / 4 && k < hashes; i++) {
                 int h = 0;
-                for (int j = (i*4); j < (i*4)+4; j++) {
+                for (int j = i * 4; j < i * 4 + 4; j++) {
                     h <<= 8;
-                    h |= ((int) digest[j]) & 0xFF;
+                    h |= digest[j] & 0xFF;
                 }
                 result[k] = h;
                 k++;
@@ -184,100 +145,119 @@
     }
 
     /**
-     * Compares the contents of two instances to see if they are equal.
-     *
-     * @param obj is the object to compare to.
-     * @return True if the contents of the objects are equal.
+     * Constructs an empty Bloom filter with a given false positive 
probability.
+     * The number of bits per element and the number of hash functions is
+     * estimated to match the false positive probability.
+     * 
+     * @param falsePositiveProbability
+     *            is the desired false positive probability.
+     * @param expectedNumberOfElements
+     *            is the expected number of elements in the Bloom filter.
      */
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final BloomFilter<E> other = (BloomFilter<E>) obj;        
-        if (this.expectedNumberOfFilterElements != 
other.expectedNumberOfFilterElements) {
-            return false;
-        }
-        if (this.k != other.k) {
-            return false;
-        }
-        if (this.bitSetSize != other.bitSetSize) {
-            return false;
-        }
-        if (this.bitset != other.bitset && (this.bitset == null || 
!this.bitset.equals(other.bitset))) {
-            return false;
-        }
-        return true;
+    public BloomFilter(final double falsePositiveProbability,
+            final int expectedNumberOfElements) {
+        this(Math.ceil(-(Math.log(falsePositiveProbability) / Math.log(2)))
+                / Math.log(2), // c = k / ln(2)
+                expectedNumberOfElements, (int) Math.ceil(-(Math
+                        .log(falsePositiveProbability) / Math.log(2)))); // k =
+                                                                         // 
ceil(-log_2(false
+                                                                         // 
prob.))
     }
 
     /**
-     * Calculates a hash code for this class.
-     * @return hash code representing the contents of an instance of this 
class.
+     * Constructs an empty Bloom filter. The total length of the Bloom filter
+     * will be c*n.
+     * 
+     * @param c
+     *            is the number of bits used per element.
+     * @param n
+     *            is the expected number of elements the filter will contain.
+     * @param k
+     *            is the number of hash functions used.
      */
-    @Override
-    public int hashCode() {
-        int hash = 7;
-        hash = 61 * hash + (this.bitset != null ? this.bitset.hashCode() : 0);
-        hash = 61 * hash + this.expectedNumberOfFilterElements;
-        hash = 61 * hash + this.bitSetSize;
-        hash = 61 * hash + this.k;
-        return hash;
+    public BloomFilter(final double c, final int n, final int k) {
+        this.expectedNumberOfFilterElements = n;
+        this.k = k;
+        this.bitsPerElement = c;
+        this.bitSetSize = (int) Math.ceil(c * n);
+        numberOfAddedElements = 0;
+        this.bitset = new BitSet(bitSetSize);
     }
 
+    /**
+     * Constructs an empty Bloom filter. The optimal number of hash functions
+     * (k) is estimated from the total size of the Bloom and the number of
+     * expected elements.
+     * 
+     * @param bitSetSize
+     *            defines how many bits should be used in total for the filter.
+     * @param expectedNumberOElements
+     *            defines the maximum number of elements the filter is expected
+     *            to contain.
+     */
+    public BloomFilter(final int bitSetSize, final int 
expectedNumberOElements) {
+        this(bitSetSize / (double) expectedNumberOElements,
+                expectedNumberOElements, (int) Math.round(bitSetSize
+                        / (double) expectedNumberOElements * Math.log(2.0)));
+    }
 
     /**
-     * Calculates the expected probability of false positives based on
-     * the number of expected filter elements and the size of the Bloom filter.
-     * <br /><br />
-     * The value returned by this method is the <i>expected</i> rate of false
-     * positives, assuming the number of inserted elements equals the number of
-     * expected elements. If the number of elements in the Bloom filter is less
-     * than the expected value, the true probability of false positives will 
be lower.
-     *
-     * @return expected probability of false positives.
+     * Construct a new Bloom filter based on existing Bloom filter data.
+     * 
+     * @param bitSetSize
+     *            defines how many bits should be used for the filter.
+     * @param expectedNumberOfFilterElements
+     *            defines the maximum number of elements the filter is expected
+     *            to contain.
+     * @param actualNumberOfFilterElements
+     *            specifies how many elements have been inserted into the
+     *            <code>filterData</code> BitSet.
+     * @param filterData
+     *            a BitSet representing an existing Bloom filter.
      */
-    public double expectedFalsePositiveProbability() {
-        return getFalsePositiveProbability(expectedNumberOfFilterElements);
+    public BloomFilter(final int bitSetSize,
+            final int expectedNumberOfFilterElements,
+            final int actualNumberOfFilterElements, final BitSet filterData) {
+        this(bitSetSize, expectedNumberOfFilterElements);
+        this.bitset = filterData;
+        this.numberOfAddedElements = actualNumberOfFilterElements;
     }
 
     /**
-     * Calculate the probability of a false positive given the specified
-     * number of inserted elements.
-     *
-     * @param numberOfElements number of inserted elements.
-     * @return probability of a false positive.
+     * Adds an array of bytes to the Bloom filter.
+     * 
+     * @param bytes
+     *            array of bytes to add to the Bloom filter.
      */
-    public double getFalsePositiveProbability(double numberOfElements) {
-        // (1 - e^(-k * n / m)) ^ k
-        return Math.pow((1 - Math.exp(-k * (double) numberOfElements
-                        / (double) bitSetSize)), k);
-
+    public void add(final byte[] bytes) {
+        final int[] hashes = createHashes(bytes, k);
+        for (final int hash : hashes) {
+            bitset.set(Math.abs(hash % bitSetSize), true);
+        }
+        numberOfAddedElements++;
     }
 
     /**
-     * Get the current probability of a false positive. The probability is 
calculated from
-     * the size of the Bloom filter and the current number of elements added 
to it.
-     *
-     * @return probability of false positives.
+     * Adds an object to the Bloom filter. The output from the object's
+     * toString() method is used as input to the hash functions.
+     * 
+     * @param element
+     *            is an element to register in the Bloom filter.
      */
-    public double getFalsePositiveProbability() {
-        return getFalsePositiveProbability(numberOfAddedElements);
+    public void add(final E element) {
+        add(element.toString().getBytes(charset));
     }
 
-
     /**
-     * Returns the value chosen for K.<br />
-     * <br />
-     * K is the optimal number of hash functions based on the size
-     * of the Bloom filter and the expected number of inserted elements.
-     *
-     * @return optimal k.
+     * Adds all elements from a Collection to the Bloom filter.
+     * 
+     * @param c
+     *            Collection of elements.
      */
-    public int getK() {
-        return k;
+    public void addAll(final Collection<? extends E> c) {
+        for (final E element : c) {
+            add(element);
+        }
     }
 
     /**
@@ -289,100 +269,129 @@
     }
 
     /**
-     * Adds an object to the Bloom filter. The output from the object's
-     * toString() method is used as input to the hash functions.
-     *
-     * @param element is an element to register in the Bloom filter.
+     * Returns true if the array of bytes could have been inserted into the
+     * Bloom filter. Use getFalsePositiveProbability() to calculate the
+     * probability of this being correct.
+     * 
+     * @param bytes
+     *            array of bytes to check.
+     * @return true if the array could have been inserted into the Bloom 
filter.
      */
-    public void add(E element) {
-       add(element.toString().getBytes(charset));
+    public boolean contains(final byte[] bytes) {
+        final int[] hashes = createHashes(bytes, k);
+        for (final int hash : hashes) {
+            if (!bitset.get(Math.abs(hash % bitSetSize))) {
+                return false;
+            }
+        }
+        return true;
     }
 
     /**
-     * Adds an array of bytes to the Bloom filter.
-     *
-     * @param bytes array of bytes to add to the Bloom filter.
+     * Returns true if the element could have been inserted into the Bloom
+     * filter. Use getFalsePositiveProbability() to calculate the probability 
of
+     * this being correct.
+     * 
+     * @param element
+     *            element to check.
+     * @return true if the element could have been inserted into the Bloom
+     *         filter.
      */
-    public void add(byte[] bytes) {
-       int[] hashes = createHashes(bytes, k);
-       for (int hash : hashes)
-           bitset.set(Math.abs(hash % bitSetSize), true);
-       numberOfAddedElements ++;
+    public boolean contains(final E element) {
+        return contains(element.toString().getBytes(charset));
     }
 
     /**
-     * Adds all elements from a Collection to the Bloom filter.
-     * @param c Collection of elements.
+     * Returns true if all the elements of a Collection could have been 
inserted
+     * into the Bloom filter. Use getFalsePositiveProbability() to calculate 
the
+     * probability of this being correct.
+     * 
+     * @param c
+     *            elements to check.
+     * @return true if all the elements in c could have been inserted into the
+     *         Bloom filter.
      */
-    public void addAll(Collection<? extends E> c) {
-        for (E element : c)
-            add(element);
+    public boolean containsAll(final Collection<? extends E> c) {
+        for (final E element : c) {
+            if (!contains(element)) {
+                return false;
+            }
+        }
+        return true;
     }
-        
+
     /**
-     * Returns true if the element could have been inserted into the Bloom 
filter.
-     * Use getFalsePositiveProbability() to calculate the probability of this
-     * being correct.
-     *
-     * @param element element to check.
-     * @return true if the element could have been inserted into the Bloom 
filter.
+     * Returns the number of elements added to the Bloom filter after it was
+     * constructed or after clear() was called.
+     * 
+     * @return number of elements added to the Bloom filter.
      */
-    public boolean contains(E element) {
-        return contains(element.toString().getBytes(charset));
+    public int count() {
+        return this.numberOfAddedElements;
     }
 
     /**
-     * Returns true if the array of bytes could have been inserted into the 
Bloom filter.
-     * Use getFalsePositiveProbability() to calculate the probability of this
-     * being correct.
-     *
-     * @param bytes array of bytes to check.
-     * @return true if the array could have been inserted into the Bloom 
filter.
+     * Compares the contents of two instances to see if they are equal.
+     * 
+     * @param obj
+     *            is the object to compare to.
+     * @return True if the contents of the objects are equal.
      */
-    public boolean contains(byte[] bytes) {
-        int[] hashes = createHashes(bytes, k);
-        for (int hash : hashes) {
-            if (!bitset.get(Math.abs(hash % bitSetSize))) {
-                return false;
-            }
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
         }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final BloomFilter<E> other = (BloomFilter<E>) obj;
+        if (this.expectedNumberOfFilterElements != 
other.expectedNumberOfFilterElements) {
+            return false;
+        }
+        if (this.k != other.k) {
+            return false;
+        }
+        if (this.bitSetSize != other.bitSetSize) {
+            return false;
+        }
+        if (this.bitset != other.bitset
+                && (this.bitset == null || !this.bitset.equals(other.bitset))) 
{
+            return false;
+        }
         return true;
     }
 
     /**
-     * Returns true if all the elements of a Collection could have been 
inserted
-     * into the Bloom filter. Use getFalsePositiveProbability() to calculate 
the
-     * probability of this being correct.
-     * @param c elements to check.
-     * @return true if all the elements in c could have been inserted into the 
Bloom filter.
+     * Calculates the expected probability of false positives based on the
+     * number of expected filter elements and the size of the Bloom filter. 
<br />
+     * <br />
+     * The value returned by this method is the <i>expected</i> rate of false
+     * positives, assuming the number of inserted elements equals the number of
+     * expected elements. If the number of elements in the Bloom filter is less
+     * than the expected value, the true probability of false positives will be
+     * lower.
+     * 
+     * @return expected probability of false positives.
      */
-    public boolean containsAll(Collection<? extends E> c) {
-        for (E element : c)
-            if (!contains(element))
-                return false;
-        return true;
+    public double expectedFalsePositiveProbability() {
+        return getFalsePositiveProbability(expectedNumberOfFilterElements);
     }
 
     /**
      * Read a single bit from the Bloom filter.
-     * @param bit the bit to read.
+     * 
+     * @param bit
+     *            the bit to read.
      * @return true if the bit is set, false if it is not.
      */
-    public boolean getBit(int bit) {
+    public boolean getBit(final int bit) {
         return bitset.get(bit);
     }
 
     /**
-     * Set a single bit in the Bloom filter.
-     * @param bit is the bit to set.
-     * @param value If true, the bit is set. If false, the bit is cleared.
-     */
-    public void setBit(int bit, boolean value) {
-        bitset.set(bit, value);
-    }
-
-    /**
      * Return the bit set used to store the Bloom filter.
+     * 
      * @return bit set representing the Bloom filter.
      */
     public BitSet getBitSet() {
@@ -390,29 +399,31 @@
     }
 
     /**
-     * Returns the number of bits in the Bloom filter. Use count() to retrieve
-     * the number of inserted elements.
-     *
-     * @return the size of the bitset used by the Bloom filter.
+     * Get actual number of bits per element based on the number of elements
+     * that have currently been inserted and the length of the Bloom filter. 
See
+     * also getExpectedBitsPerElement().
+     * 
+     * @return number of bits per element.
      */
-    public int size() {
-        return this.bitSetSize;
+    public double getBitsPerElement() {
+        return this.bitSetSize / (double) numberOfAddedElements;
     }
 
     /**
-     * Returns the number of elements added to the Bloom filter after it
-     * was constructed or after clear() was called.
-     *
-     * @return number of elements added to the Bloom filter.
+     * Get expected number of bits per element when the Bloom filter is full.
+     * This value is set by the constructor when the Bloom filter is created.
+     * See also getBitsPerElement().
+     * 
+     * @return expected number of bits per element.
      */
-    public int count() {
-        return this.numberOfAddedElements;
+    public double getExpectedBitsPerElement() {
+        return this.bitsPerElement;
     }
 
     /**
      * Returns the expected number of elements to be inserted into the filter.
      * This value is the same value as the one passed to the constructor.
-     *
+     * 
      * @return expected number of elements.
      */
     public int getExpectedNumberOfElements() {
@@ -420,22 +431,76 @@
     }
 
     /**
-     * Get expected number of bits per element when the Bloom filter is full. 
This value is set by the constructor
-     * when the Bloom filter is created. See also getBitsPerElement().
-     *
-     * @return expected number of bits per element.
+     * Get the current probability of a false positive. The probability is
+     * calculated from the size of the Bloom filter and the current number of
+     * elements added to it.
+     * 
+     * @return probability of false positives.
      */
-    public double getExpectedBitsPerElement() {
-        return this.bitsPerElement;
+    public double getFalsePositiveProbability() {
+        return getFalsePositiveProbability(numberOfAddedElements);
     }
 
     /**
-     * Get actual number of bits per element based on the number of elements 
that have currently been inserted and the length
-     * of the Bloom filter. See also getExpectedBitsPerElement().
-     *
-     * @return number of bits per element.
+     * Calculate the probability of a false positive given the specified number
+     * of inserted elements.
+     * 
+     * @param numberOfElements
+     *            number of inserted elements.
+     * @return probability of a false positive.
      */
-    public double getBitsPerElement() {
-        return this.bitSetSize / (double)numberOfAddedElements;
+    public double getFalsePositiveProbability(final double numberOfElements) {
+        // (1 - e^(-k * n / m)) ^ k
+        return Math.pow(1 - Math.exp(-k * numberOfElements / bitSetSize), k);
+
     }
-}
\ No newline at end of file
+
+    /**
+     * Returns the value chosen for K.<br />
+     * <br />
+     * K is the optimal number of hash functions based on the size of the Bloom
+     * filter and the expected number of inserted elements.
+     * 
+     * @return optimal k.
+     */
+    public int getK() {
+        return k;
+    }
+
+    /**
+     * Calculates a hash code for this class.
+     * 
+     * @return hash code representing the contents of an instance of this 
class.
+     */
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        hash = 61 * hash + (this.bitset != null ? this.bitset.hashCode() : 0);
+        hash = 61 * hash + this.expectedNumberOfFilterElements;
+        hash = 61 * hash + this.bitSetSize;
+        hash = 61 * hash + this.k;
+        return hash;
+    }
+
+    /**
+     * Set a single bit in the Bloom filter.
+     * 
+     * @param bit
+     *            is the bit to set.
+     * @param value
+     *            If true, the bit is set. If false, the bit is cleared.
+     */
+    public void setBit(final int bit, final boolean value) {
+        bitset.set(bit, value);
+    }
+
+    /**
+     * Returns the number of bits in the Bloom filter. Use count() to retrieve
+     * the number of inserted elements.
+     * 
+     * @return the size of the bitset used by the Bloom filter.
+     */
+    public int size() {
+        return this.bitSetSize;
+    }
+}

Modified: gnunet-java/test/org/gnunet/construct/ConstructTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/ConstructTest.java    2011-11-30 
15:21:36 UTC (rev 18410)
+++ gnunet-java/test/org/gnunet/construct/ConstructTest.java    2011-12-01 
01:00:29 UTC (rev 18411)
@@ -1,86 +1,96 @@
 package org.gnunet.construct;
 
+import java.math.BigInteger;
+
 import org.gnunet.messages.MessageHeader;
+import org.gnunet.messages.QueryMessage;
 import org.gnunet.messages.SimpleTestMessage;
 import org.gnunet.messages.SimpleTestMessage2;
 import org.gnunet.messages.SizeTestMessage;
-import org.gnunet.messages.StringTestMessage;
-import org.gnunet.messages.TestMessage3;
-import org.gnunet.messages.TestMessage4;
+import org.gnunet.messages.StringMessage;
 import org.junit.Assert;
 import org.junit.Test;
 
 public class ConstructTest {
-
+    
     @Test
-    public void test_SimpleTestMessage_1() {
-        Parser op = Construct.makeParser(SimpleTestMessage.class);
-        byte[] a = { 0x02, 0x01, // v1
-                0x00, 0x1c, // v2
-                0x00, 0x00, 0x00, 0x05 // nested
-        };
-        SimpleTestMessage m = Construct.parseWith(op, a, 0);
-
-        Assert.assertTrue(m.v1 == ((0x02 << 8) | 0x01));
-        Assert.assertTrue(m.v2 == 0x1c);
-
-        Assert.assertEquals(8, Construct.estimateSize(m));
+    public void test_SimpleTestMessage() {
+        SimpleTestMessage stm = new SimpleTestMessage();
+        stm.v1 = 20;
+        stm.v2 = 21;
+        stm.mn = new SimpleTestMessage2();
+        stm.mn.value = 42;
+        stm.mns = new SimpleTestMessage2[5];
+        for (int i = 0; i < stm.mns.length; i++) {
+            stm.mns[i] = new SimpleTestMessage2();
+            stm.mns[i].value = i;
+        }
+        
+        byte[] a = Construct.toBinary(stm);
+        SimpleTestMessage stm2 = Construct.parseAs(a, 0, 
SimpleTestMessage.class);
+        
+        Assert.assertEquals(stm.v1, stm2.v1);
+        Assert.assertEquals(stm.v2, stm2.v2);
+        Assert.assertEquals(stm.mn.value, stm2.mn.value);
+        Assert.assertEquals(stm.mns.length, stm2.mns.length);
+        
+        for (int i = 0; i < stm.mns.length; i++) {
+            Assert.assertEquals(stm.mns[i].value, stm2.mns[i].value);
+            
+        }
+        
+        
     }
-
-    @Test
-    public void test_SimpleTestMessage_2() {
-        SimpleTestMessage m1 = new SimpleTestMessage();
-
-        m1.v1 = 42;
-        m1.v2 = 420;
-
-        m1.mn = new SimpleTestMessage2();
-        m1.mn.value = 300;
-
-        byte[] data = Construct.unparse(m1);
-
-        SimpleTestMessage m2 = Construct
-                .parse(data, 0, SimpleTestMessage.class);
-
-        Assert.assertEquals(m1, m2);
-
+    
+    public static String toHex(byte[] bytes) {
+        BigInteger bi = new BigInteger(1, bytes);
+        return String.format("%0" + (bytes.length << 1) + "X", bi);
     }
-
+    
     @Test
-    public void test_TestMessage3() {
-        TestMessage3 tm3 = new TestMessage3();
-        tm3.arr = new int[10];
+    public void test_StringMessage() {
+        StringMessage strm = new StringMessage();
+        strm.num = 58;
+        strm.str = "ab";
+        strm.num2 = 80;
+        
+        byte[] a = Construct.toBinary(strm);
+        StringMessage strm2 = Construct.parseAs(a, 0, StringMessage.class);
+        
+        for (byte b : a) {
+            System.out.print((char) b);
+        }
 
-        int size = Construct.estimateSize(tm3);
-
-        Assert.assertEquals(2 * 10, size);
-
-        byte[] data = Construct.unparse(tm3);
-
-        TestMessage3 tm3_2 = Construct.parse(data, 0, TestMessage3.class);
+        Assert.assertEquals(strm.num, strm2.num);
+        Assert.assertEquals(strm.num2, strm2.num2);
+        Assert.assertEquals(strm.str, strm2.str);
+        
     }
 
+    
     @Test
-    public void test_TestMessage4() {
-        TestMessage4 tm4 = new TestMessage4();
-        tm4.tm3s = new TestMessage3[3];
-
-        for (int i = 0; i < 3; ++i) {
-            TestMessage3 tm3 = new TestMessage3();
-            tm3.arr = new int[10];
-            tm4.tm3s[i] = tm3;
-        }
-
-        tm4.value = 54;
-
-        Assert.assertEquals(10*2*3 + 2, Construct.estimateSize(tm4));
+    public void test_QueryMessage() {
+        QueryMessage qm = new QueryMessage();
+        qm.header = new MessageHeader();
+        qm.header.type = 0x42;
+        qm.query = 0x43;
+        qm.varsize = new byte[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
         
-        byte[] data = Construct.unparse(tm4);
         
-        TestMessage4 tm4_2 = Construct.parse(data, 0, TestMessage4.class);
+        Construct.patchSizeFields(qm);
         
-        // do equality check
-        // [...]
+        
+        byte[] a = Construct.toBinary(qm);
+        
+        
+        QueryMessage qm2 = Construct.parseAs(a, 0, QueryMessage.class);
+        
+        
+        Assert.assertEquals(qm.header.size, qm2.header.size);
+        Assert.assertEquals(qm.header.type, qm2.header.type);
+        Assert.assertEquals(qm.query, qm2.query);
+        
+        Assert.assertArrayEquals(qm.varsize, qm2.varsize);
 
     }
     
@@ -88,40 +98,39 @@
     @Test
     public void test_SizeTestMessage() {
         SizeTestMessage stm = new SizeTestMessage();
+        stm.someValue = 42;
+        stm.rest = new byte[]{1,2,3,4,5};
         
-        byte[] data = Construct.unparse(stm);
+        Construct.patchSizeFields(stm);
         
-        int size = data[0] << 8 | data[1];
         
-        Assert.assertEquals(size, Construct.estimateSize(stm));
+        byte[] a = Construct.toBinary(stm);
         
-        SizeTestMessage stm_2 = Construct.parse(data, 0, 
SizeTestMessage.class);
+        SizeTestMessage stm2 = Construct.parseAs(a, 0, SizeTestMessage.class);
         
-        Assert.assertEquals(stm_2.total_size, Construct.estimateSize(stm_2));
+        Assert.assertEquals(stm.someValue, stm2.someValue);
+        Assert.assertEquals(stm.totalSize, stm2.totalSize);
+        
+        
+        Assert.assertArrayEquals(stm.rest, stm2.rest);   
     }
     
     @Test
-    public void test_StringTestMessage() {
-        StringTestMessage stm = new StringTestMessage();
-        stm.s = "Hallo, Welt!";
+    public void test_MessageHeader() {
+        MessageHeader h1 = new MessageHeader();
         
-        byte[] data = Construct.unparse(stm);
+        h1.size = 42;
+        h1.type = 52;
         
-        StringTestMessage stm_2 = Construct.parse(data, 0, 
StringTestMessage.class);
+        byte[] a = Construct.toBinary(h1);
         
-        Assert.assertEquals(stm.s, stm_2.s);
+        MessageHeader h2 = Construct.parseAs(a, 0, MessageHeader.class);
         
-    }
-    
-    @Test
-    public void test_MessageHeader() {
-        MessageHeader h = new MessageHeader();
-        h.type = 42;
-        h.body = new byte[20];
+        byte[] b = Construct.toBinary(h2);
         
-        byte[] data = Construct.unparse(h);
+        Assert.assertArrayEquals(a, b);
         
-        MessageHeader h2 = Construct.parse(data, 0, MessageHeader.class);
+        Assert.assertEquals(h1.size, h2.size);
+        Assert.assertEquals(h1.type, h2.type);
     }
-
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]