Full Code of JoshuaKissoon/Kademlia for AI

master cc62dff54cfd cached
86 files
295.1 KB
69.1k tokens
531 symbols
1 requests
Download .txt
Showing preview only (319K chars total). Download the full file or copy to clipboard to get everything.
Repository: JoshuaKissoon/Kademlia
Branch: master
Commit: cc62dff54cfd
Files: 86
Total size: 295.1 KB

Directory structure:
gitextract_uwntm7qj/

├── .gitignore
├── LICENSE
├── README.md
├── build.xml
├── manifest.mf
├── nbproject/
│   ├── build-impl.xml
│   ├── genfiles.properties
│   ├── project.properties
│   └── project.xml
└── src/
    └── kademlia/
        ├── DefaultConfiguration.java
        ├── JKademliaNode.java
        ├── KadConfiguration.java
        ├── KadServer.java
        ├── KadStatistician.java
        ├── KademliaNode.java
        ├── Statistician.java
        ├── Todo
        ├── dht/
        │   ├── DHT.java
        │   ├── GetParameter.java
        │   ├── JKademliaStorageEntry.java
        │   ├── KadContent.java
        │   ├── KademliaDHT.java
        │   ├── KademliaStorageEntry.java
        │   ├── KademliaStorageEntryMetadata.java
        │   ├── StorageEntryMetadata.java
        │   └── StoredContentManager.java
        ├── exceptions/
        │   ├── ContentExistException.java
        │   ├── ContentNotFoundException.java
        │   ├── KadServerDownException.java
        │   ├── RoutingException.java
        │   └── UnknownMessageException.java
        ├── message/
        │   ├── AcknowledgeMessage.java
        │   ├── ConnectMessage.java
        │   ├── ConnectReceiver.java
        │   ├── ContentLookupMessage.java
        │   ├── ContentLookupReceiver.java
        │   ├── ContentMessage.java
        │   ├── KademliaMessageFactory.java
        │   ├── Message.java
        │   ├── MessageFactory.java
        │   ├── NodeLookupMessage.java
        │   ├── NodeLookupReceiver.java
        │   ├── NodeReplyMessage.java
        │   ├── Receiver.java
        │   ├── SimpleMessage.java
        │   ├── SimpleReceiver.java
        │   ├── StoreContentMessage.java
        │   ├── StoreContentReceiver.java
        │   └── Streamable.java
        ├── node/
        │   ├── KademliaId.java
        │   ├── KeyComparator.java
        │   └── Node.java
        ├── operation/
        │   ├── BucketRefreshOperation.java
        │   ├── ConnectOperation.java
        │   ├── ContentLookupOperation.java
        │   ├── ContentRefreshOperation.java
        │   ├── KadRefreshOperation.java
        │   ├── NodeLookupOperation.java
        │   ├── Operation.java
        │   ├── PingOperation.java
        │   └── StoreOperation.java
        ├── routing/
        │   ├── Contact.java
        │   ├── ContactLastSeenComparator.java
        │   ├── JKademliaBucket.java
        │   ├── JKademliaRoutingTable.java
        │   ├── KademliaBucket.java
        │   └── KademliaRoutingTable.java
        ├── simulations/
        │   ├── AutoRefreshOperation.java
        │   ├── AutoRefreshOperation2.java
        │   ├── ContentSendingTest.java
        │   ├── ContentUpdatingTest.java
        │   ├── DHTContentImpl.java
        │   ├── NodeConnectionTest.java
        │   ├── RefreshOperationTest.java
        │   ├── RoutingTableSimulation.java
        │   ├── RoutingTableStateTesting.java
        │   ├── SaveStateTest.java
        │   ├── SaveStateTest2.java
        │   ├── SimpleMessageTest.java
        │   └── Simulation.java
        └── util/
            ├── HashCalculator.java
            ├── RouteLengthChecker.java
            └── serializer/
                ├── JsonDHTSerializer.java
                ├── JsonRoutingTableSerializer.java
                ├── JsonSerializer.java
                └── KadSerializer.java

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
/dist/
/build/

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2014 Joshua Kissoon

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
Kademlia
========

This is an implementation of the Kademlia (http://en.wikipedia.org/wiki/Kademlia) routing protocol and DHT. 

I wrote an article [An Introduction to Kademlia DHT & How It Works](http://gleamly.com/article/introduction-kademlia-dht-how-it-works). Have a read. 

Kademlia original Publication: http://link.springer.com/chapter/10.1007/3-540-45748-8_5

Note: This repository is a Netbeans project which you can simply download and import. 

Usage
-----
The Implementation is meant to be self contained and very easy to setup and use. There are several tests (https://github.com/JoshuaKissoon/Kademlia/tree/master/src/kademlia/tests) which demonstrates the usage of the protocol and DHT.


**Configuration**

There is a configuration file available in the kademlia.core package which have all settings used throughout the protocol, all of these settings are described in depth in the Configuration file.


**Creating a Kad Instance**

All of Kademlia's sub-components (DHT, Node, Routing Table, Server, etc) are wrapped within the Kademlia object to simplify the usage of the protocol. To create an instance, simply call:

```Java
Kademlia kad1 = new Kademlia("OwnerName1", new NodeId("ASF45678947584567463"), 12049);
Kademlia kad2 = new Kademlia("OwnerName2", new NodeId(), 12057);  // Random NodeId will be generated
```
Param 1: The Name of the owner of this instance, can be any name.
Param 2: A NodeId for this node
Param 3: The port on which this Kademlia instance will run on.

After this initialization phase, the 2 Kad instances will basically be 2 separate networks. Lets connect them so they'll be in the same network.


**Connecting Nodes**

Test: https://github.com/JoshuaKissoon/Kademlia/blob/master/src/kademlia/tests/NodeConnectionTest.java
```Java
kad2.bootstrap(kad1.getNode());   // Bootstrap kad2 by using kad1 as the main network node
```


**Storing Content**

Test: https://github.com/JoshuaKissoon/Kademlia/blob/master/src/kademlia/tests/ContentSendingTest.java
```Java
/* Working example at: https://github.com/JoshuaKissoon/Kademlia/blob/master/src/kademlia/tests/ContentSendingTest.java */
DHTContentImpl c = new DHTContentImpl(kad2.getOwnerId(), "Some Data");  // Create a content
kad2.put(c);    // Put the content on the network

```


**Retrieving Content**

Test: https://github.com/JoshuaKissoon/Kademlia/blob/master/src/kademlia/tests/ContentSendingTest.java
```Java
/* Create a GetParameter object with the parameters of the content to retrieve */
GetParameter gp = new GetParameter(c.getKey());   // Lets look for content by key
gp.setType(DHTContentImpl.TYPE);                  // We also only want content of this type
gp.setOwnerId(c.getOwnerId());                    // And content from this owner

/* Now we call get specifying the GetParameters and the Number of results we want */
List<KadContent> conte = kad2.get(gp, 1);
```


**Saving and Retrieving a Node State**

Test: https://github.com/JoshuaKissoon/Kademlia/blob/master/src/kademlia/tests/SaveStateTest.java

You may want to save the Node state when your application is shut down and Retrieve the Node state on startup to remove the need of rebuilding the Node State (Routing Table, DHT Content Entries, etc). Lets look at how we do this.

```Java
/** 
 * Shutting down the Kad instance.
 * Calling .shutdown() ill automatically store the node state in the location specified in the Configuration file 
 */
kad1.shutdown();

/**
 * Retrieving the Node state
 * This is done by simply building the Kademlia instance by calling .loadFromFile()
 * and passing in the instance Owner name as a parameter
 */
 Kademlia kad1Reloaded = Kademlia.loadFromFile("OwnerName1");
```

For more information on using Kademlia, check the tests at: https://github.com/JoshuaKissoon/Kademlia/tree/master/src/kademlia/tests


Usage in a Real Project
-----------------------
I am currently using this implementation of Kademlia in developing a Distributed Online Social Network Architecture, you can look at that project at https://github.com/JoshuaKissoon/DOSNA for more ideas on using Kademlia.


================================================
FILE: build.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="Kademlia" default="default" basedir=".">
    <description>Builds, tests, and runs the project Kademlia.</description>
    <import file="nbproject/build-impl.xml"/>
    <!--

    There exist several targets which are by default empty and which can be 
    used for execution of your tasks. These targets are usually executed 
    before and after some main targets. They are: 

      -pre-init:                 called before initialization of project properties
      -post-init:                called after initialization of project properties
      -pre-compile:              called before javac compilation
      -post-compile:             called after javac compilation
      -pre-compile-single:       called before javac compilation of single file
      -post-compile-single:      called after javac compilation of single file
      -pre-compile-test:         called before javac compilation of JUnit tests
      -post-compile-test:        called after javac compilation of JUnit tests
      -pre-compile-test-single:  called before javac compilation of single JUnit test
      -post-compile-test-single: called after javac compilation of single JUunit test
      -pre-jar:                  called before JAR building
      -post-jar:                 called after JAR building
      -post-clean:               called after cleaning build products

    (Targets beginning with '-' are not intended to be called on their own.)

    Example of inserting an obfuscator after compilation could look like this:

        <target name="-post-compile">
            <obfuscate>
                <fileset dir="${build.classes.dir}"/>
            </obfuscate>
        </target>

    For list of available properties check the imported 
    nbproject/build-impl.xml file. 


    Another way to customize the build is by overriding existing main targets.
    The targets of interest are: 

      -init-macrodef-javac:     defines macro for javac compilation
      -init-macrodef-junit:     defines macro for junit execution
      -init-macrodef-debug:     defines macro for class debugging
      -init-macrodef-java:      defines macro for class execution
      -do-jar:                  JAR building
      run:                      execution of project 
      -javadoc-build:           Javadoc generation
      test-report:              JUnit report generation

    An example of overriding the target for project execution could look like this:

        <target name="run" depends="Kademlia-impl.jar">
            <exec dir="bin" executable="launcher.exe">
                <arg file="${dist.jar}"/>
            </exec>
        </target>

    Notice that the overridden target depends on the jar target and not only on 
    the compile target as the regular run target does. Again, for a list of available 
    properties which you can use, check the target you are overriding in the
    nbproject/build-impl.xml file. 

    -->
</project>


================================================
FILE: manifest.mf
================================================
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build



================================================
FILE: nbproject/build-impl.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT  ***
***         EDIT ../build.xml INSTEAD         ***

For the purpose of easier reading the script
is divided into following sections:

  - initialization
  - compilation
  - jar
  - execution
  - debugging
  - javadoc
  - test compilation
  - test execution
  - test debugging
  - applet
  - cleanup

        -->
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="Kademlia-impl">
    <fail message="Please build using Ant 1.8.0 or higher.">
        <condition>
            <not>
                <antversion atleast="1.8.0"/>
            </not>
        </condition>
    </fail>
    <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
    <!-- 
                ======================
                INITIALIZATION SECTION 
                ======================
            -->
    <target name="-pre-init">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="-pre-init" name="-init-private">
        <property file="nbproject/private/config.properties"/>
        <property file="nbproject/private/configs/${config}.properties"/>
        <property file="nbproject/private/private.properties"/>
    </target>
    <target depends="-pre-init,-init-private" name="-init-user">
        <property file="${user.properties.file}"/>
        <!-- The two properties below are usually overridden -->
        <!-- by the active platform. Just a fallback. -->
        <property name="default.javac.source" value="1.4"/>
        <property name="default.javac.target" value="1.4"/>
    </target>
    <target depends="-pre-init,-init-private,-init-user" name="-init-project">
        <property file="nbproject/configs/${config}.properties"/>
        <property file="nbproject/project.properties"/>
    </target>
    <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
        <property name="platform.java" value="${java.home}/bin/java"/>
        <available file="${manifest.file}" property="manifest.available"/>
        <condition property="splashscreen.available">
            <and>
                <not>
                    <equals arg1="${application.splash}" arg2="" trim="true"/>
                </not>
                <available file="${application.splash}"/>
            </and>
        </condition>
        <condition property="main.class.available">
            <and>
                <isset property="main.class"/>
                <not>
                    <equals arg1="${main.class}" arg2="" trim="true"/>
                </not>
            </and>
        </condition>
        <condition property="profile.available">
            <and>
                <isset property="javac.profile"/>
                <length length="0" string="${javac.profile}" when="greater"/>
                <matches pattern="1\.[89](\..*)?" string="${javac.source}"/>
            </and>
        </condition>
        <condition property="do.archive">
            <or>
                <not>
                    <istrue value="${jar.archive.disabled}"/>
                </not>
                <istrue value="${not.archive.disabled}"/>
            </or>
        </condition>
        <condition property="do.mkdist">
            <and>
                <isset property="do.archive"/>
                <isset property="libs.CopyLibs.classpath"/>
                <not>
                    <istrue value="${mkdist.disabled}"/>
                </not>
            </and>
        </condition>
        <condition property="do.archive+manifest.available">
            <and>
                <isset property="manifest.available"/>
                <istrue value="${do.archive}"/>
            </and>
        </condition>
        <condition property="do.archive+main.class.available">
            <and>
                <isset property="main.class.available"/>
                <istrue value="${do.archive}"/>
            </and>
        </condition>
        <condition property="do.archive+splashscreen.available">
            <and>
                <isset property="splashscreen.available"/>
                <istrue value="${do.archive}"/>
            </and>
        </condition>
        <condition property="do.archive+profile.available">
            <and>
                <isset property="profile.available"/>
                <istrue value="${do.archive}"/>
            </and>
        </condition>
        <condition property="have.tests">
            <or>
                <available file="${test.src.dir}"/>
            </or>
        </condition>
        <condition property="have.sources">
            <or>
                <available file="${src.dir}"/>
            </or>
        </condition>
        <condition property="netbeans.home+have.tests">
            <and>
                <isset property="netbeans.home"/>
                <isset property="have.tests"/>
            </and>
        </condition>
        <condition property="no.javadoc.preview">
            <and>
                <isset property="javadoc.preview"/>
                <isfalse value="${javadoc.preview}"/>
            </and>
        </condition>
        <property name="run.jvmargs" value=""/>
        <property name="run.jvmargs.ide" value=""/>
        <property name="javac.compilerargs" value=""/>
        <property name="work.dir" value="${basedir}"/>
        <condition property="no.deps">
            <and>
                <istrue value="${no.dependencies}"/>
            </and>
        </condition>
        <property name="javac.debug" value="true"/>
        <property name="javadoc.preview" value="true"/>
        <property name="application.args" value=""/>
        <property name="source.encoding" value="${file.encoding}"/>
        <property name="runtime.encoding" value="${source.encoding}"/>
        <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
            <and>
                <isset property="javadoc.encoding"/>
                <not>
                    <equals arg1="${javadoc.encoding}" arg2=""/>
                </not>
            </and>
        </condition>
        <property name="javadoc.encoding.used" value="${source.encoding}"/>
        <property name="includes" value="**"/>
        <property name="excludes" value=""/>
        <property name="do.depend" value="false"/>
        <condition property="do.depend.true">
            <istrue value="${do.depend}"/>
        </condition>
        <path id="endorsed.classpath.path" path="${endorsed.classpath}"/>
        <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'">
            <and>
                <isset property="endorsed.classpath"/>
                <not>
                    <equals arg1="${endorsed.classpath}" arg2="" trim="true"/>
                </not>
            </and>
        </condition>
        <condition else="" property="javac.profile.cmd.line.arg" value="-profile ${javac.profile}">
            <isset property="profile.available"/>
        </condition>
        <condition else="false" property="jdkBug6558476">
            <and>
                <matches pattern="1\.[56]" string="${java.specification.version}"/>
                <not>
                    <os family="unix"/>
                </not>
            </and>
        </condition>
        <property name="javac.fork" value="${jdkBug6558476}"/>
        <property name="jar.index" value="false"/>
        <property name="jar.index.metainf" value="${jar.index}"/>
        <property name="copylibs.rebase" value="true"/>
        <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
        <condition property="junit.available">
            <or>
                <available classname="org.junit.Test" classpath="${run.test.classpath}"/>
                <available classname="junit.framework.Test" classpath="${run.test.classpath}"/>
            </or>
        </condition>
        <condition property="testng.available">
            <available classname="org.testng.annotations.Test" classpath="${run.test.classpath}"/>
        </condition>
        <condition property="junit+testng.available">
            <and>
                <istrue value="${junit.available}"/>
                <istrue value="${testng.available}"/>
            </and>
        </condition>
        <condition else="testng" property="testng.mode" value="mixed">
            <istrue value="${junit+testng.available}"/>
        </condition>
        <condition else="" property="testng.debug.mode" value="-mixed">
            <istrue value="${junit+testng.available}"/>
        </condition>
    </target>
    <target name="-post-init">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
        <fail unless="src.dir">Must set src.dir</fail>
        <fail unless="test.src.dir">Must set test.src.dir</fail>
        <fail unless="build.dir">Must set build.dir</fail>
        <fail unless="dist.dir">Must set dist.dir</fail>
        <fail unless="build.classes.dir">Must set build.classes.dir</fail>
        <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
        <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
        <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
        <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
        <fail unless="dist.jar">Must set dist.jar</fail>
    </target>
    <target name="-init-macrodef-property">
        <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
            <attribute name="name"/>
            <attribute name="value"/>
            <sequential>
                <property name="@{name}" value="${@{value}}"/>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${src.dir}" name="srcdir"/>
            <attribute default="${build.classes.dir}" name="destdir"/>
            <attribute default="${javac.classpath}" name="classpath"/>
            <attribute default="${javac.processorpath}" name="processorpath"/>
            <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="${javac.debug}" name="debug"/>
            <attribute default="${empty.dir}" name="sourcepath"/>
            <attribute default="${empty.dir}" name="gensrcdir"/>
            <element name="customize" optional="true"/>
            <sequential>
                <property location="${build.dir}/empty" name="empty.dir"/>
                <mkdir dir="${empty.dir}"/>
                <mkdir dir="@{apgeneratedsrcdir}"/>
                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
                    <src>
                        <dirset dir="@{gensrcdir}" erroronmissingdir="false">
                            <include name="*"/>
                        </dirset>
                    </src>
                    <classpath>
                        <path path="@{classpath}"/>
                    </classpath>
                    <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
                    <compilerarg line="${javac.profile.cmd.line.arg}"/>
                    <compilerarg line="${javac.compilerargs}"/>
                    <compilerarg value="-processorpath"/>
                    <compilerarg path="@{processorpath}:${empty.dir}"/>
                    <compilerarg line="${ap.processors.internal}"/>
                    <compilerarg line="${annotation.processing.processor.options}"/>
                    <compilerarg value="-s"/>
                    <compilerarg path="@{apgeneratedsrcdir}"/>
                    <compilerarg line="${ap.proc.none.internal}"/>
                    <customize/>
                </javac>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${src.dir}" name="srcdir"/>
            <attribute default="${build.classes.dir}" name="destdir"/>
            <attribute default="${javac.classpath}" name="classpath"/>
            <attribute default="${javac.processorpath}" name="processorpath"/>
            <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="${javac.debug}" name="debug"/>
            <attribute default="${empty.dir}" name="sourcepath"/>
            <attribute default="${empty.dir}" name="gensrcdir"/>
            <element name="customize" optional="true"/>
            <sequential>
                <property location="${build.dir}/empty" name="empty.dir"/>
                <mkdir dir="${empty.dir}"/>
                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
                    <src>
                        <dirset dir="@{gensrcdir}" erroronmissingdir="false">
                            <include name="*"/>
                        </dirset>
                    </src>
                    <classpath>
                        <path path="@{classpath}"/>
                    </classpath>
                    <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
                    <compilerarg line="${javac.profile.cmd.line.arg}"/>
                    <compilerarg line="${javac.compilerargs}"/>
                    <customize/>
                </javac>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
        <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${src.dir}" name="srcdir"/>
            <attribute default="${build.classes.dir}" name="destdir"/>
            <attribute default="${javac.classpath}" name="classpath"/>
            <sequential>
                <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
                    <classpath>
                        <path path="@{classpath}"/>
                    </classpath>
                </depend>
            </sequential>
        </macrodef>
        <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${build.classes.dir}" name="destdir"/>
            <sequential>
                <fail unless="javac.includes">Must set javac.includes</fail>
                <pathconvert pathsep="${line.separator}" property="javac.includes.binary">
                    <path>
                        <filelist dir="@{destdir}" files="${javac.includes}"/>
                    </path>
                    <globmapper from="*.java" to="*.class"/>
                </pathconvert>
                <tempfile deleteonexit="true" property="javac.includesfile.binary"/>
                <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/>
                <delete>
                    <files includesfile="${javac.includesfile.binary}"/>
                </delete>
                <delete>
                    <fileset file="${javac.includesfile.binary}"/>
                </delete>
            </sequential>
        </macrodef>
    </target>
    <target if="${junit.available}" name="-init-macrodef-junit-init">
        <condition else="false" property="nb.junit.batch" value="true">
            <and>
                <istrue value="${junit.available}"/>
                <not>
                    <isset property="test.method"/>
                </not>
            </and>
        </condition>
        <condition else="false" property="nb.junit.single" value="true">
            <and>
                <istrue value="${junit.available}"/>
                <isset property="test.method"/>
            </and>
        </condition>
    </target>
    <target name="-init-test-properties">
        <property name="test.binaryincludes" value="&lt;nothing&gt;"/>
        <property name="test.binarytestincludes" value=""/>
        <property name="test.binaryexcludes" value=""/>
    </target>
    <target if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}">
        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element name="customize" optional="true"/>
            <sequential>
                <property name="junit.forkmode" value="perTest"/>
                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
                    <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
                    <syspropertyset>
                        <propertyref prefix="test-sys-prop."/>
                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
                    </syspropertyset>
                    <formatter type="brief" usefile="false"/>
                    <formatter type="xml"/>
                    <jvmarg value="-ea"/>
                    <customize/>
                </junit>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element name="customize" optional="true"/>
            <sequential>
                <property name="junit.forkmode" value="perTest"/>
                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
                    <batchtest todir="${build.test.results.dir}">
                        <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                            <filename name="@{testincludes}"/>
                        </fileset>
                        <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
                            <filename name="${test.binarytestincludes}"/>
                        </fileset>
                    </batchtest>
                    <syspropertyset>
                        <propertyref prefix="test-sys-prop."/>
                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
                    </syspropertyset>
                    <formatter type="brief" usefile="false"/>
                    <formatter type="xml"/>
                    <jvmarg value="-ea"/>
                    <customize/>
                </junit>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/>
    <target if="${testng.available}" name="-init-macrodef-testng">
        <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element name="customize" optional="true"/>
            <sequential>
                <condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}">
                    <isset property="test.method"/>
                </condition>
                <union id="test.set">
                    <fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
                        <filename name="@{testincludes}"/>
                    </fileset>
                </union>
                <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
                <testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="Kademlia" testname="TestNG tests" workingDir="${work.dir}">
                    <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
                    <propertyset>
                        <propertyref prefix="test-sys-prop."/>
                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
                    </propertyset>
                    <customize/>
                </testng>
            </sequential>
        </macrodef>
    </target>
    <target name="-init-macrodef-test-impl">
        <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element implicit="true" name="customize" optional="true"/>
            <sequential>
                <echo>No tests executed.</echo>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-impl">
        <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element implicit="true" name="customize" optional="true"/>
            <sequential>
                <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
                    <customize/>
                </j2seproject3:junit>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-testng" if="${testng.available}" name="-init-macrodef-testng-impl">
        <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element implicit="true" name="customize" optional="true"/>
            <sequential>
                <j2seproject3:testng excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
                    <customize/>
                </j2seproject3:testng>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-test-impl,-init-macrodef-junit-impl,-init-macrodef-testng-impl" name="-init-macrodef-test">
        <macrodef name="test" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <sequential>
                <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
                    <customize>
                        <classpath>
                            <path path="${run.test.classpath}"/>
                        </classpath>
                        <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                        <jvmarg line="${run.jvmargs}"/>
                        <jvmarg line="${run.jvmargs.ide}"/>
                    </customize>
                </j2seproject3:test-impl>
            </sequential>
        </macrodef>
    </target>
    <target if="${junit.available}" name="-init-macrodef-junit-debug" unless="${nb.junit.batch}">
        <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element name="customize" optional="true"/>
            <sequential>
                <property name="junit.forkmode" value="perTest"/>
                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
                    <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
                    <syspropertyset>
                        <propertyref prefix="test-sys-prop."/>
                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
                    </syspropertyset>
                    <formatter type="brief" usefile="false"/>
                    <formatter type="xml"/>
                    <jvmarg value="-ea"/>
                    <jvmarg line="${debug-args-line}"/>
                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
                    <customize/>
                </junit>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-debug-batch">
        <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element name="customize" optional="true"/>
            <sequential>
                <property name="junit.forkmode" value="perTest"/>
                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
                    <batchtest todir="${build.test.results.dir}">
                        <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                            <filename name="@{testincludes}"/>
                        </fileset>
                        <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
                            <filename name="${test.binarytestincludes}"/>
                        </fileset>
                    </batchtest>
                    <syspropertyset>
                        <propertyref prefix="test-sys-prop."/>
                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
                    </syspropertyset>
                    <formatter type="brief" usefile="false"/>
                    <formatter type="xml"/>
                    <jvmarg value="-ea"/>
                    <jvmarg line="${debug-args-line}"/>
                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
                    <customize/>
                </junit>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-junit-debug,-init-macrodef-junit-debug-batch" if="${junit.available}" name="-init-macrodef-junit-debug-impl">
        <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <element implicit="true" name="customize" optional="true"/>
            <sequential>
                <j2seproject3:junit-debug excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
                    <customize/>
                </j2seproject3:junit-debug>
            </sequential>
        </macrodef>
    </target>
    <target if="${testng.available}" name="-init-macrodef-testng-debug">
        <macrodef name="testng-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${main.class}" name="testClass"/>
            <attribute default="" name="testMethod"/>
            <element name="customize2" optional="true"/>
            <sequential>
                <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}">
                    <isset property="test.method"/>
                </condition>
                <condition else="-suitename Kademlia -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}">
                    <matches pattern=".*\.xml" string="@{testClass}"/>
                </condition>
                <delete dir="${build.test.results.dir}" quiet="true"/>
                <mkdir dir="${build.test.results.dir}"/>
                <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}">
                    <customize>
                        <customize2/>
                        <jvmarg value="-ea"/>
                        <arg line="${testng.debug.mode}"/>
                        <arg line="-d ${build.test.results.dir}"/>
                        <arg line="-listener org.testng.reporters.VerboseReporter"/>
                        <arg line="${testng.cmd.args}"/>
                    </customize>
                </j2seproject3:debug>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-testng-debug" if="${testng.available}" name="-init-macrodef-testng-debug-impl">
        <macrodef name="testng-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${main.class}" name="testClass"/>
            <attribute default="" name="testMethod"/>
            <element implicit="true" name="customize2" optional="true"/>
            <sequential>
                <j2seproject3:testng-debug testClass="@{testClass}" testMethod="@{testMethod}">
                    <customize2/>
                </j2seproject3:testng-debug>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-junit-debug-impl" if="${junit.available}" name="-init-macrodef-test-debug-junit">
        <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <attribute default="${main.class}" name="testClass"/>
            <attribute default="" name="testMethod"/>
            <sequential>
                <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
                    <customize>
                        <classpath>
                            <path path="${run.test.classpath}"/>
                        </classpath>
                        <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                        <jvmarg line="${run.jvmargs}"/>
                        <jvmarg line="${run.jvmargs.ide}"/>
                    </customize>
                </j2seproject3:test-debug-impl>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-testng-debug-impl" if="${testng.available}" name="-init-macrodef-test-debug-testng">
        <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <attribute default="" name="testmethods"/>
            <attribute default="${main.class}" name="testClass"/>
            <attribute default="" name="testMethod"/>
            <sequential>
                <j2seproject3:testng-debug-impl testClass="@{testClass}" testMethod="@{testMethod}">
                    <customize2>
                        <syspropertyset>
                            <propertyref prefix="test-sys-prop."/>
                            <mapper from="test-sys-prop.*" to="*" type="glob"/>
                        </syspropertyset>
                    </customize2>
                </j2seproject3:testng-debug-impl>
            </sequential>
        </macrodef>
    </target>
    <target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/>
    <!--
                pre NB7.2 profiling section; consider it deprecated
            -->
    <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/>
    <target if="profiler.info.jvmargs.agent" name="-profile-pre-init">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target if="profiler.info.jvmargs.agent" name="-profile-post-init">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target if="profiler.info.jvmargs.agent" name="-profile-init-macrodef-profile">
        <macrodef name="resolve">
            <attribute name="name"/>
            <attribute name="value"/>
            <sequential>
                <property name="@{name}" value="${env.@{value}}"/>
            </sequential>
        </macrodef>
        <macrodef name="profile">
            <attribute default="${main.class}" name="classname"/>
            <element name="customize" optional="true"/>
            <sequential>
                <property environment="env"/>
                <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
                <java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">
                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                    <jvmarg value="${profiler.info.jvmargs.agent}"/>
                    <jvmarg line="${profiler.info.jvmargs}"/>
                    <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
                    <arg line="${application.args}"/>
                    <classpath>
                        <path path="${run.classpath}"/>
                    </classpath>
                    <syspropertyset>
                        <propertyref prefix="run-sys-prop."/>
                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
                    </syspropertyset>
                    <customize/>
                </java>
            </sequential>
        </macrodef>
    </target>
    <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" if="profiler.info.jvmargs.agent" name="-profile-init-check">
        <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail>
        <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>
    </target>
    <!--
                end of pre NB7.2 profiling section
            -->
    <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
        <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
            <attribute default="${main.class}" name="name"/>
            <attribute default="${debug.classpath}" name="classpath"/>
            <attribute default="" name="stopclassname"/>
            <sequential>
                <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
                    <classpath>
                        <path path="@{classpath}"/>
                    </classpath>
                </nbjpdastart>
            </sequential>
        </macrodef>
        <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
            <attribute default="${build.classes.dir}" name="dir"/>
            <sequential>
                <nbjpdareload>
                    <fileset dir="@{dir}" includes="${fix.classes}">
                        <include name="${fix.includes}*.class"/>
                    </fileset>
                </nbjpdareload>
            </sequential>
        </macrodef>
    </target>
    <target name="-init-debug-args">
        <property name="version-output" value="java version &quot;${ant.java.version}"/>
        <condition property="have-jdk-older-than-1.4">
            <or>
                <contains string="${version-output}" substring="java version &quot;1.0"/>
                <contains string="${version-output}" substring="java version &quot;1.1"/>
                <contains string="${version-output}" substring="java version &quot;1.2"/>
                <contains string="${version-output}" substring="java version &quot;1.3"/>
            </or>
        </condition>
        <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
            <istrue value="${have-jdk-older-than-1.4}"/>
        </condition>
        <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
            <os family="windows"/>
        </condition>
        <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
            <isset property="debug.transport"/>
        </condition>
    </target>
    <target depends="-init-debug-args" name="-init-macrodef-debug">
        <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${main.class}" name="classname"/>
            <attribute default="${debug.classpath}" name="classpath"/>
            <element name="customize" optional="true"/>
            <sequential>
                <java classname="@{classname}" dir="${work.dir}" fork="true">
                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                    <jvmarg line="${debug-args-line}"/>
                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
                    <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
                    <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
                    <jvmarg line="${run.jvmargs}"/>
                    <jvmarg line="${run.jvmargs.ide}"/>
                    <classpath>
                        <path path="@{classpath}"/>
                    </classpath>
                    <syspropertyset>
                        <propertyref prefix="run-sys-prop."/>
                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
                    </syspropertyset>
                    <customize/>
                </java>
            </sequential>
        </macrodef>
    </target>
    <target name="-init-macrodef-java">
        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
            <attribute default="${main.class}" name="classname"/>
            <attribute default="${run.classpath}" name="classpath"/>
            <attribute default="jvm" name="jvm"/>
            <element name="customize" optional="true"/>
            <sequential>
                <java classname="@{classname}" dir="${work.dir}" fork="true">
                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                    <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
                    <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
                    <jvmarg line="${run.jvmargs}"/>
                    <jvmarg line="${run.jvmargs.ide}"/>
                    <classpath>
                        <path path="@{classpath}"/>
                    </classpath>
                    <syspropertyset>
                        <propertyref prefix="run-sys-prop."/>
                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
                    </syspropertyset>
                    <customize/>
                </java>
            </sequential>
        </macrodef>
    </target>
    <target name="-init-macrodef-copylibs">
        <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${manifest.file}" name="manifest"/>
            <element name="customize" optional="true"/>
            <sequential>
                <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
                <pathconvert property="run.classpath.without.build.classes.dir">
                    <path path="${run.classpath}"/>
                    <map from="${build.classes.dir.resolved}" to=""/>
                </pathconvert>
                <pathconvert pathsep=" " property="jar.classpath">
                    <path path="${run.classpath.without.build.classes.dir}"/>
                    <chainedmapper>
                        <flattenmapper/>
                        <filtermapper>
                            <replacestring from=" " to="%20"/>
                        </filtermapper>
                        <globmapper from="*" to="lib/*"/>
                    </chainedmapper>
                </pathconvert>
                <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
                <copylibs compress="${jar.compress}" excludeFromCopy="${copylibs.excludes}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
                    <fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/>
                    <manifest>
                        <attribute name="Class-Path" value="${jar.classpath}"/>
                        <customize/>
                    </manifest>
                </copylibs>
            </sequential>
        </macrodef>
    </target>
    <target name="-init-presetdef-jar">
        <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
            <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">
                <j2seproject1:fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/>
            </jar>
        </presetdef>
    </target>
    <target name="-init-ap-cmdline-properties">
        <property name="annotation.processing.enabled" value="true"/>
        <property name="annotation.processing.processors.list" value=""/>
        <property name="annotation.processing.processor.options" value=""/>
        <property name="annotation.processing.run.all.processors" value="true"/>
        <property name="javac.processorpath" value="${javac.classpath}"/>
        <property name="javac.test.processorpath" value="${javac.test.classpath}"/>
        <condition property="ap.supported.internal" value="true">
            <not>
                <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/>
            </not>
        </condition>
    </target>
    <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported">
        <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}">
            <isfalse value="${annotation.processing.run.all.processors}"/>
        </condition>
        <condition else="" property="ap.proc.none.internal" value="-proc:none">
            <isfalse value="${annotation.processing.enabled}"/>
        </condition>
    </target>
    <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline">
        <property name="ap.cmd.line.internal" value=""/>
    </target>
    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>
    <!--
                ===================
                COMPILATION SECTION
                ===================
            -->
    <target name="-deps-jar-init" unless="built-jar.properties">
        <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>
        <delete file="${built-jar.properties}" quiet="true"/>
    </target>
    <target if="already.built.jar.${basedir}" name="-warn-already-built-jar">
        <echo level="warn" message="Cycle detected: Kademlia was already built"/>
    </target>
    <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">
        <mkdir dir="${build.dir}"/>
        <touch file="${built-jar.properties}" verbose="false"/>
        <property file="${built-jar.properties}" prefix="already.built.jar."/>
        <antcall target="-warn-already-built-jar"/>
        <propertyfile file="${built-jar.properties}">
            <entry key="${basedir}" value=""/>
        </propertyfile>
    </target>
    <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
    <target depends="init" name="-check-automatic-build">
        <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
    </target>
    <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
        <antcall target="clean"/>
    </target>
    <target depends="init,deps-jar" name="-pre-pre-compile">
        <mkdir dir="${build.classes.dir}"/>
    </target>
    <target name="-pre-compile">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target if="do.depend.true" name="-compile-depend">
        <pathconvert property="build.generated.subdirs">
            <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">
                <include name="*"/>
            </dirset>
        </pathconvert>
        <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>
    </target>
    <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
        <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
        <copy todir="${build.classes.dir}">
            <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
        </copy>
    </target>
    <target if="has.persistence.xml" name="-copy-persistence-xml">
        <mkdir dir="${build.classes.dir}/META-INF"/>
        <copy todir="${build.classes.dir}/META-INF">
            <fileset dir="${meta.inf.dir}" includes="persistence.xml orm.xml"/>
        </copy>
    </target>
    <target name="-post-compile">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
    <target name="-pre-compile-single">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
        <j2seproject3:force-recompile/>
        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/>
    </target>
    <target name="-post-compile-single">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
    <!--
                ====================
                JAR BUILDING SECTION
                ====================
            -->
    <target depends="init" name="-pre-pre-jar">
        <dirname file="${dist.jar}" property="dist.jar.dir"/>
        <mkdir dir="${dist.jar.dir}"/>
    </target>
    <target name="-pre-jar">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init" if="do.archive" name="-do-jar-create-manifest" unless="manifest.available">
        <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
        <touch file="${tmp.manifest.file}" verbose="false"/>
    </target>
    <target depends="init" if="do.archive+manifest.available" name="-do-jar-copy-manifest">
        <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
        <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/>
    </target>
    <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+main.class.available" name="-do-jar-set-mainclass">
        <manifest file="${tmp.manifest.file}" mode="update">
            <attribute name="Main-Class" value="${main.class}"/>
        </manifest>
    </target>
    <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+profile.available" name="-do-jar-set-profile">
        <manifest file="${tmp.manifest.file}" mode="update">
            <attribute name="Profile" value="${javac.profile}"/>
        </manifest>
    </target>
    <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-set-splashscreen">
        <basename file="${application.splash}" property="splashscreen.basename"/>
        <mkdir dir="${build.classes.dir}/META-INF"/>
        <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>
        <manifest file="${tmp.manifest.file}" mode="update">
            <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
        </manifest>
    </target>
    <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.mkdist" name="-do-jar-copylibs">
        <j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
        <echo level="info">To run this application from the command line without Ant, try:</echo>
        <property location="${dist.jar}" name="dist.jar.resolved"/>
        <echo level="info">java -jar "${dist.jar.resolved}"</echo>
    </target>
    <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.archive" name="-do-jar-jar" unless="do.mkdist">
        <j2seproject1:jar manifest="${tmp.manifest.file}"/>
        <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
        <property location="${dist.jar}" name="dist.jar.resolved"/>
        <pathconvert property="run.classpath.with.dist.jar">
            <path path="${run.classpath}"/>
            <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
        </pathconvert>
        <condition else="" property="jar.usage.message" value="To run this application from the command line without Ant, try:${line.separator}${platform.java} -cp ${run.classpath.with.dist.jar} ${main.class}">
            <isset property="main.class.available"/>
        </condition>
        <condition else="debug" property="jar.usage.level" value="info">
            <isset property="main.class.available"/>
        </condition>
        <echo level="${jar.usage.level}" message="${jar.usage.message}"/>
    </target>
    <target depends="-do-jar-copylibs" if="do.archive" name="-do-jar-delete-manifest">
        <delete>
            <fileset file="${tmp.manifest.file}"/>
        </delete>
    </target>
    <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-jar,-do-jar-delete-manifest" name="-do-jar-without-libraries"/>
    <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-copylibs,-do-jar-delete-manifest" name="-do-jar-with-libraries"/>
    <target name="-post-jar">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init,compile,-pre-jar,-do-jar-without-libraries,-do-jar-with-libraries,-post-jar" name="-do-jar"/>
    <target depends="init,compile,-pre-jar,-do-jar,-post-jar" description="Build JAR." name="jar"/>
    <!--
                =================
                EXECUTION SECTION
                =================
            -->
    <target depends="init,compile" description="Run a main class." name="run">
        <j2seproject1:java>
            <customize>
                <arg line="${application.args}"/>
            </customize>
        </j2seproject1:java>
    </target>
    <target name="-do-not-recompile">
        <property name="javac.includes.binary" value=""/>
    </target>
    <target depends="init,compile-single" name="run-single">
        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
        <j2seproject1:java classname="${run.class}"/>
    </target>
    <target depends="init,compile-test-single" name="run-test-with-main">
        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
        <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
    </target>
    <!--
                =================
                DEBUGGING SECTION
                =================
            -->
    <target depends="init" if="netbeans.home" name="-debug-start-debugger">
        <j2seproject1:nbjpdastart name="${debug.class}"/>
    </target>
    <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">
        <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>
    </target>
    <target depends="init,compile" name="-debug-start-debuggee">
        <j2seproject3:debug>
            <customize>
                <arg line="${application.args}"/>
            </customize>
        </j2seproject3:debug>
    </target>
    <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
    <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
        <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
    </target>
    <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
        <j2seproject3:debug classname="${debug.class}"/>
    </target>
    <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
    <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">
        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
        <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>
    </target>
    <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>
    <target depends="init" name="-pre-debug-fix">
        <fail unless="fix.includes">Must set fix.includes</fail>
        <property name="javac.includes" value="${fix.includes}.java"/>
    </target>
    <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
        <j2seproject1:nbjpdareload/>
    </target>
    <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
    <!--
                =================
                PROFILING SECTION
                =================
            -->
    <!--
                pre NB7.2 profiler integration
            -->
    <target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72">
        <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
        <nbprofiledirect>
            <classpath>
                <path path="${run.classpath}"/>
            </classpath>
        </nbprofiledirect>
        <profile/>
    </target>
    <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="profiler.info.jvmargs.agent" name="-profile-single-pre72">
        <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail>
        <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
        <nbprofiledirect>
            <classpath>
                <path path="${run.classpath}"/>
            </classpath>
        </nbprofiledirect>
        <profile classname="${profile.class}"/>
    </target>
    <target depends="profile-init,compile-single" if="profiler.info.jvmargs.agent" name="-profile-applet-pre72">
        <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
        <nbprofiledirect>
            <classpath>
                <path path="${run.classpath}"/>
            </classpath>
        </nbprofiledirect>
        <profile classname="sun.applet.AppletViewer">
            <customize>
                <arg value="${applet.url}"/>
            </customize>
        </profile>
    </target>
    <target depends="profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72">
        <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
        <nbprofiledirect>
            <classpath>
                <path path="${run.test.classpath}"/>
            </classpath>
        </nbprofiledirect>
        <junit dir="${profiler.info.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${profiler.info.jvm}" showoutput="true">
            <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
            <jvmarg value="${profiler.info.jvmargs.agent}"/>
            <jvmarg line="${profiler.info.jvmargs}"/>
            <test name="${profile.class}"/>
            <classpath>
                <path path="${run.test.classpath}"/>
            </classpath>
            <syspropertyset>
                <propertyref prefix="test-sys-prop."/>
                <mapper from="test-sys-prop.*" to="*" type="glob"/>
            </syspropertyset>
            <formatter type="brief" usefile="false"/>
            <formatter type="xml"/>
        </junit>
    </target>
    <!--
                end of pre NB72 profiling section
            -->
    <target if="netbeans.home" name="-profile-check">
        <condition property="profiler.configured">
            <or>
                <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/>
                <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/>
            </or>
        </condition>
    </target>
    <target depends="-profile-check,-profile-pre72" description="Profile a project in the IDE." if="profiler.configured" name="profile" unless="profiler.info.jvmargs.agent">
        <startprofiler/>
        <antcall target="run"/>
    </target>
    <target depends="-profile-check,-profile-single-pre72" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-single" unless="profiler.info.jvmargs.agent">
        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
        <startprofiler/>
        <antcall target="run-single"/>
    </target>
    <target depends="-profile-test-single-pre72" description="Profile a selected test in the IDE." name="profile-test-single"/>
    <target depends="-profile-check" description="Profile a selected test in the IDE." if="profiler.configured" name="profile-test" unless="profiler.info.jvmargs">
        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
        <startprofiler/>
        <antcall target="test-single"/>
    </target>
    <target depends="-profile-check" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-test-with-main">
        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
        <startprofiler/>
        <antcal target="run-test-with-main"/>
    </target>
    <target depends="-profile-check,-profile-applet-pre72" if="profiler.configured" name="profile-applet" unless="profiler.info.jvmargs.agent">
        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
        <startprofiler/>
        <antcall target="run-applet"/>
    </target>
    <!--
                ===============
                JAVADOC SECTION
                ===============
            -->
    <target depends="init" if="have.sources" name="-javadoc-build">
        <mkdir dir="${dist.javadoc.dir}"/>
        <condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}">
            <and>
                <isset property="endorsed.classpath.cmd.line.arg"/>
                <not>
                    <equals arg1="${endorsed.classpath.cmd.line.arg}" arg2=""/>
                </not>
            </and>
        </condition>
        <condition else="" property="bug5101868workaround" value="*.java">
            <matches pattern="1\.[56](\..*)?" string="${java.version}"/>
        </condition>
        <javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
            <classpath>
                <path path="${javac.classpath}"/>
            </classpath>
            <fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
                <filename name="**/*.java"/>
            </fileset>
            <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
                <include name="**/*.java"/>
                <exclude name="*.java"/>
            </fileset>
            <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/>
        </javadoc>
        <copy todir="${dist.javadoc.dir}">
            <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
                <filename name="**/doc-files/**"/>
            </fileset>
            <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
                <include name="**/doc-files/**"/>
            </fileset>
        </copy>
    </target>
    <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
        <nbbrowse file="${dist.javadoc.dir}/index.html"/>
    </target>
    <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
    <!--
                =========================
                TEST COMPILATION SECTION
                =========================
            -->
    <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
        <mkdir dir="${build.test.classes.dir}"/>
    </target>
    <target name="-pre-compile-test">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target if="do.depend.true" name="-compile-test-depend">
        <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
    </target>
    <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.src.dir}"/>
        <copy todir="${build.test.classes.dir}">
            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
        </copy>
    </target>
    <target name="-post-compile-test">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
    <target name="-pre-compile-test-single">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
        <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
        <copy todir="${build.test.classes.dir}">
            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
        </copy>
    </target>
    <target name="-post-compile-test-single">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
    <!--
                =======================
                TEST EXECUTION SECTION
                =======================
            -->
    <target depends="init" if="have.tests" name="-pre-test-run">
        <mkdir dir="${build.test.results.dir}"/>
    </target>
    <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
        <j2seproject3:test includes="${includes}" testincludes="**/*Test.java"/>
    </target>
    <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
        <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
    </target>
    <target depends="init" if="have.tests" name="test-report"/>
    <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
    <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
    <target depends="init" if="have.tests" name="-pre-test-run-single">
        <mkdir dir="${build.test.results.dir}"/>
    </target>
    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
        <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/>
    </target>
    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
        <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
    </target>
    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method">
        <fail unless="test.class">Must select some files in the IDE or set test.class</fail>
        <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
        <j2seproject3:test excludes="" includes="${javac.includes}" testincludes="${test.class}" testmethods="${test.method}"/>
    </target>
    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method">
        <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
    </target>
    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
    <!--
                =======================
                TEST DEBUGGING SECTION
                =======================
            -->
    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test">
        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
        <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/>
    </target>
    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test-method">
        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
        <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
        <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testMethod="${test.method}" testincludes="${test.class}" testmethods="${test.method}"/>
    </target>
    <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
        <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
    </target>
    <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
    <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
    <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
        <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
    </target>
    <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
    <!--
                =========================
                APPLET EXECUTION SECTION
                =========================
            -->
    <target depends="init,compile-single" name="run-applet">
        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
        <j2seproject1:java classname="sun.applet.AppletViewer">
            <customize>
                <arg value="${applet.url}"/>
            </customize>
        </j2seproject1:java>
    </target>
    <!--
                =========================
                APPLET DEBUGGING  SECTION
                =========================
            -->
    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
        <j2seproject3:debug classname="sun.applet.AppletViewer">
            <customize>
                <arg value="${applet.url}"/>
            </customize>
        </j2seproject3:debug>
    </target>
    <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
    <!--
                ===============
                CLEANUP SECTION
                ===============
            -->
    <target name="-deps-clean-init" unless="built-clean.properties">
        <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>
        <delete file="${built-clean.properties}" quiet="true"/>
    </target>
    <target if="already.built.clean.${basedir}" name="-warn-already-built-clean">
        <echo level="warn" message="Cycle detected: Kademlia was already built"/>
    </target>
    <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">
        <mkdir dir="${build.dir}"/>
        <touch file="${built-clean.properties}" verbose="false"/>
        <property file="${built-clean.properties}" prefix="already.built.clean."/>
        <antcall target="-warn-already-built-clean"/>
        <propertyfile file="${built-clean.properties}">
            <entry key="${basedir}" value=""/>
        </propertyfile>
    </target>
    <target depends="init" name="-do-clean">
        <delete dir="${build.dir}"/>
        <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
    </target>
    <target name="-post-clean">
        <!-- Empty placeholder for easier customization. -->
        <!-- You can override this target in the ../build.xml file. -->
    </target>
    <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
    <target name="-check-call-dep">
        <property file="${call.built.properties}" prefix="already.built."/>
        <condition property="should.call.dep">
            <and>
                <not>
                    <isset property="already.built.${call.subproject}"/>
                </not>
                <available file="${call.script}"/>
            </and>
        </condition>
    </target>
    <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep">
        <ant antfile="${call.script}" inheritall="false" target="${call.target}">
            <propertyset>
                <propertyref prefix="transfer."/>
                <mapper from="transfer.*" to="*" type="glob"/>
            </propertyset>
        </ant>
    </target>
</project>


================================================
FILE: nbproject/genfiles.properties
================================================
build.xml.data.CRC32=7e563d6e
build.xml.script.CRC32=c3cd04bd
build.xml.stylesheet.CRC32=8064a381@1.68.1.46
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=7e563d6e
nbproject/build-impl.xml.script.CRC32=934ae712
nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48


================================================
FILE: nbproject/project.properties
================================================
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=Kademlia
application.vendor=Joshua
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
    ${run.classpath}
debug.test.classpath=\
    ${run.test.classpath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/Kademlia.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
file.reference.gson-2.2.4.jar=C:\\Users\\Joshua\\Documents\\NetBeansProjects\\Libraries\\gson-2.2.4.jar
includes=**
jar.compress=false
javac.classpath=\
    ${file.reference.gson-2.2.4.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.processorpath=\
    ${javac.classpath}
javac.source=1.8
javac.target=1.8
javac.test.classpath=\
    ${javac.classpath}:\
    ${build.classes.dir}
javac.test.processorpath=\
    ${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=kademlia.KademliaBasic
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
run.classpath=\
    ${javac.classpath}:\
    ${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.test.classpath=\
    ${javac.test.classpath}:\
    ${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test


================================================
FILE: nbproject/project.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
    <type>org.netbeans.modules.java.j2seproject</type>
    <configuration>
        <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
            <name>Kademlia</name>
            <source-roots>
                <root id="src.dir"/>
            </source-roots>
            <test-roots>
                <root id="test.src.dir"/>
            </test-roots>
        </data>
    </configuration>
</project>


================================================
FILE: src/kademlia/DefaultConfiguration.java
================================================
package kademlia;

import java.io.File;

/**
 * A set of Kademlia configuration parameters. Default values are
 * supplied and can be changed by the application as necessary.
 *
 */
public class DefaultConfiguration implements KadConfiguration
{

    private final static long RESTORE_INTERVAL = 60 * 1000; // in milliseconds
    private final static long RESPONSE_TIMEOUT = 2000;
    private final static long OPERATION_TIMEOUT = 2000;
    private final static int CONCURRENCY = 10;
    private final static int K = 5;
    private final static int RCSIZE = 3;
    private final static int STALE = 1;
    private final static String LOCAL_FOLDER = "kademlia";
    
    private final static boolean IS_TESTING = true;

    /**
     * Default constructor to support Gson Serialization
     */
    public DefaultConfiguration()
    {

    }

    @Override
    public long restoreInterval()
    {
        return RESTORE_INTERVAL;
    }

    @Override
    public long responseTimeout()
    {
        return RESPONSE_TIMEOUT;
    }

    @Override
    public long operationTimeout()
    {
        return OPERATION_TIMEOUT;
    }

    @Override
    public int maxConcurrentMessagesTransiting()
    {
        return CONCURRENCY;
    }

    @Override
    public int k()
    {
        return K;
    }

    @Override
    public int replacementCacheSize()
    {
        return RCSIZE;
    }

    @Override
    public int stale()
    {
        return STALE;
    }

    @Override
    public String getNodeDataFolder(String ownerId)
    {
        /* Setup the main storage folder if it doesn't exist */
        String path = System.getProperty("user.home") + File.separator + DefaultConfiguration.LOCAL_FOLDER;
        File folder = new File(path);
        if (!folder.isDirectory())
        {
            folder.mkdir();
        }

        /* Setup subfolder for this owner if it doesn't exist */
        File ownerFolder = new File(folder + File.separator + ownerId);
        if (!ownerFolder.isDirectory())
        {
            ownerFolder.mkdir();
        }

        /* Return the path */
        return ownerFolder.toString();
    }

    @Override
    public boolean isTesting()
    {
        return IS_TESTING;
    }
}


================================================
FILE: src/kademlia/JKademliaNode.java
================================================
package kademlia;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.NoSuchElementException;
import java.util.Timer;
import java.util.TimerTask;
import kademlia.dht.GetParameter;
import kademlia.dht.DHT;
import kademlia.dht.KadContent;
import kademlia.dht.KademliaDHT;
import kademlia.dht.KademliaStorageEntry;
import kademlia.dht.JKademliaStorageEntry;
import kademlia.exceptions.ContentNotFoundException;
import kademlia.exceptions.RoutingException;
import kademlia.message.MessageFactory;
import kademlia.node.Node;
import kademlia.node.KademliaId;
import kademlia.operation.ConnectOperation;
import kademlia.operation.ContentLookupOperation;
import kademlia.operation.Operation;
import kademlia.operation.KadRefreshOperation;
import kademlia.operation.StoreOperation;
import kademlia.routing.JKademliaRoutingTable;
import kademlia.routing.KademliaRoutingTable;
import kademlia.util.serializer.JsonDHTSerializer;
import kademlia.util.serializer.JsonRoutingTableSerializer;
import kademlia.util.serializer.JsonSerializer;

/**
 * The main Kademlia Node on the network, this node manages everything for this local system.
 *
 * @author Joshua Kissoon
 * @since 20140215
 *
 * @todo When we receive a store message - if we have a newer version of the content, re-send this newer version to that node so as to update their version
 * @todo Handle IPv6 Addresses
 *
 */
public class JKademliaNode implements KademliaNode
{

    /* Kademlia Attributes */
    private final String ownerId;

    /* Objects to be used */
    private final transient Node localNode;
    private final transient KadServer server;
    private final transient KademliaDHT dht;
    private transient KademliaRoutingTable routingTable;
    private final int udpPort;
    private transient KadConfiguration config;

    /* Timer used to execute refresh operations */
    private transient Timer refreshOperationTimer;
    private transient TimerTask refreshOperationTTask;

    /* Factories */
    private final transient MessageFactory messageFactory;

    /* Statistics */
    private final transient KadStatistician statistician;

    
    {
        statistician = new Statistician();
    }

    /**
     * Creates a Kademlia DistributedMap using the specified name as filename base.
     * If the id cannot be read from disk the specified defaultId is used.
     * The instance is bootstraped to an existing network by specifying the
     * address of a bootstrap node in the network.
     *
     * @param ownerId      The Name of this node used for storage
     * @param localNode    The Local Node for this Kad instance
     * @param udpPort      The UDP port to use for routing messages
     * @param dht          The DHT for this instance
     * @param config
     * @param routingTable
     *
     * @throws IOException If an error occurred while reading id or local map
     *                     from disk <i>or</i> a network error occurred while
     *                     attempting to bootstrap to the network
     * */
    public JKademliaNode(String ownerId, Node localNode, int udpPort, KademliaDHT dht, KademliaRoutingTable routingTable, KadConfiguration config) throws IOException
    {
        this.ownerId = ownerId;
        this.udpPort = udpPort;
        this.localNode = localNode;
        this.dht = dht;
        this.config = config;
        this.routingTable = routingTable;
        this.messageFactory = new MessageFactory(this, this.dht, this.config);
        this.server = new KadServer(udpPort, this.messageFactory, this.localNode, this.config, this.statistician);
        this.startRefreshOperation();
    }

    @Override
    public final void startRefreshOperation()
    {
        this.refreshOperationTimer = new Timer(true);
        refreshOperationTTask = new TimerTask()
        {
            @Override
            public void run()
            {
                try
                {
                    /* Runs a DHT RefreshOperation  */
                    JKademliaNode.this.refresh();
                }
                catch (IOException e)
                {
                    System.err.println("KademliaNode: Refresh Operation Failed; Message: " + e.getMessage());
                }
            }
        };
        refreshOperationTimer.schedule(refreshOperationTTask, this.config.restoreInterval(), this.config.restoreInterval());
    }

    @Override
    public final void stopRefreshOperation()
    {
        /* Close off the timer tasks */
        this.refreshOperationTTask.cancel();
        this.refreshOperationTimer.cancel();
        this.refreshOperationTimer.purge();
    }

    public JKademliaNode(String ownerId, Node node, int udpPort, KademliaRoutingTable routingTable, KadConfiguration config) throws IOException
    {
        this(
                ownerId,
                node,
                udpPort,
                new DHT(ownerId, config),
                routingTable,
                config
        );
    }

    public JKademliaNode(String ownerId, Node node, int udpPort, KadConfiguration config) throws IOException
    {
        this(
                ownerId,
                node,
                udpPort,
                new JKademliaRoutingTable(node, config),
                config
        );
    }

    public JKademliaNode(String ownerId, KademliaId defaultId, int udpPort) throws IOException
    {
        this(
                ownerId,
                new Node(defaultId, InetAddress.getLocalHost(), udpPort),
                udpPort,
                new DefaultConfiguration()
        );
    }

    /**
     * Load Stored state using default configuration
     *
     * @param ownerId The ID of the owner for the stored state
     *
     * @return A Kademlia instance loaded from a stored state in a file
     *
     * @throws java.io.FileNotFoundException
     * @throws java.lang.ClassNotFoundException
     */
    public static JKademliaNode loadFromFile(String ownerId) throws FileNotFoundException, IOException, ClassNotFoundException
    {
        return JKademliaNode.loadFromFile(ownerId, new DefaultConfiguration());
    }

    /**
     * Load Stored state
     *
     * @param ownerId The ID of the owner for the stored state
     * @param iconfig Configuration information to work with
     *
     * @return A Kademlia instance loaded from a stored state in a file
     *
     * @throws java.io.FileNotFoundException
     * @throws java.lang.ClassNotFoundException
     */
    public static JKademliaNode loadFromFile(String ownerId, KadConfiguration iconfig) throws FileNotFoundException, IOException, ClassNotFoundException
    {
        DataInputStream din;

        /**
         * @section Read Basic Kad data
         */
        din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "kad.kns"));
        JKademliaNode ikad = new JsonSerializer<JKademliaNode>().read(din);

        /**
         * @section Read the routing table
         */
        din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "routingtable.kns"));
        KademliaRoutingTable irtbl = new JsonRoutingTableSerializer(iconfig).read(din);

        /**
         * @section Read the node state
         */
        din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "node.kns"));
        Node inode = new JsonSerializer<Node>().read(din);

        /**
         * @section Read the DHT
         */
        din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "dht.kns"));
        KademliaDHT idht = new JsonDHTSerializer().read(din);
        idht.setConfiguration(iconfig);

        return new JKademliaNode(ownerId, inode, ikad.getPort(), idht, irtbl, iconfig);
    }

    @Override
    public Node getNode()
    {
        return this.localNode;
    }

    @Override
    public KadServer getServer()
    {
        return this.server;
    }

    @Override
    public KademliaDHT getDHT()
    {
        return this.dht;
    }

    @Override
    public KadConfiguration getCurrentConfiguration()
    {
        return this.config;
    }

    @Override
    public synchronized final void bootstrap(Node n) throws IOException, RoutingException
    {
        long startTime = System.nanoTime();
        Operation op = new ConnectOperation(this.server, this, n, this.config);
        op.execute();
        long endTime = System.nanoTime();
        this.statistician.setBootstrapTime(endTime - startTime);
    }

    @Override
    public int put(KadContent content) throws IOException
    {
        return this.put(new JKademliaStorageEntry(content));
    }

    @Override
    public int put(JKademliaStorageEntry entry) throws IOException
    {
        StoreOperation sop = new StoreOperation(this.server, this, entry, this.dht, this.config);
        sop.execute();

        /* Return how many nodes the content was stored on */
        return sop.numNodesStoredAt();
    }

    @Override
    public void putLocally(KadContent content) throws IOException
    {
        this.dht.store(new JKademliaStorageEntry(content));
    }

    @Override
    public JKademliaStorageEntry get(GetParameter param) throws NoSuchElementException, IOException, ContentNotFoundException
    {
        if (this.dht.contains(param))
        {
            /* If the content exist in our own DHT, then return it. */
            return this.dht.get(param);
        }

        /* Seems like it doesn't exist in our DHT, get it from other Nodes */
        long startTime = System.nanoTime();
        ContentLookupOperation clo = new ContentLookupOperation(server, this, param, this.config);
        clo.execute();
        long endTime = System.nanoTime();
        this.statistician.addContentLookup(endTime - startTime, clo.routeLength(), clo.isContentFound());
        return clo.getContentFound();
    }

    @Override
    public void refresh() throws IOException
    {
        new KadRefreshOperation(this.server, this, this.dht, this.config).execute();
    }

    @Override
    public String getOwnerId()
    {
        return this.ownerId;
    }

    @Override
    public int getPort()
    {
        return this.udpPort;
    }

    @Override
    public void shutdown(final boolean saveState) throws IOException
    {
        /* Shut down the server */
        this.server.shutdown();

        this.stopRefreshOperation();

        /* Save this Kademlia instance's state if required */
        if (saveState)
        {
            /* Save the system state */
            this.saveKadState();
        }
    }

    @Override
    public void saveKadState() throws IOException
    {
        DataOutputStream dout;

        /**
         * @section Store Basic Kad data
         */
        dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "kad.kns"));
        new JsonSerializer<JKademliaNode>().write(this, dout);

        /**
         * @section Save the node state
         */
        dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "node.kns"));
        new JsonSerializer<Node>().write(this.localNode, dout);

        /**
         * @section Save the routing table
         * We need to save the routing table separate from the node since the routing table will contain the node and the node will contain the routing table
         * This will cause a serialization recursion, and in turn a Stack Overflow
         */
        dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "routingtable.kns"));
        new JsonRoutingTableSerializer(this.config).write(this.getRoutingTable(), dout);

        /**
         * @section Save the DHT
         */
        dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "dht.kns"));
        new JsonDHTSerializer().write(this.dht, dout);

    }

    /**
     * Get the name of the folder for which a content should be stored
     *
     * @return String The name of the folder to store node states
     */
    private static String getStateStorageFolderName(String ownerId, KadConfiguration iconfig)
    {
        /* Setup the nodes storage folder if it doesn't exist */
        String path = iconfig.getNodeDataFolder(ownerId) + File.separator + "nodeState";
        File nodeStateFolder = new File(path);
        if (!nodeStateFolder.isDirectory())
        {
            nodeStateFolder.mkdir();
        }
        return nodeStateFolder.toString();
    }

    @Override
    public KademliaRoutingTable getRoutingTable()
    {
        return this.routingTable;
    }

    @Override
    public KadStatistician getStatistician()
    {
        return this.statistician;
    }

    /**
     * Creates a string containing all data about this Kademlia instance
     *
     * @return The string representation of this Kad instance
     */
    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder("\n\nPrinting Kad State for instance with owner: ");
        sb.append(this.ownerId);
        sb.append("\n\n");

        sb.append("\n");
        sb.append("Local Node");
        sb.append(this.localNode);
        sb.append("\n");

        sb.append("\n");
        sb.append("Routing Table: ");
        sb.append(this.getRoutingTable());
        sb.append("\n");

        sb.append("\n");
        sb.append("DHT: ");
        sb.append(this.dht);
        sb.append("\n");

        sb.append("\n\n\n");

        return sb.toString();
    }
}


================================================
FILE: src/kademlia/KadConfiguration.java
================================================
package kademlia;

/**
 * Interface that defines a KadConfiguration object
 *
 * @author Joshua Kissoon
 * @since 20140329
 */
public interface KadConfiguration
{

    /**
     * @return Interval in milliseconds between execution of RestoreOperations.
     */
    public long restoreInterval();

    /**
     * If no reply received from a node in this period (in milliseconds)
     * consider the node unresponsive.
     *
     * @return The time it takes to consider a node unresponsive
     */
    public long responseTimeout();

    /**
     * @return Maximum number of milliseconds for performing an operation.
     */
    public long operationTimeout();

    /**
     * @return Maximum number of concurrent messages in transit.
     */
    public int maxConcurrentMessagesTransiting();

    /**
     * @return K-Value used throughout Kademlia
     */
    public int k();

    /**
     * @return Size of replacement cache.
     */
    public int replacementCacheSize();

    /**
     * @return # of times a node can be marked as stale before it is actually removed.
     */
    public int stale();

    /**
     * Creates the folder in which this node data is to be stored.
     *
     * @param ownerId
     *
     * @return The folder path
     */
    public String getNodeDataFolder(String ownerId);

    /**
     * @return Whether we're in a testing or production system.
     */
    public boolean isTesting();
}


================================================
FILE: src/kademlia/KadServer.java
================================================
package kademlia;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import kademlia.exceptions.KadServerDownException;
import kademlia.message.KademliaMessageFactory;
import kademlia.message.Message;
import kademlia.message.MessageFactory;
import kademlia.node.Node;
import kademlia.message.Receiver;

/**
 * The server that handles sending and receiving messages between nodes on the Kad Network
 *
 * @author Joshua Kissoon
 * @created 20140215
 */
public class KadServer
{

    /* Maximum size of a Datagram Packet */
    private static final int DATAGRAM_BUFFER_SIZE = 64 * 1024;      // 64KB

    /* Basic Kad Objects */
    private final transient KadConfiguration config;

    /* Server Objects */
    private final DatagramSocket socket;
    private transient boolean isRunning;
    private final Map<Integer, Receiver> receivers;
    private final Timer timer;      // Schedule future tasks
    private final Map<Integer, TimerTask> tasks;    // Keep track of scheduled tasks

    private final Node localNode;

    /* Factories */
    private final KademliaMessageFactory messageFactory;

    private final KadStatistician statistician;

    
    {
        isRunning = true;
        this.tasks = new HashMap<>();
        this.receivers = new HashMap<>();
        this.timer = new Timer(true);
    }

    /**
     * Initialize our KadServer
     *
     * @param udpPort      The port to listen on
     * @param mFactory     Factory used to create messages
     * @param localNode    Local node on which this server runs on
     * @param config
     * @param statistician A statistician to manage the server statistics
     *
     * @throws java.net.SocketException
     */
    public KadServer(int udpPort, KademliaMessageFactory mFactory, Node localNode, KadConfiguration config, KadStatistician statistician) throws SocketException
    {
        this.config = config;
        this.socket = new DatagramSocket(udpPort);
        this.localNode = localNode;
        this.messageFactory = mFactory;
        this.statistician = statistician;

        /* Start listening for incoming requests in a new thread */
        this.startListener();
    }

    /**
     * Starts the listener to listen for incoming messages
     */
    private void startListener()
    {
        new Thread()
        {
            @Override
            public void run()
            {
                listen();
            }
        }.start();
    }

    /**
     * Sends a message
     *
     * @param msg  The message to send
     * @param to   The node to send the message to
     * @param recv The receiver to handle the response message
     *
     * @return Integer The communication ID of this message
     *
     * @throws IOException
     * @throws kademlia.exceptions.KadServerDownException
     */
    public synchronized int sendMessage(Node to, Message msg, Receiver recv) throws IOException, KadServerDownException
    {
        if (!isRunning)
        {
            throw new KadServerDownException(this.localNode + " - Kad Server is not running.");
        }

        /* Generate a random communication ID */
        int comm = new Random().nextInt();

        /* If we have a receiver */
        if (recv != null)
        {
            try
            {
                /* Setup the receiver to handle message response */
                receivers.put(comm, recv);
                TimerTask task = new TimeoutTask(comm, recv);
                timer.schedule(task, this.config.responseTimeout());
                tasks.put(comm, task);
            }
            catch (IllegalStateException ex)
            {
                /* The timer is already cancelled so we cannot do anything here really */
            }
        }

        /* Send the message */
        sendMessage(to, msg, comm);

        return comm;
    }

    /**
     * Method called to reply to a message received
     *
     * @param to   The Node to send the reply to
     * @param msg  The reply message
     * @param comm The communication ID - the one received
     *
     * @throws java.io.IOException
     */
    public synchronized void reply(Node to, Message msg, int comm) throws IOException
    {
        if (!isRunning)
        {
            throw new IllegalStateException("Kad Server is not running.");
        }
        sendMessage(to, msg, comm);
    }

    /**
     * Internal sendMessage method called by the public sendMessage method after a communicationId is generated
     */
    private void sendMessage(Node to, Message msg, int comm) throws IOException
    {
        /* Use a try-with resource to auto-close streams after usage */
        try (ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(bout);)
        {
            /* Setup the message for transmission */
            dout.writeInt(comm);
            dout.writeByte(msg.code());
            msg.toStream(dout);
            dout.close();

            byte[] data = bout.toByteArray();

            if (data.length > DATAGRAM_BUFFER_SIZE)
            {
                throw new IOException("Message is too big");
            }

            /* Everything is good, now create the packet and send it */
            DatagramPacket pkt = new DatagramPacket(data, 0, data.length);
            pkt.setSocketAddress(to.getSocketAddress());
            socket.send(pkt);

            /* Lets inform the statistician that we've sent some data */
            this.statistician.sentData(data.length);
        }
    }

    /**
     * Listen for incoming messages in a separate thread
     */
    private void listen()
    {
        try
        {
            while (isRunning)
            {
                try
                {
                    /* Wait for a packet */
                    byte[] buffer = new byte[DATAGRAM_BUFFER_SIZE];
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                    socket.receive(packet);

                    /* Lets inform the statistician that we've received some data */
                    this.statistician.receivedData(packet.getLength());

                    if (this.config.isTesting())
                    {
                        /**
                         * Simulating network latency
                         * We pause for 1 millisecond/100 bytes
                         */
                        int pause = packet.getLength() / 100;
                        try
                        {
                            Thread.sleep(pause);
                        }
                        catch (InterruptedException ex)
                        {

                        }
                    }

                    /* We've received a packet, now handle it */
                    try (ByteArrayInputStream bin = new ByteArrayInputStream(packet.getData(), packet.getOffset(), packet.getLength());
                            DataInputStream din = new DataInputStream(bin);)
                    {

                        /* Read in the conversation Id to know which handler to handle this response */
                        int comm = din.readInt();
                        byte messCode = din.readByte();

                        Message msg = messageFactory.createMessage(messCode, din);
                        din.close();

                        /* Get a receiver for this message */
                        Receiver receiver;
                        if (this.receivers.containsKey(comm))
                        {
                            /* If there is a reciever in the receivers to handle this */
                            synchronized (this)
                            {
                                receiver = this.receivers.remove(comm);
                                TimerTask task = (TimerTask) tasks.remove(comm);
                                if (task != null)
                                {
                                    task.cancel();
                                }
                            }
                        }
                        else
                        {
                            /* There is currently no receivers, try to get one */
                            receiver = messageFactory.createReceiver(messCode, this);
                        }

                        /* Invoke the receiver */
                        if (receiver != null)
                        {
                            receiver.receive(msg, comm);
                        }
                    }
                }
                catch (IOException e)
                {
                    //this.isRunning = false;
                    System.err.println("Server ran into a problem in listener method. Message: " + e.getMessage());
                }
            }
        }
        finally
        {
            if (!socket.isClosed())
            {
                socket.close();
            }
            this.isRunning = false;
        }
    }

    /**
     * Remove a conversation receiver
     *
     * @param comm The id of this conversation
     */
    private synchronized void unregister(int comm)
    {
        receivers.remove(comm);
        this.tasks.remove(comm);
    }

    /**
     * Stops listening and shuts down the server
     */
    public synchronized void shutdown()
    {
        this.isRunning = false;
        this.socket.close();
        timer.cancel();
    }

    /**
     * Task that gets called by a separate thread if a timeout for a receiver occurs.
     * When a reply arrives this task must be canceled using the <code>cancel()</code>
     * method inherited from <code>TimerTask</code>. In this case the caller is
     * responsible for removing the task from the <code>tasks</code> map.
     * */
    class TimeoutTask extends TimerTask
    {

        private final int comm;
        private final Receiver recv;

        public TimeoutTask(int comm, Receiver recv)
        {
            this.comm = comm;
            this.recv = recv;
        }

        @Override
        public void run()
        {
            if (!KadServer.this.isRunning)
            {
                return;
            }

            try
            {
                unregister(comm);
                recv.timeout(comm);
            }
            catch (IOException e)
            {
                System.err.println("Cannot unregister a receiver. Message: " + e.getMessage());
            }
        }
    }

    public void printReceivers()
    {
        for (Integer r : this.receivers.keySet())
        {
            System.out.println("Receiver for comm: " + r + "; Receiver: " + this.receivers.get(r));
        }
    }

    public boolean isRunning()
    {
        return this.isRunning;
    }

}


================================================
FILE: src/kademlia/KadStatistician.java
================================================
package kademlia;

/**
 * Specification for class that keeps statistics for a Kademlia instance.
 *
 * These statistics are temporary and will be lost when Kad is shut down.
 *
 * @author Joshua Kissoon
 * @since 20140507
 */
public interface KadStatistician
{

    /**
     * Used to indicate some data is sent
     *
     * @param size The size of the data sent
     */
    public void sentData(long size);

    /**
     * @return The total data sent in KiloBytes
     */
    public long getTotalDataSent();

    /**
     * Used to indicate some data was received
     *
     * @param size The size of the data received
     */
    public void receivedData(long size);

    /**
     * @return The total data received in KiloBytes
     */
    public long getTotalDataReceived();

    /**
     * Sets the bootstrap time for this Kademlia Node
     *
     * @param time The bootstrap time in nanoseconds
     */
    public void setBootstrapTime(long time);

    /**
     * @return How long the system took to bootstrap in milliseconds
     */
    public long getBootstrapTime();

    /**
     * Add the timing for a new content lookup operation that took place
     *
     * @param time         The time the content lookup took in nanoseconds
     * @param routeLength  The length of the route it took to get the content
     * @param isSuccessful Whether the content lookup was successful or not
     */
    public void addContentLookup(long time, int routeLength, boolean isSuccessful);

    /**
     * @return The total number of content lookups performed.
     */
    public int numContentLookups();

    /**
     * @return How many content lookups have failed.
     */
    public int numFailedContentLookups();

    /**
     * @return The total time spent on content lookups.
     */
    public long totalContentLookupTime();

    /**
     * Compute the average time a content lookup took
     *
     * @return The average time in milliseconds
     */
    public double averageContentLookupTime();

    /**
     * Compute the average route length of content lookup operations.
     *
     * @return The average route length
     */
    public double averageContentLookupRouteLength();
}


================================================
FILE: src/kademlia/KademliaNode.java
================================================
package kademlia;

import java.io.IOException;
import java.util.NoSuchElementException;
import kademlia.dht.GetParameter;
import kademlia.dht.JKademliaStorageEntry;
import kademlia.dht.KadContent;
import kademlia.dht.KademliaDHT;
import kademlia.dht.KademliaStorageEntry;
import kademlia.exceptions.ContentNotFoundException;
import kademlia.exceptions.RoutingException;
import kademlia.node.Node;
import kademlia.routing.KademliaRoutingTable;

/**
 * The main Kademlia Node on the network, this node manages everything for this local system.
 *
 * @author Joshua Kissoon
 * @since 20140523
 *
 */
public interface KademliaNode
{

    /**
     * Schedule the recurring refresh operation
     */
    public void startRefreshOperation();

    /**
     * Stop the recurring refresh operation
     */
    public void stopRefreshOperation();

    /**
     * @return Node The local node for this system
     */
    public Node getNode();

    /**
     * @return The KadServer used to send/receive messages
     */
    public KadServer getServer();

    /**
     * @return The DHT for this kad instance
     */
    public KademliaDHT getDHT();

    /**
     * @return The current KadConfiguration object being used
     */
    public KadConfiguration getCurrentConfiguration();

    /**
     * Connect to an existing peer-to-peer network.
     *
     * @param n The known node in the peer-to-peer network
     *
     * @throws RoutingException      If the bootstrap node could not be contacted
     * @throws IOException           If a network error occurred
     * @throws IllegalStateException If this object is closed
     * */
    public void bootstrap(Node n) throws IOException, RoutingException;

    /**
     * Stores the specified value under the given key
     * This value is stored on K nodes on the network, or all nodes if there are > K total nodes in the network
     *
     * @param content The content to put onto the DHT
     *
     * @return Integer How many nodes the content was stored on
     *
     * @throws java.io.IOException
     *
     */
    public int put(KadContent content) throws IOException;

    /**
     * Stores the specified value under the given key
     * This value is stored on K nodes on the network, or all nodes if there are > K total nodes in the network
     *
     * @param entry The StorageEntry with the content to put onto the DHT
     *
     * @return Integer How many nodes the content was stored on
     *
     * @throws java.io.IOException
     *
     */
    public int put(JKademliaStorageEntry entry) throws IOException;

    /**
     * Store a content on the local node's DHT
     *
     * @param content The content to put on the DHT
     *
     * @throws java.io.IOException
     */
    public void putLocally(KadContent content) throws IOException;

    /**
     * Get some content stored on the DHT
     *
     * @param param The parameters used to search for the content
     *
     * @return DHTContent The content
     *
     * @throws java.io.IOException
     * @throws kademlia.exceptions.ContentNotFoundException
     */
    public JKademliaStorageEntry get(GetParameter param) throws NoSuchElementException, IOException, ContentNotFoundException;

    /**
     * Allow the user of the System to call refresh even out of the normal Kad refresh timing
     *
     * @throws java.io.IOException
     */
    public void refresh() throws IOException;

    /**
     * @return String The ID of the owner of this local network
     */
    public String getOwnerId();

    /**
     * @return Integer The port on which this kad instance is running
     */
    public int getPort();

    /**
     * Here we handle properly shutting down the Kademlia instance
     *
     * @param saveState Whether to save the application state or not
     *
     * @throws java.io.FileNotFoundException
     */
    public void shutdown(final boolean saveState) throws IOException;

    /**
     * Saves the node state to a text file
     *
     * @throws java.io.FileNotFoundException
     */
    public void saveKadState() throws IOException;

    /**
     * @return The routing table for this node.
     */
    public KademliaRoutingTable getRoutingTable();

    /**
     * @return The statistician that manages all statistics
     */
    public KadStatistician getStatistician();
}


================================================
FILE: src/kademlia/Statistician.java
================================================
package kademlia;

import java.text.DecimalFormat;

/**
 * Class that keeps statistics for this Kademlia instance.
 *
 * These statistics are temporary and will be lost when Kad is shut down.
 *
 * @author Joshua Kissoon
 * @since 20140505
 */
public class Statistician implements KadStatistician
{

    /* How much data was sent and received by the server over the network */
    private long totalDataSent, totalDataReceived;
    private long numDataSent, numDataReceived;

    /* Bootstrap timings */
    private long bootstrapTime;

    /* Content lookup operation timing & route length */
    private int numContentLookups, numFailedContentLookups;
    private long totalContentLookupTime;
    private long totalRouteLength;

    
    {
        this.totalDataSent = 0;
        this.totalDataReceived = 0;
        this.bootstrapTime = 0;
        this.numContentLookups = 0;
        this.totalContentLookupTime = 0;
        this.totalRouteLength = 0;
    }

    @Override
    public void sentData(long size)
    {
        this.totalDataSent += size;
        this.numDataSent++;
    }

    @Override
    public long getTotalDataSent()
    {
        if (this.totalDataSent == 0)
        {
            return 0L;
        }
        
        return this.totalDataSent / 1000L;
    }

    @Override
    public void receivedData(long size)
    {
        this.totalDataReceived += size;
        this.numDataReceived++;
    }

    @Override
    public long getTotalDataReceived()
    {
        if (this.totalDataReceived == 0)
        {
            return 0L;
        }
        return this.totalDataReceived / 1000L;
    }

    @Override
    public void setBootstrapTime(long time)
    {
        this.bootstrapTime = time;
    }

    @Override
    public long getBootstrapTime()
    {
        return this.bootstrapTime / 1000000L;
    }

    @Override
    public void addContentLookup(long time, int routeLength, boolean isSuccessful)
    {
        if (isSuccessful)
        {
            this.numContentLookups++;
            this.totalContentLookupTime += time;
            this.totalRouteLength += routeLength;
        }
        else
        {
            this.numFailedContentLookups++;
        }
    }

    @Override
    public int numContentLookups()
    {
        return this.numContentLookups;
    }

    @Override
    public int numFailedContentLookups()
    {
        return this.numFailedContentLookups;
    }

    @Override
    public long totalContentLookupTime()
    {
        return this.totalContentLookupTime;
    }

    @Override
    public double averageContentLookupTime()
    {
        if (this.numContentLookups == 0)
        {
            return 0D;
        }

        double avg = (double) ((double) this.totalContentLookupTime / (double) this.numContentLookups) / 1000000D;
        DecimalFormat df = new DecimalFormat("#.00");
        return new Double(df.format(avg));
    }

    @Override
    public double averageContentLookupRouteLength()
    {
        if (this.numContentLookups == 0)
        {
            return 0D;
        }
        double avg = (double) ((double) this.totalRouteLength / (double) this.numContentLookups);
        DecimalFormat df = new DecimalFormat("#.00");
        return new Double(df.format(avg));
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder("Statistician: [");

        sb.append("Bootstrap Time: ");
        sb.append(this.getBootstrapTime());
        sb.append("; ");

        sb.append("Data Sent: ");
        sb.append("(");
        sb.append(this.numDataSent);
        sb.append(") ");
        sb.append(this.getTotalDataSent());
        sb.append(" bytes; ");

        sb.append("Data Received: ");
        sb.append("(");
        sb.append(this.numDataReceived);
        sb.append(") ");
        sb.append(this.getTotalDataReceived());
        sb.append(" bytes; ");

        sb.append("Num Content Lookups: ");
        sb.append(this.numContentLookups());
        sb.append("; ");

        sb.append("Avg Content Lookup Time: ");
        sb.append(this.averageContentLookupTime());
        sb.append("; ");

        sb.append("Avg Content Lookup Route Lth: ");
        sb.append(this.averageContentLookupRouteLength());
        sb.append("; ");

        sb.append("]");

        return sb.toString();
    }
}


================================================
FILE: src/kademlia/Todo
================================================
# What's left to add to the implementation

1. Implement the "Optimized Contact Accounting" features as mentioned in the paper
2. Implement the "Accelerated Lookups" featured as described in the paper
3. Add a setup file on how to setup Kademlia and run it.


Next Steps:
- Write Unit Tests
- Improve multi-threading system
-- I think server is slow in handling requests because the listen method runs in a single thread.
--- Listen() method should create a new thread to handle every incoming request.
- KadStatistician
-- Let the statistician keep track of failed get requests!

================================================
FILE: src/kademlia/dht/DHT.java
================================================
package kademlia.dht;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.NoSuchElementException;
import kademlia.KadConfiguration;
import kademlia.exceptions.ContentExistException;
import kademlia.exceptions.ContentNotFoundException;
import kademlia.node.KademliaId;
import kademlia.util.serializer.JsonSerializer;
import kademlia.util.serializer.KadSerializer;

/**
 * The main Distributed Hash Table class that manages the entire DHT
 *
 * @author Joshua Kissoon
 * @since 20140226
 */
public class DHT implements KademliaDHT
{

    private transient StoredContentManager contentManager;
    private transient KadSerializer<JKademliaStorageEntry> serializer = null;
    private transient KadConfiguration config;

    private final String ownerId;

    public DHT(String ownerId, KadConfiguration config)
    {
        this.ownerId = ownerId;
        this.config = config;
        this.initialize();
    }

    @Override
    public final void initialize()
    {
        contentManager = new StoredContentManager();
    }

    @Override
    public void setConfiguration(KadConfiguration con)
    {
        this.config = con;
    }

    @Override
    public KadSerializer<JKademliaStorageEntry> getSerializer()
    {
        if (null == serializer)
        {
            serializer = new JsonSerializer<>();
        }

        return serializer;
    }

    @Override
    public boolean store(JKademliaStorageEntry content) throws IOException
    {
        /* Lets check if we have this content and it's the updated version */
        if (this.contentManager.contains(content.getContentMetadata()))
        {
            KademliaStorageEntryMetadata current = this.contentManager.get(content.getContentMetadata());

            /* update the last republished time */
            current.updateLastRepublished();

            if (current.getLastUpdatedTimestamp() >= content.getContentMetadata().getLastUpdatedTimestamp())
            {
                /* We have the current content, no need to update it! just leave this method now */
                return false;
            }
            else
            {
                /* We have this content, but not the latest version, lets delete it so the new version will be added below */
                try
                {
                    //System.out.println("Removing older content to update it");
                    this.remove(content.getContentMetadata());
                }
                catch (ContentNotFoundException ex)
                {
                    /* This won't ever happen at this point since we only get here if the content is found, lets ignore it  */
                }
            }
        }

        /**
         * If we got here means we don't have this content, or we need to update the content
         * If we need to update the content, the code above would've already deleted it, so we just need to re-add it
         */
        try
        {
            //System.out.println("Adding new content.");
            /* Keep track of this content in the entries manager */
            KademliaStorageEntryMetadata sEntry = this.contentManager.put(content.getContentMetadata());

            /* Now we store the content locally in a file */
            String contentStorageFolder = this.getContentStorageFolderName(content.getContentMetadata().getKey());

            try (FileOutputStream fout = new FileOutputStream(contentStorageFolder + File.separator + sEntry.hashCode() + ".kct");
                    DataOutputStream dout = new DataOutputStream(fout))
            {
                this.getSerializer().write(content, dout);
            }
            return true;
        }
        catch (ContentExistException e)
        {
            /**
             * Content already exist on the DHT
             * This won't happen because above takes care of removing the content if it's older and needs to be updated,
             * or returning if we already have the current content version.
             */
            return false;
        }
    }

    @Override
    public boolean store(KadContent content) throws IOException
    {
        return this.store(new JKademliaStorageEntry(content));
    }

    @Override
    public JKademliaStorageEntry retrieve(KademliaId key, int hashCode) throws FileNotFoundException, IOException, ClassNotFoundException
    {
        String folder = this.getContentStorageFolderName(key);
        DataInputStream din = new DataInputStream(new FileInputStream(folder + File.separator + hashCode + ".kct"));
        return this.getSerializer().read(din);
    }

    @Override
    public boolean contains(GetParameter param)
    {
        return this.contentManager.contains(param);
    }

    @Override
    public JKademliaStorageEntry get(KademliaStorageEntryMetadata entry) throws IOException, NoSuchElementException
    {
        try
        {
            return this.retrieve(entry.getKey(), entry.hashCode());
        }
        catch (FileNotFoundException e)
        {
            System.err.println("Error while loading file for content. Message: " + e.getMessage());
        }
        catch (ClassNotFoundException e)
        {
            System.err.println("The class for some content was not found. Message: " + e.getMessage());
        }

        /* If we got here, means we got no entries */
        throw new NoSuchElementException();
    }

    @Override
    public JKademliaStorageEntry get(GetParameter param) throws NoSuchElementException, IOException
    {
        /* Load a KadContent if any exist for the given criteria */
        try
        {
            KademliaStorageEntryMetadata e = this.contentManager.get(param);
            return this.retrieve(e.getKey(), e.hashCode());
        }
        catch (FileNotFoundException e)
        {
            System.err.println("Error while loading file for content. Message: " + e.getMessage());
        }
        catch (ClassNotFoundException e)
        {
            System.err.println("The class for some content was not found. Message: " + e.getMessage());
        }

        /* If we got here, means we got no entries */
        throw new NoSuchElementException();
    }

    @Override
    public void remove(KadContent content) throws ContentNotFoundException
    {
        this.remove(new StorageEntryMetadata(content));
    }

    @Override
    public void remove(KademliaStorageEntryMetadata entry) throws ContentNotFoundException
    {
        String folder = this.getContentStorageFolderName(entry.getKey());
        File file = new File(folder + File.separator + entry.hashCode() + ".kct");

        contentManager.remove(entry);

        if (file.exists())
        {
            file.delete();
        }
        else
        {
            throw new ContentNotFoundException();
        }
    }

    /**
     * Get the name of the folder for which a content should be stored
     *
     * @param key The key of the content
     *
     * @return String The name of the folder
     */
    private String getContentStorageFolderName(KademliaId key)
    {
        /**
         * Each content is stored in a folder named after the first 2 characters of the NodeId
         *
         * The name of the file containing the content is the hash of this content
         */
        String folderName = key.hexRepresentation().substring(0, 2);
        File contentStorageFolder = new File(this.config.getNodeDataFolder(ownerId) + File.separator + folderName);

        /* Create the content folder if it doesn't exist */
        if (!contentStorageFolder.isDirectory())
        {
            contentStorageFolder.mkdir();
        }

        return contentStorageFolder.toString();
    }

    @Override
    public List<KademliaStorageEntryMetadata> getStorageEntries()
    {
        return contentManager.getAllEntries();
    }

    @Override
    public void putStorageEntries(List<KademliaStorageEntryMetadata> ientries)
    {
        for (KademliaStorageEntryMetadata e : ientries)
        {
            try
            {
                this.contentManager.put(e);
            }
            catch (ContentExistException ex)
            {
                /* Entry already exist, no need to store it again */
            }
        }
    }

    @Override
    public synchronized String toString()
    {
        return this.contentManager.toString();
    }
}


================================================
FILE: src/kademlia/dht/GetParameter.java
================================================
package kademlia.dht;

import kademlia.node.KademliaId;

/**
 * A GET request can get content based on Key, Owner, Type, etc
 *
 * This is a class containing the parameters to be passed in a GET request
 *
 * We use a class since the number of filtering parameters can change later
 *
 * @author Joshua Kissoon
 * @since 20140224
 */
public class GetParameter
{

    private KademliaId key;
    private String ownerId = null;
    private String type = null;

    /**
     * Construct a GetParameter to search for data by NodeId and owner
     *
     * @param key
     * @param type
     */
    public GetParameter(KademliaId key, String type)
    {
        this.key = key;
        this.type = type;
    }

    /**
     * Construct a GetParameter to search for data by NodeId, owner, type
     *
     * @param key
     * @param type
     * @param owner
     */
    public GetParameter(KademliaId key, String type, String owner)
    {
        this(key, type);
        this.ownerId = owner;
    }

    /**
     * Construct our get parameter from a Content
     *
     * @param c
     */
    public GetParameter(KadContent c)
    {
        this.key = c.getKey();

        if (c.getType() != null)
        {
            this.type = c.getType();
        }

        if (c.getOwnerId() != null)
        {
            this.ownerId = c.getOwnerId();
        }
    }

    /**
     * Construct our get parameter from a StorageEntryMeta data
     *
     * @param md
     */
    public GetParameter(KademliaStorageEntryMetadata md)
    {
        this.key = md.getKey();

        if (md.getType() != null)
        {
            this.type = md.getType();
        }

        if (md.getOwnerId() != null)
        {
            this.ownerId = md.getOwnerId();
        }
    }

    public KademliaId getKey()
    {
        return this.key;
    }

    public void setOwnerId(String ownerId)
    {
        this.ownerId = ownerId;
    }

    public String getOwnerId()
    {
        return this.ownerId;
    }

    public void setType(String type)
    {
        this.type = type;
    }

    public String getType()
    {
        return this.type;
    }

    @Override
    public String toString()
    {
        return "GetParameter - [Key: " + key + "][Owner: " + this.ownerId + "][Type: " + this.type + "]";
    }
}


================================================
FILE: src/kademlia/dht/JKademliaStorageEntry.java
================================================
package kademlia.dht;

/**
 * A JKademliaStorageEntry class that is used to store a content on the DHT
 *
 * @author Joshua Kissoon
 * @since 20140402
 */
public class JKademliaStorageEntry implements KademliaStorageEntry
{

    private String content;
    private final StorageEntryMetadata metadata;

    public JKademliaStorageEntry(final KadContent content)
    {
        this(content, new StorageEntryMetadata(content));
    }

    public JKademliaStorageEntry(final KadContent content, final StorageEntryMetadata metadata)
    {
        this.setContent(content.toSerializedForm());
        this.metadata = metadata;
    }

    @Override
    public final void setContent(final byte[] data)
    {
        this.content = new String(data);
    }

    @Override
    public final byte[] getContent()
    {
        return this.content.getBytes();
    }

    @Override
    public final KademliaStorageEntryMetadata getContentMetadata()
    {
        return this.metadata;
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder("[StorageEntry: ");

        sb.append("[Content: ");
        sb.append(this.getContent());
        sb.append("]");

        sb.append(this.getContentMetadata());

        sb.append("]");

        return sb.toString();
    }
}


================================================
FILE: src/kademlia/dht/KadContent.java
================================================
package kademlia.dht;

import kademlia.node.KademliaId;

/**
 * Any piece of content that needs to be stored on the DHT
 *
 * @author Joshua Kissoon
 *
 * @since 20140224
 */
public interface KadContent
{

    /**
     * @return NodeId The DHT key for this content
     */
    public KademliaId getKey();

    /**
     * @return String The type of content
     */
    public String getType();

    /**
     * Each content will have an created date
     * This allows systems to know when to delete a content form his/her machine
     *
     * @return long The create date of this content
     */
    public long getCreatedTimestamp();

    /**
     * Each content will have an update timestamp
     * This allows the DHT to keep only the latest version of a content
     *
     * @return long The timestamp of when this content was last updated
     */
    public long getLastUpdatedTimestamp();

    /**
     * @return The ID of the owner of this content
     */
    public String getOwnerId();

    /**
     * Each content needs to be in byte format for transporting and storage,
     * this method takes care of that.
     *
     * Each object is responsible for transforming itself to byte format since the
     * structure of methods may differ.
     *
     * @return The content in byte format
     */
    public byte[] toSerializedForm();

    /**
     * Given the Content in byte format, read it
     *
     * @param data The object in byte format
     *
     * @return A new object from the given
     */
    public KadContent fromSerializedForm(byte[] data);
}


================================================
FILE: src/kademlia/dht/KademliaDHT.java
================================================
package kademlia.dht;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.NoSuchElementException;
import kademlia.KadConfiguration;
import kademlia.exceptions.ContentNotFoundException;
import kademlia.node.KademliaId;
import kademlia.util.serializer.KadSerializer;

/**
 * The main Distributed Hash Table interface that manages the entire DHT
 *
 * @author Joshua Kissoon
 * @since 20140523
 */
public interface KademliaDHT
{

    /**
     * Initialize this DHT to it's default state
     */
    public void initialize();

    /**
     * Set a new configuration. Mainly used when we restore the DHT state from a file
     *
     * @param con The new configuration file
     */
    public void setConfiguration(KadConfiguration con);

    /**
     * Creates a new Serializer or returns an existing serializer
     *
     * @return The new ContentSerializer
     */
    public KadSerializer<JKademliaStorageEntry> getSerializer();

    /**
     * Handle storing content locally
     *
     * @param content The DHT content to store
     *
     * @return boolean true if we stored the content, false if the content already exists and is up to date
     *
     * @throws java.io.IOException
     */
    public boolean store(JKademliaStorageEntry content) throws IOException;

    public boolean store(KadContent content) throws IOException;

    /**
     * Retrieves a Content from local storage
     *
     * @param key      The Key of the content to retrieve
     * @param hashCode The hash code of the content to retrieve
     *
     * @return A KadContent object
     *
     * @throws java.io.FileNotFoundException
     * @throws java.lang.ClassNotFoundException
     */
    public JKademliaStorageEntry retrieve(KademliaId key, int hashCode) throws FileNotFoundException, IOException, ClassNotFoundException;

    /**
     * Check if any content for the given criteria exists in this DHT
     *
     * @param param The content search criteria
     *
     * @return boolean Whether any content exist that satisfy the criteria
     */
    public boolean contains(GetParameter param);

    /**
     * Retrieve and create a KadContent object given the StorageEntry object
     *
     * @param entry The StorageEntry used to retrieve this content
     *
     * @return KadContent The content object
     *
     * @throws java.io.IOException
     */
    public JKademliaStorageEntry get(KademliaStorageEntryMetadata entry) throws IOException, NoSuchElementException;

    /**
     * Get the StorageEntry for the content if any exist.
     *
     * @param param The parameters used to filter the content needed
     *
     * @return KadContent A KadContent found on the DHT satisfying the given criteria
     *
     * @throws java.io.IOException
     */
    public JKademliaStorageEntry get(GetParameter param) throws NoSuchElementException, IOException;

    /**
     * Delete a content from local storage
     *
     * @param content The Content to Remove
     *
     *
     * @throws kademlia.exceptions.ContentNotFoundException
     */
    public void remove(KadContent content) throws ContentNotFoundException;

    public void remove(KademliaStorageEntryMetadata entry) throws ContentNotFoundException;

    /**
     * @return A List of all StorageEntries for this node
     */
    public List<KademliaStorageEntryMetadata> getStorageEntries();

    /**
     * Used to add a list of storage entries for existing content to the DHT.
     * Mainly used when retrieving StorageEntries from a saved state file.
     *
     * @param ientries The entries to add
     */
    public void putStorageEntries(List<KademliaStorageEntryMetadata> ientries);

}


================================================
FILE: src/kademlia/dht/KademliaStorageEntry.java
================================================
package kademlia.dht;

/**
 * A StorageEntry interface for the storage entry class used to store a content on the DHT
 *
 * @author Joshua Kissoon
 * @since 20140523
 */
public interface KademliaStorageEntry
{

    /**
     * Add the content to the storage entry
     *
     * @param data The content data in byte[] format
     */
    public void setContent(final byte[] data);

    /**
     * Get the content from this storage entry
     *
     * @return The content in byte format
     */
    public byte[] getContent();

    /**
     * Get the metadata for this storage entry
     *
     * @return the storage entry metadata
     */
    public KademliaStorageEntryMetadata getContentMetadata();
}


================================================
FILE: src/kademlia/dht/KademliaStorageEntryMetadata.java
================================================
package kademlia.dht;

import kademlia.node.KademliaId;

/**
 * Keeps track of data for a Content stored in the DHT
 * Used by the StorageEntryManager class
 *
 * @author Joshua Kissoon
 * @since 20140226
 */
public interface KademliaStorageEntryMetadata
{

    /**
     * @return The Kademlia ID of this content
     */
    public KademliaId getKey();

    /**
     * @return The content's owner ID
     */
    public String getOwnerId();

    /**
     * @return The type of this content
     */
    public String getType();

    /**
     * @return A hash of the content
     */
    public int getContentHash();

    /**
     * @return The last time this content was updated
     */
    public long getLastUpdatedTimestamp();

    /**
     * When a node is looking for content, he sends the search criteria in a GetParameter object
     * Here we take this GetParameter object and check if this StorageEntry satisfies the given parameters
     *
     * @param params
     *
     * @return boolean Whether this content satisfies the parameters
     */
    public boolean satisfiesParameters(GetParameter params);

    /**
     * @return The timestamp for the last time this content was republished
     */
    public long lastRepublished();

    /**
     * Whenever we republish a content or get this content from the network, we update the last republished time
     */
    public void updateLastRepublished();
}


================================================
FILE: src/kademlia/dht/StorageEntryMetadata.java
================================================
package kademlia.dht;

import java.util.Objects;
import kademlia.node.KademliaId;

/**
 * Keeps track of data for a Content stored in the DHT
 * Used by the StorageEntryManager class
 *
 * @author Joshua Kissoon
 * @since 20140226
 */
public class StorageEntryMetadata implements KademliaStorageEntryMetadata
{

    private final KademliaId key;
    private final String ownerId;
    private final String type;
    private final int contentHash;
    private final long updatedTs;

    /* This value is the last time this content was last updated from the network */
    private long lastRepublished;

    public StorageEntryMetadata(KadContent content)
    {
        this.key = content.getKey();
        this.ownerId = content.getOwnerId();
        this.type = content.getType();
        this.contentHash = content.hashCode();
        this.updatedTs = content.getLastUpdatedTimestamp();

        this.lastRepublished = System.currentTimeMillis() / 1000L;
    }

    @Override
    public KademliaId getKey()
    {
        return this.key;
    }

    @Override
    public String getOwnerId()
    {
        return this.ownerId;
    }

    @Override
    public String getType()
    {
        return this.type;
    }

    @Override
    public int getContentHash()
    {
        return this.contentHash;
    }

    @Override
    public long getLastUpdatedTimestamp()
    {
        return this.updatedTs;
    }

    /**
     * When a node is looking for content, he sends the search criteria in a GetParameter object
     * Here we take this GetParameter object and check if this StorageEntry satisfies the given parameters
     *
     * @param params
     *
     * @return boolean Whether this content satisfies the parameters
     */
    @Override
    public boolean satisfiesParameters(GetParameter params)
    {
        /* Check that owner id matches */
        if ((params.getOwnerId() != null) && (!params.getOwnerId().equals(this.ownerId)))
        {
            return false;
        }

        /* Check that type matches */
        if ((params.getType() != null) && (!params.getType().equals(this.type)))
        {
            return false;
        }

        /* Check that key matches */
        if ((params.getKey() != null) && (!params.getKey().equals(this.key)))
        {
            return false;
        }

        return true;
    }

    @Override
    public long lastRepublished()
    {
        return this.lastRepublished;
    }

    /**
     * Whenever we republish a content or get this content from the network, we update the last republished time
     */
    @Override
    public void updateLastRepublished()
    {
        this.lastRepublished = System.currentTimeMillis() / 1000L;
    }

    @Override
    public boolean equals(Object o)
    {
        if (o instanceof KademliaStorageEntryMetadata)
        {
            return this.hashCode() == o.hashCode();
        }

        return false;
    }

    @Override
    public int hashCode()
    {
        int hash = 3;
        hash = 23 * hash + Objects.hashCode(this.key);
        hash = 23 * hash + Objects.hashCode(this.ownerId);
        hash = 23 * hash + Objects.hashCode(this.type);
        return hash;
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder("[StorageEntry: ");

        sb.append("{Key: ");
        sb.append(this.key);
        sb.append("} ");
        sb.append("{Owner: ");
        sb.append(this.ownerId);
        sb.append("} ");
        sb.append("{Type: ");
        sb.append(this.type);
        sb.append("} ");
        sb.append("]");

        return sb.toString();
    }
}


================================================
FILE: src/kademlia/dht/StoredContentManager.java
================================================
package kademlia.dht;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import kademlia.exceptions.ContentExistException;
import kademlia.exceptions.ContentNotFoundException;
import kademlia.node.KademliaId;

/**
 * It would be infeasible to keep all content in memory to be send when requested
 * Instead we store content into files
 * We use this Class to keep track of all content stored
 *
 * @author Joshua Kissoon
 * @since 20140226
 */
class StoredContentManager
{

    private final Map<KademliaId, List<KademliaStorageEntryMetadata>> entries;

    
    {
        entries = new HashMap<>();
    }

    /**
     * Add a new entry to our storage
     *
     * @param content The content to store a reference to
     */
    public KademliaStorageEntryMetadata put(KadContent content) throws ContentExistException
    {
        return this.put(new StorageEntryMetadata(content));
    }

    /**
     * Add a new entry to our storage
     *
     * @param entry The StorageEntry to store
     */
    public KademliaStorageEntryMetadata put(KademliaStorageEntryMetadata entry) throws ContentExistException
    {
        if (!this.entries.containsKey(entry.getKey()))
        {
            this.entries.put(entry.getKey(), new ArrayList<>());
        }

        /* If this entry doesn't already exist, then we add it */
        if (!this.contains(entry))
        {
            this.entries.get(entry.getKey()).add(entry);

            return entry;
        }
        else
        {
            throw new ContentExistException("Content already exists on this DHT");
        }
    }

    /**
     * Checks if our DHT has a Content for the given criteria
     *
     * @param param The parameters used to search for a content
     *
     * @return boolean
     */
    public synchronized boolean contains(GetParameter param)
    {
        if (this.entries.containsKey(param.getKey()))
        {
            /* Content with this key exist, check if any match the rest of the search criteria */
            for (KademliaStorageEntryMetadata e : this.entries.get(param.getKey()))
            {
                /* If any entry satisfies the given parameters, return true */
                if (e.satisfiesParameters(param))
                {
                    return true;
                }
            }
        }
        else
        {
        }
        return false;
    }

    /**
     * Check if a content exist in the DHT
     */
    public synchronized boolean contains(KadContent content)
    {
        return this.contains(new GetParameter(content));
    }

    /**
     * Check if a StorageEntry exist on this DHT
     */
    public synchronized boolean contains(KademliaStorageEntryMetadata entry)
    {
        return this.contains(new GetParameter(entry));
    }

    /**
     * Checks if our DHT has a Content for the given criteria
     *
     * @param param The parameters used to search for a content
     *
     * @return List of content for the specific search parameters
     */
    public KademliaStorageEntryMetadata get(GetParameter param) throws NoSuchElementException
    {
        if (this.entries.containsKey(param.getKey()))
        {
            /* Content with this key exist, check if any match the rest of the search criteria */
            for (KademliaStorageEntryMetadata e : this.entries.get(param.getKey()))
            {
                /* If any entry satisfies the given parameters, return true */
                if (e.satisfiesParameters(param))
                {
                    return e;
                }
            }

            /* If we got here, means we didn't find any entry */
            throw new NoSuchElementException();
        }
        else
        {
            throw new NoSuchElementException("No content exist for the given parameters");
        }
    }

    public KademliaStorageEntryMetadata get(KademliaStorageEntryMetadata md)
    {
        return this.get(new GetParameter(md));
    }

    /**
     * @return A list of all storage entries
     */
    public synchronized List<KademliaStorageEntryMetadata> getAllEntries()
    {
        List<KademliaStorageEntryMetadata> entriesRet = new ArrayList<>();

        for (List<KademliaStorageEntryMetadata> entrySet : this.entries.values())
        {
            if (entrySet.size() > 0)
            {
                entriesRet.addAll(entrySet);
            }
        }

        return entriesRet;
    }

    public void remove(KadContent content) throws ContentNotFoundException
    {
        this.remove(new StorageEntryMetadata(content));
    }

    public void remove(KademliaStorageEntryMetadata entry) throws ContentNotFoundException
    {
        if (contains(entry))
        {
            this.entries.get(entry.getKey()).remove(entry);
        }
        else
        {
            throw new ContentNotFoundException("This content does not exist in the Storage Entries");
        }
    }

    @Override
    public synchronized String toString()
    {
        StringBuilder sb = new StringBuilder("Stored Content: \n");
        int count = 0;
        for (List<KademliaStorageEntryMetadata> es : this.entries.values())
        {
            if (entries.size() < 1)
            {
                continue;
            }

            for (KademliaStorageEntryMetadata e : es)
            {
                sb.append(++count);
                sb.append(". ");
                sb.append(e);
                sb.append("\n");
            }
        }

        sb.append("\n");
        return sb.toString();
    }
}


================================================
FILE: src/kademlia/exceptions/ContentExistException.java
================================================
package kademlia.exceptions;

/**
 * An exception used to indicate that a content already exist on the DHT
 *
 * @author Joshua Kissoon
 * @created 20140322
 */
public class ContentExistException extends Exception
{

    public ContentExistException()
    {
        super();
    }

    public ContentExistException(String message)
    {
        super(message);
    }
}


================================================
FILE: src/kademlia/exceptions/ContentNotFoundException.java
================================================
package kademlia.exceptions;

/**
 * An exception used to indicate that a content does not exist on the DHT
 *
 * @author Joshua Kissoon
 * @created 20140322
 */
public class ContentNotFoundException extends Exception
{

    public ContentNotFoundException()
    {
        super();
    }

    public ContentNotFoundException(String message)
    {
        super(message);
    }
}


================================================
FILE: src/kademlia/exceptions/KadServerDownException.java
================================================
package kademlia.exceptions;

/**
 * An exception to be thrown whenever the Kad Server is down
 *
 * @author Joshua Kissoon
 * @created 20140428
 */
public class KadServerDownException extends RoutingException
{

    public KadServerDownException()
    {
        super();
    }

    public KadServerDownException(String message)
    {
        super(message);
    }
}


================================================
FILE: src/kademlia/exceptions/RoutingException.java
================================================
package kademlia.exceptions;

import java.io.IOException;

/**
 * An exception to be thrown whenever there is a routing problem
 *
 * @author Joshua Kissoon
 * @created 20140219
 */
public class RoutingException extends IOException
{

    public RoutingException()
    {
        super();
    }

    public RoutingException(String message)
    {
        super(message);
    }
}


================================================
FILE: src/kademlia/exceptions/UnknownMessageException.java
================================================
package kademlia.exceptions;

/**
 * An exception used to indicate an unknown message type or communication identifier
 *
 * @author Joshua Kissoon
 * @created 20140219
 */
public class UnknownMessageException extends RuntimeException
{

    public UnknownMessageException()
    {
        super();
    }

    public UnknownMessageException(String message)
    {
        super(message);
    }
}


================================================
FILE: src/kademlia/message/AcknowledgeMessage.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import kademlia.node.Node;

/**
 * A message used to acknowledge a request from a node; can be used in many situations.
 * - Mainly used to acknowledge a connect message
 *
 * @author Joshua Kissoon
 * @created 20140218
 */
public class AcknowledgeMessage implements Message
{

    private Node origin;
    public static final byte CODE = 0x01;

    public AcknowledgeMessage(Node origin)
    {
        this.origin = origin;
    }

    public AcknowledgeMessage(DataInputStream in) throws IOException
    {
        this.fromStream(in);
    }

    @Override
    public final void fromStream(DataInputStream in) throws IOException
    {
        this.origin = new Node(in);
    }

    @Override
    public void toStream(DataOutputStream out) throws IOException
    {
        origin.toStream(out);
    }

    public Node getOrigin()
    {
        return this.origin;
    }

    @Override
    public byte code()
    {
        return CODE;
    }

    @Override
    public String toString()
    {
        return "AcknowledgeMessage[origin=" + origin.getNodeId() + "]";
    }
}


================================================
FILE: src/kademlia/message/ConnectMessage.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import kademlia.node.Node;

/**
 * A message sent to another node requesting to connect to them.
 *
 * @author Joshua Kissoon
 * @created 20140218
 */
public class ConnectMessage implements Message
{

    private Node origin;
    public static final byte CODE = 0x02;

    public ConnectMessage(Node origin)
    {
        this.origin = origin;
    }

    public ConnectMessage(DataInputStream in) throws IOException
    {
        this.fromStream(in);
    }

    @Override
    public final void fromStream(DataInputStream in) throws IOException
    {
        this.origin = new Node(in);
    }

    @Override
    public void toStream(DataOutputStream out) throws IOException
    {
        origin.toStream(out);
    }

    public Node getOrigin()
    {
        return this.origin;
    }

    @Override
    public byte code()
    {
        return CODE;
    }

    @Override
    public String toString()
    {
        return "ConnectMessage[origin NodeId=" + origin.getNodeId() + "]";
    }
}


================================================
FILE: src/kademlia/message/ConnectReceiver.java
================================================
package kademlia.message;

import java.io.IOException;
import kademlia.KadServer;
import kademlia.KademliaNode;

/**
 * Receives a ConnectMessage and sends an AcknowledgeMessage as reply.
 *
 * @author Joshua Kissoon
 * @created 20140219
 */
public class ConnectReceiver implements Receiver
{

    private final KadServer server;
    private final KademliaNode localNode;

    public ConnectReceiver(KadServer server, KademliaNode local)
    {
        this.server = server;
        this.localNode = local;
    }

    /**
     * Handle receiving a ConnectMessage
     *
     * @param comm
     *
     * @throws java.io.IOException
     */
    @Override
    public void receive(Message incoming, int comm) throws IOException
    {
        ConnectMessage mess = (ConnectMessage) incoming;

        /* Update the local space by inserting the origin node. */
        this.localNode.getRoutingTable().insert(mess.getOrigin());

        /* Respond to the connect request */
        AcknowledgeMessage msg = new AcknowledgeMessage(this.localNode.getNode());

        /* Reply to the connect message with an Acknowledgement */
        this.server.reply(mess.getOrigin(), msg, comm);
    }

    /**
     * We don't need to do anything here
     *
     * @param comm
     *
     * @throws java.io.IOException
     */
    @Override
    public void timeout(int comm) throws IOException
    {
    }
}


================================================
FILE: src/kademlia/message/ContentLookupMessage.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import kademlia.dht.GetParameter;
import kademlia.node.Node;
import kademlia.util.serializer.JsonSerializer;

/**
 * Messages used to send to another node requesting content.
 *
 * @author Joshua Kissoon
 * @since 20140226
 */
public class ContentLookupMessage implements Message
{

    public static final byte CODE = 0x03;

    private Node origin;
    private GetParameter params;

    /**
     * @param origin The node where this lookup came from
     * @param params The parameters used to find the content
     */
    public ContentLookupMessage(Node origin, GetParameter params)
    {
        this.origin = origin;
        this.params = params;
    }

    public ContentLookupMessage(DataInputStream in) throws IOException
    {
        this.fromStream(in);
    }

    public GetParameter getParameters()
    {
        return this.params;
    }

    public Node getOrigin()
    {
        return this.origin;
    }

    @Override
    public void toStream(DataOutputStream out) throws IOException
    {
        this.origin.toStream(out);

        /* Write the params to the stream */
        new JsonSerializer<GetParameter>().write(this.params, out);
    }

    @Override
    public final void fromStream(DataInputStream in) throws IOException
    {
        this.origin = new Node(in);

        /* Read the params from the stream */
        try
        {
            this.params = new JsonSerializer<GetParameter>().read(in);
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public byte code()
    {
        return CODE;
    }

}


================================================
FILE: src/kademlia/message/ContentLookupReceiver.java
================================================
package kademlia.message;

import java.io.IOException;
import java.util.NoSuchElementException;
import kademlia.KadConfiguration;
import kademlia.KadServer;
import kademlia.KademliaNode;
import kademlia.dht.KademliaDHT;

/**
 * Responds to a ContentLookupMessage by sending a ContentMessage containing the requested content;
 * if the requested content is not found, a NodeReplyMessage containing the K closest nodes to the request key is sent.
 *
 * @author Joshua Kissoon
 * @since 20140226
 */
public class ContentLookupReceiver implements Receiver
{

    private final KadServer server;
    private final KademliaNode localNode;
    private final KademliaDHT dht;
    private final KadConfiguration config;

    public ContentLookupReceiver(KadServer server, KademliaNode localNode, KademliaDHT dht, KadConfiguration config)
    {
        this.server = server;
        this.localNode = localNode;
        this.dht = dht;
        this.config = config;
    }

    @Override
    public void receive(Message incoming, int comm) throws IOException
    {
        ContentLookupMessage msg = (ContentLookupMessage) incoming;
        this.localNode.getRoutingTable().insert(msg.getOrigin());

        /* Check if we can have this data */
        if (this.dht.contains(msg.getParameters()))
        {
            try
            {
                /* Return a ContentMessage with the required data */
                ContentMessage cMsg = new ContentMessage(localNode.getNode(), this.dht.get(msg.getParameters()));
                server.reply(msg.getOrigin(), cMsg, comm);
            }
            catch (NoSuchElementException ex)
            {
                /* @todo Not sure why this exception is thrown here, checkup the system when tests are writtem*/
            }
        }
        else
        {
            /**
             * Return a the K closest nodes to this content identifier
             * We create a NodeLookupReceiver and let this receiver handle this operation
             */
            NodeLookupMessage lkpMsg = new NodeLookupMessage(msg.getOrigin(), msg.getParameters().getKey());
            new NodeLookupReceiver(server, localNode, this.config).receive(lkpMsg, comm);
        }
    }

    @Override
    public void timeout(int comm)
    {

    }
}


================================================
FILE: src/kademlia/message/ContentMessage.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import kademlia.dht.JKademliaStorageEntry;
import kademlia.dht.KademliaStorageEntry;
import kademlia.node.Node;
import kademlia.util.serializer.JsonSerializer;

/**
 * A Message used to send content between nodes
 *
 * @author Joshua Kissoon
 * @since 20140226
 */
public class ContentMessage implements Message
{

    public static final byte CODE = 0x04;

    private JKademliaStorageEntry content;
    private Node origin;

    /**
     * @param origin  Where the message came from
     * @param content The content to be stored
     *
     */
    public ContentMessage(Node origin, JKademliaStorageEntry content)
    {
        this.content = content;
        this.origin = origin;
    }

    public ContentMessage(DataInputStream in) throws IOException
    {
        this.fromStream(in);
    }

    @Override
    public void toStream(DataOutputStream out) throws IOException
    {
        this.origin.toStream(out);

        /* Serialize the KadContent, then send it to the stream */
        new JsonSerializer<JKademliaStorageEntry>().write(content, out);
    }

    @Override
    public final void fromStream(DataInputStream in) throws IOException
    {
        this.origin = new Node(in);

        try
        {
            this.content = new JsonSerializer<JKademliaStorageEntry>().read(in);
        }
        catch (ClassNotFoundException e)
        {
            System.err.println("ClassNotFoundException when reading StorageEntry; Message: " + e.getMessage());
        }
    }

    public Node getOrigin()
    {
        return this.origin;
    }

    public JKademliaStorageEntry getContent()
    {
        return this.content;
    }

    @Override
    public byte code()
    {
        return CODE;
    }

    @Override
    public String toString()
    {
        return "ContentMessage[origin=" + origin + ",content=" + content + "]";
    }
}


================================================
FILE: src/kademlia/message/KademliaMessageFactory.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.IOException;
import kademlia.KadServer;

/**
 * A factory that handles creating messages and receivers
 *
 * @author Joshua Kissoon
 * @since 20140523
 */
public interface KademliaMessageFactory
{

    /**
     * Method that creates a message based on the code and input stream
     *
     * @param code The message code
     * @param in   An input stream with the message data
     *
     * @return A message
     *
     * @throws java.io.IOException
     */
    public Message createMessage(byte code, DataInputStream in) throws IOException;

    /**
     * Method that returns a receiver to handle a specific type of message
     *
     * @param code   The message code
     * @param server
     *
     * @return A receiver
     */
    public Receiver createReceiver(byte code, KadServer server);
}


================================================
FILE: src/kademlia/message/Message.java
================================================
package kademlia.message;

public interface Message extends Streamable
{

    /**
     * The unique code for the message type, used to differentiate all messages
     * from each other. Since this is of <code>byte</code> type there can
     * be at most 256 different message types.
     *
     * @return byte A unique code representing the message type
     * */
    public byte code();
}


================================================
FILE: src/kademlia/message/MessageFactory.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.IOException;
import kademlia.KadConfiguration;
import kademlia.KadServer;
import kademlia.KademliaNode;
import kademlia.dht.KademliaDHT;

/**
 * Handles creating messages and receivers
 *
 * @author Joshua Kissoon
 * @since 20140202
 */
public class MessageFactory implements KademliaMessageFactory
{

    private final KademliaNode localNode;
    private final KademliaDHT dht;
    private final KadConfiguration config;

    public MessageFactory(KademliaNode local, KademliaDHT dht, KadConfiguration config)
    {
        this.localNode = local;
        this.dht = dht;
        this.config = config;
    }

    @Override
    public Message createMessage(byte code, DataInputStream in) throws IOException
    {
        switch (code)
        {
            case AcknowledgeMessage.CODE:
                return new AcknowledgeMessage(in);
            case ConnectMessage.CODE:
                return new ConnectMessage(in);
            case ContentMessage.CODE:
                return new ContentMessage(in);
            case ContentLookupMessage.CODE:
                return new ContentLookupMessage(in);
            case NodeLookupMessage.CODE:
                return new NodeLookupMessage(in);
            case NodeReplyMessage.CODE:
                return new NodeReplyMessage(in);
            case SimpleMessage.CODE:
                return new SimpleMessage(in);
            case StoreContentMessage.CODE:
                return new StoreContentMessage(in);
            default:
                //System.out.println(this.localNode + " - No Message handler found for message. Code: " + code);
                return new SimpleMessage(in);

        }
    }

    @Override
    public Receiver createReceiver(byte code, KadServer server)
    {
        switch (code)
        {
            case ConnectMessage.CODE:
                return new ConnectReceiver(server, this.localNode);
            case ContentLookupMessage.CODE:
                return new ContentLookupReceiver(server, this.localNode, this.dht, this.config);
            case NodeLookupMessage.CODE:
                return new NodeLookupReceiver(server, this.localNode, this.config);
            case StoreContentMessage.CODE:
                return new StoreContentReceiver(server, this.localNode, this.dht);
            default:
                //System.out.println("No receiver found for message. Code: " + code);
                return new SimpleReceiver();
        }
    }
}


================================================
FILE: src/kademlia/message/NodeLookupMessage.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import kademlia.node.Node;
import kademlia.node.KademliaId;

/**
 * A message sent to other nodes requesting the K-Closest nodes to a key sent in this message.
 *
 * @author Joshua Kissoon
 * @created 20140218
 */
public class NodeLookupMessage implements Message
{

    private Node origin;
    private KademliaId lookupId;

    public static final byte CODE = 0x05;

    /**
     * A new NodeLookupMessage to find nodes
     *
     * @param origin The Node from which the message is coming from
     * @param lookup The key for which to lookup nodes for
     */
    public NodeLookupMessage(Node origin, KademliaId lookup)
    {
        this.origin = origin;
        this.lookupId = lookup;
    }

    public NodeLookupMessage(DataInputStream in) throws IOException
    {
        this.fromStream(in);
    }

    @Override
    public final void fromStream(DataInputStream in) throws IOException
    {
        this.origin = new Node(in);
        this.lookupId = new KademliaId(in);
    }

    @Override
    public void toStream(DataOutputStream out) throws IOException
    {
        this.origin.toStream(out);
        this.lookupId.toStream(out);
    }

    public Node getOrigin()
    {
        return this.origin;
    }

    public KademliaId getLookupId()
    {
        return this.lookupId;
    }

    @Override
    public byte code()
    {
        return CODE;
    }

    @Override
    public String toString()
    {
        return "NodeLookupMessage[origin=" + origin + ",lookup=" + lookupId + "]";
    }
}


================================================
FILE: src/kademlia/message/NodeLookupReceiver.java
================================================
package kademlia.message;

import java.io.IOException;
import java.util.List;
import kademlia.KadConfiguration;
import kademlia.KadServer;
import kademlia.KademliaNode;
import kademlia.node.Node;

/**
 * Receives a NodeLookupMessage and sends a NodeReplyMessage as reply with the K-Closest nodes to the ID sent.
 *
 * @author Joshua Kissoon
 * @created 20140219
 */
public class NodeLookupReceiver implements Receiver
{

    private final KadServer server;
    private final KademliaNode localNode;
    private final KadConfiguration config;

    public NodeLookupReceiver(KadServer server, KademliaNode local, KadConfiguration config)
    {
        this.server = server;
        this.localNode = local;
        this.config = config;
    }

    /**
     * Handle receiving a NodeLookupMessage
     * Find the set of K nodes closest to the lookup ID and return them
     *
     * @param comm
     *
     * @throws java.io.IOException
     */
    @Override
    public void receive(Message incoming, int comm) throws IOException
    {
        NodeLookupMessage msg = (NodeLookupMessage) incoming;

        Node origin = msg.getOrigin();

        /* Update the local space by inserting the origin node. */
        this.localNode.getRoutingTable().insert(origin);

        /* Find nodes closest to the LookupId */
        List<Node> nodes = this.localNode.getRoutingTable().findClosest(msg.getLookupId(), this.config.k());

        /* Respond to the NodeLookupMessage */
        Message reply = new NodeReplyMessage(this.localNode.getNode(), nodes);

        if (this.server.isRunning())
        {
            /* Let the Server send the reply */
            this.server.reply(origin, reply, comm);
        }
    }

    /**
     * We don't need to do anything here
     *
     * @param comm
     *
     * @throws java.io.IOException
     */
    @Override
    public void timeout(int comm) throws IOException
    {
    }
}


================================================
FILE: src/kademlia/message/NodeReplyMessage.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import kademlia.node.Node;

/**
 * A message used to connect nodes.
 * When a NodeLookup Request comes in, we respond with a NodeReplyMessage.
 *
 * @author Joshua Kissoon
 * @created 20140218
 */
public class NodeReplyMessage implements Message
{

    private Node origin;
    public static final byte CODE = 0x06;
    private List<Node> nodes;

    public NodeReplyMessage(Node origin, List<Node> nodes)
    {
        this.origin = origin;
        this.nodes = nodes;
    }

    public NodeReplyMessage(DataInputStream in) throws IOException
    {
        this.fromStream(in);
    }

    @Override
    public final void fromStream(DataInputStream in) throws IOException
    {
        /* Read in the origin */
        this.origin = new Node(in);

        /* Get the number of incoming nodes */
        int len = in.readInt();
        this.nodes = new ArrayList<>(len);

        /* Read in all nodes */
        for (int i = 0; i < len; i++)
        {
            this.nodes.add(new Node(in));
        }
    }

    @Override
    public void toStream(DataOutputStream out) throws IOException
    {
        /* Add the origin node to the stream */
        origin.toStream(out);

        /* Add all other nodes to the stream */
        int len = this.nodes.size();
        if (len > 255)
        {
            throw new IndexOutOfBoundsException("Too many nodes in list to send in NodeReplyMessage. Size: " + len);
        }

        /* Writing the nodes to the stream */
        out.writeInt(len);
        for (Node n : this.nodes)
        {
            n.toStream(out);
        }
    }

    public Node getOrigin()
    {
        return this.origin;
    }

    @Override
    public byte code()
    {
        return CODE;
    }

    public List<Node> getNodes()
    {
        return this.nodes;
    }

    @Override
    public String toString()
    {
        return "NodeReplyMessage[origin NodeId=" + origin.getNodeId() + "]";
    }
}


================================================
FILE: src/kademlia/message/Receiver.java
================================================
package kademlia.message;

import java.io.IOException;

/**
 * A receiver waits for incoming messages and perform some action when the message is received
 *
 * @author Joshua Kissoon
 * @created 20140218
 */
public interface Receiver
{

    /**
     * Message is received, now handle it
     *
     * @param conversationId The ID of this conversation, used for further conversations
     * @param incoming       The incoming
     *
     * @throws java.io.IOException
     */
    public void receive(Message incoming, int conversationId) throws IOException;

    /**
     * If no reply is received in <code>MessageServer.TIMEOUT</code> seconds for the
     * message with communication id <code>comm</code>, the MessageServer calls this method
     *
     * @param conversationId The conversation ID of this communication
     *
     * @throws IOException if an I/O error occurs
     * */
    public void timeout(int conversationId) throws IOException;
}


================================================
FILE: src/kademlia/message/SimpleMessage.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

/**
 * A simple message used for testing the system; Default message constructed if the message type sent is not available
 *
 * @author Joshua Kissoon
 * @created 20140217
 */
public class SimpleMessage implements Message
{

    /* Message constants */
    public static final byte CODE = 0x07;

    private String content;

    public SimpleMessage(String message)
    {
        this.content = message;
    }

    public SimpleMessage(DataInputStream in)
    {
        this.fromStream(in);
    }

    @Override
    public byte code()
    {
        return CODE;
    }

    @Override
    public void toStream(DataOutputStream out)
    {
        try
        {
            out.writeInt(this.content.length());
            out.writeBytes(this.content);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public final void fromStream(DataInputStream in)
    {
        try
        {
            byte[] buff = new byte[in.readInt()];
            in.readFully(buff);

            this.content = new String(buff);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public String toString()
    {
        return this.content;
    }
}


================================================
FILE: src/kademlia/message/SimpleReceiver.java
================================================
package kademlia.message;

import java.io.IOException;

/**
 * Default receiver if none other is called
 *
 * @author Joshua Kissoon
 * @created 20140202
 */
public class SimpleReceiver implements Receiver
{

    @Override
    public void receive(Message incoming, int conversationId)
    {
        //System.out.println("Received message: " + incoming);
    }

    @Override
    public void timeout(int conversationId) throws IOException
    {
        //System.out.println("SimpleReceiver message timeout.");
    }
}


================================================
FILE: src/kademlia/message/StoreContentMessage.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import kademlia.dht.JKademliaStorageEntry;
import kademlia.dht.KademliaStorageEntry;
import kademlia.node.Node;
import kademlia.util.serializer.JsonSerializer;

/**
 * A StoreContentMessage used to send a store message to a node
 *
 * @author Joshua Kissoon
 * @since 20140225
 */
public class StoreContentMessage implements Message
{

    public static final byte CODE = 0x08;

    private JKademliaStorageEntry content;
    private Node origin;

    /**
     * @param origin  Where the message came from
     * @param content The content to be stored
     *
     */
    public StoreContentMessage(Node origin, JKademliaStorageEntry content)
    {
        this.content = content;
        this.origin = origin;
    }

    public StoreContentMessage(DataInputStream in) throws IOException
    {
        this.fromStream(in);
    }

    @Override
    public void toStream(DataOutputStream out) throws IOException
    {
        this.origin.toStream(out);

        /* Serialize the KadContent, then send it to the stream */
        new JsonSerializer<JKademliaStorageEntry>().write(content, out);
    }

    @Override
    public final void fromStream(DataInputStream in) throws IOException
    {
        this.origin = new Node(in);
        try
        {
            this.content = new JsonSerializer<JKademliaStorageEntry>().read(in);
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }

    public Node getOrigin()
    {
        return this.origin;
    }

    public JKademliaStorageEntry getContent()
    {
        return this.content;
    }

    @Override
    public byte code()
    {
        return CODE;
    }

    @Override
    public String toString()
    {
        return "StoreContentMessage[origin=" + origin + ",content=" + content + "]";
    }
}


================================================
FILE: src/kademlia/message/StoreContentReceiver.java
================================================
package kademlia.message;

import java.io.IOException;
import kademlia.KadServer;
import kademlia.KademliaNode;
import kademlia.dht.KademliaDHT;

/**
 * Receiver for incoming StoreContentMessage
 *
 * @author Joshua Kissoon
 * @since 20140225
 */
public class StoreContentReceiver implements Receiver
{

    private final KadServer server;
    private final KademliaNode localNode;
    private final KademliaDHT dht;

    public StoreContentReceiver(KadServer server, KademliaNode localNode, KademliaDHT dht)
    {
        this.server = server;
        this.localNode = localNode;
        this.dht = dht;
    }

    @Override
    public void receive(Message incoming, int comm)
    {
        /* It's a StoreContentMessage we're receiving */
        StoreContentMessage msg = (StoreContentMessage) incoming;

        /* Insert the message sender into this node's routing table */
        this.localNode.getRoutingTable().insert(msg.getOrigin());

        try
        {
            /* Store this Content into the DHT */
            this.dht.store(msg.getContent());
        }
        catch (IOException e)
        {
            System.err.println("Unable to store received content; Message: " + e.getMessage());
        }

    }

    @Override
    public void timeout(int comm)
    {
        /**
         * This receiver only handles Receiving content when we've received the message,
         * so no timeout will happen with this receiver.
         */
    }
}


================================================
FILE: src/kademlia/message/Streamable.java
================================================
package kademlia.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

/**
 * A Streamable object is able to write it's state to an output stream and
 * a class implementing Streamable must be able to recreate an instance of
 * the class from an input stream. No information about class name is written
 * to the output stream so it must be known what class type is expected when
 * reading objects back in from an input stream. This gives a space
 * advantage over Serializable.
 * <p>
 * Since the exact class must be known anyway prior to reading, it is incouraged
 * that classes implementing Streamble also provide a constructor of the form:
 * <p>
 * <code>Streamable(DataInput in) throws IOException;</code>
 * */
public interface Streamable
{

    /**
     * Writes the internal state of the Streamable object to the output stream
     * in a format that can later be read by the same Streamble class using
     * the {@link #fromStream} method.
     *
     * @param out
     *
     * @throws java.io.IOException
     */
    public void toStream(DataOutputStream out) throws IOException;

    /**
     * Reads the internal state of the Streamable object from the input stream.
     *
     * @param out
     *
     * @throws java.io.IOException
     */
    public void fromStream(DataInputStream out) throws IOException;
}


================================================
FILE: src/kademlia/node/KademliaId.java
================================================
/**
 * @author Joshua Kissoon
 * @created 20140215
 * @desc Represents a Kademlia Node ID
 */
package kademlia.node;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Random;
import kademlia.message.Streamable;

public class KademliaId implements Streamable, Serializable
{

    public final transient static int ID_LENGTH = 160;
    private byte[] keyBytes;

    /**
     * Construct the NodeId from some string
     *
     * @param data The user generated key string
     */
    public KademliaId(String data)
    {
        keyBytes = data.getBytes();
        if (keyBytes.length != ID_LENGTH / 8)
        {
            throw new IllegalArgumentException("Specified Data need to be " + (ID_LENGTH / 8) + " characters long.");
        }
    }

    /**
     * Generate a random key
     */
    public KademliaId()
    {
        keyBytes = new byte[ID_LENGTH / 8];
        new Random().nextBytes(keyBytes);
    }

    /**
     * Generate the NodeId from a given byte[]
     *
     * @param bytes
     */
    public KademliaId(byte[] bytes)
    {
        if (bytes.length != ID_LENGTH / 8)
        {
            throw new IllegalArgumentException("Specified Data need to be " + (ID_LENGTH / 8) + " characters long. Data Given: '" + new String(bytes) + "'");
        }
        this.keyBytes = bytes;
    }

    /**
     * Load the NodeId from a DataInput stream
     *
     * @param in The stream from which to load the NodeId
     *
     * @throws IOException
     */
    public KademliaId(DataInputStream in) throws IOException
    {
        this.fromStream(in);
    }

    public byte[] getBytes()
    {
        return this.keyBytes;
    }

    /**
     * @return The BigInteger representation of the key
     */
    public BigInteger getInt()
    {
        return new BigInteger(1, this.getBytes());
    }

    /**
     * Compares a NodeId to this NodeId
     *
     * @param o The NodeId to compare to this NodeId
     *
     * @return boolean Whether the 2 NodeIds are equal
     */
    @Override
    public boolean equals(Object o)
    {
        if (o instanceof KademliaId)
        {
            KademliaId nid = (KademliaId) o;
            return this.hashCode() == nid.hashCode();
        }
        return false;
    }

    @Override
    public int hashCode()
    {
        int hash = 7;
        hash = 83 * hash + Arrays.hashCode(this.keyBytes);
        return hash;
    }

    /**
     * Checks the distance between this and another NodeId
     *
     * @param nid
     *
     * @return The distance of this NodeId from the given NodeId
     */
    public KademliaId xor(KademliaId nid)
    {
        byte[] result = new byte[ID_LENGTH / 8];
        byte[] nidBytes = nid.getBytes();

        for (int i = 0; i < ID_LENGTH / 8; i++)
        {
            result[i] = (byte) (this.keyBytes[i] ^ nidBytes[i]);
        }

        KademliaId resNid = new KademliaId(result);

        return resNid;
    }

    /**
     * Generates a NodeId that is some distance away from this NodeId
     *
     * @param distance in number of bits
     *
     * @return NodeId The newly generated NodeId
     */
    public KademliaId generateNodeIdByDistance(int distance)
    {
        byte[] result = new byte[ID_LENGTH / 8];

        /* Since distance = ID_LENGTH - prefixLength, we need to fill that amount with 0's */
        int numByteZeroes = (ID_LENGTH - distance) / 8;
        int numBitZeroes = 8 - (distance % 8);

        /* Filling by
Download .txt
gitextract_uwntm7qj/

├── .gitignore
├── LICENSE
├── README.md
├── build.xml
├── manifest.mf
├── nbproject/
│   ├── build-impl.xml
│   ├── genfiles.properties
│   ├── project.properties
│   └── project.xml
└── src/
    └── kademlia/
        ├── DefaultConfiguration.java
        ├── JKademliaNode.java
        ├── KadConfiguration.java
        ├── KadServer.java
        ├── KadStatistician.java
        ├── KademliaNode.java
        ├── Statistician.java
        ├── Todo
        ├── dht/
        │   ├── DHT.java
        │   ├── GetParameter.java
        │   ├── JKademliaStorageEntry.java
        │   ├── KadContent.java
        │   ├── KademliaDHT.java
        │   ├── KademliaStorageEntry.java
        │   ├── KademliaStorageEntryMetadata.java
        │   ├── StorageEntryMetadata.java
        │   └── StoredContentManager.java
        ├── exceptions/
        │   ├── ContentExistException.java
        │   ├── ContentNotFoundException.java
        │   ├── KadServerDownException.java
        │   ├── RoutingException.java
        │   └── UnknownMessageException.java
        ├── message/
        │   ├── AcknowledgeMessage.java
        │   ├── ConnectMessage.java
        │   ├── ConnectReceiver.java
        │   ├── ContentLookupMessage.java
        │   ├── ContentLookupReceiver.java
        │   ├── ContentMessage.java
        │   ├── KademliaMessageFactory.java
        │   ├── Message.java
        │   ├── MessageFactory.java
        │   ├── NodeLookupMessage.java
        │   ├── NodeLookupReceiver.java
        │   ├── NodeReplyMessage.java
        │   ├── Receiver.java
        │   ├── SimpleMessage.java
        │   ├── SimpleReceiver.java
        │   ├── StoreContentMessage.java
        │   ├── StoreContentReceiver.java
        │   └── Streamable.java
        ├── node/
        │   ├── KademliaId.java
        │   ├── KeyComparator.java
        │   └── Node.java
        ├── operation/
        │   ├── BucketRefreshOperation.java
        │   ├── ConnectOperation.java
        │   ├── ContentLookupOperation.java
        │   ├── ContentRefreshOperation.java
        │   ├── KadRefreshOperation.java
        │   ├── NodeLookupOperation.java
        │   ├── Operation.java
        │   ├── PingOperation.java
        │   └── StoreOperation.java
        ├── routing/
        │   ├── Contact.java
        │   ├── ContactLastSeenComparator.java
        │   ├── JKademliaBucket.java
        │   ├── JKademliaRoutingTable.java
        │   ├── KademliaBucket.java
        │   └── KademliaRoutingTable.java
        ├── simulations/
        │   ├── AutoRefreshOperation.java
        │   ├── AutoRefreshOperation2.java
        │   ├── ContentSendingTest.java
        │   ├── ContentUpdatingTest.java
        │   ├── DHTContentImpl.java
        │   ├── NodeConnectionTest.java
        │   ├── RefreshOperationTest.java
        │   ├── RoutingTableSimulation.java
        │   ├── RoutingTableStateTesting.java
        │   ├── SaveStateTest.java
        │   ├── SaveStateTest2.java
        │   ├── SimpleMessageTest.java
        │   └── Simulation.java
        └── util/
            ├── HashCalculator.java
            ├── RouteLengthChecker.java
            └── serializer/
                ├── JsonDHTSerializer.java
                ├── JsonRoutingTableSerializer.java
                ├── JsonSerializer.java
                └── KadSerializer.java
Download .txt
SYMBOL INDEX (531 symbols across 76 files)

FILE: src/kademlia/DefaultConfiguration.java
  class DefaultConfiguration (line 10) | public class DefaultConfiguration implements KadConfiguration
    method DefaultConfiguration (line 27) | public DefaultConfiguration()
    method restoreInterval (line 32) | @Override
    method responseTimeout (line 38) | @Override
    method operationTimeout (line 44) | @Override
    method maxConcurrentMessagesTransiting (line 50) | @Override
    method k (line 56) | @Override
    method replacementCacheSize (line 62) | @Override
    method stale (line 68) | @Override
    method getNodeDataFolder (line 74) | @Override
    method isTesting (line 96) | @Override

FILE: src/kademlia/JKademliaNode.java
  class JKademliaNode (line 46) | public class JKademliaNode implements KademliaNode
    method JKademliaNode (line 92) | public JKademliaNode(String ownerId, Node localNode, int udpPort, Kade...
    method startRefreshOperation (line 105) | @Override
    method stopRefreshOperation (line 128) | @Override
    method JKademliaNode (line 137) | public JKademliaNode(String ownerId, Node node, int udpPort, KademliaR...
    method JKademliaNode (line 149) | public JKademliaNode(String ownerId, Node node, int udpPort, KadConfig...
    method JKademliaNode (line 160) | public JKademliaNode(String ownerId, KademliaId defaultId, int udpPort...
    method loadFromFile (line 180) | public static JKademliaNode loadFromFile(String ownerId) throws FileNo...
    method loadFromFile (line 196) | public static JKademliaNode loadFromFile(String ownerId, KadConfigurat...
    method getNode (line 228) | @Override
    method getServer (line 234) | @Override
    method getDHT (line 240) | @Override
    method getCurrentConfiguration (line 246) | @Override
    method bootstrap (line 252) | @Override
    method put (line 262) | @Override
    method put (line 268) | @Override
    method putLocally (line 278) | @Override
    method get (line 284) | @Override
    method refresh (line 302) | @Override
    method getOwnerId (line 308) | @Override
    method getPort (line 314) | @Override
    method shutdown (line 320) | @Override
    method saveKadState (line 336) | @Override
    method getStateStorageFolderName (line 374) | private static String getStateStorageFolderName(String ownerId, KadCon...
    method getRoutingTable (line 386) | @Override
    method getStatistician (line 392) | @Override
    method toString (line 403) | @Override

FILE: src/kademlia/KadConfiguration.java
  type KadConfiguration (line 9) | public interface KadConfiguration
    method restoreInterval (line 15) | public long restoreInterval();
    method responseTimeout (line 23) | public long responseTimeout();
    method operationTimeout (line 28) | public long operationTimeout();
    method maxConcurrentMessagesTransiting (line 33) | public int maxConcurrentMessagesTransiting();
    method k (line 38) | public int k();
    method replacementCacheSize (line 43) | public int replacementCacheSize();
    method stale (line 48) | public int stale();
    method getNodeDataFolder (line 57) | public String getNodeDataFolder(String ownerId);
    method isTesting (line 62) | public boolean isTesting();

FILE: src/kademlia/KadServer.java
  class KadServer (line 29) | public class KadServer
    method KadServer (line 71) | public KadServer(int udpPort, KademliaMessageFactory mFactory, Node lo...
    method startListener (line 86) | private void startListener()
    method sendMessage (line 110) | public synchronized int sendMessage(Node to, Message msg, Receiver rec...
    method reply (line 152) | public synchronized void reply(Node to, Message msg, int comm) throws ...
    method sendMessage (line 164) | private void sendMessage(Node to, Message msg, int comm) throws IOExce...
    method listen (line 195) | private void listen()
    method unregister (line 290) | private synchronized void unregister(int comm)
    method shutdown (line 299) | public synchronized void shutdown()
    class TimeoutTask (line 312) | class TimeoutTask extends TimerTask
      method TimeoutTask (line 318) | public TimeoutTask(int comm, Receiver recv)
      method run (line 324) | @Override
    method printReceivers (line 344) | public void printReceivers()
    method isRunning (line 352) | public boolean isRunning()

FILE: src/kademlia/KadStatistician.java
  type KadStatistician (line 11) | public interface KadStatistician
    method sentData (line 19) | public void sentData(long size);
    method getTotalDataSent (line 24) | public long getTotalDataSent();
    method receivedData (line 31) | public void receivedData(long size);
    method getTotalDataReceived (line 36) | public long getTotalDataReceived();
    method setBootstrapTime (line 43) | public void setBootstrapTime(long time);
    method getBootstrapTime (line 48) | public long getBootstrapTime();
    method addContentLookup (line 57) | public void addContentLookup(long time, int routeLength, boolean isSuc...
    method numContentLookups (line 62) | public int numContentLookups();
    method numFailedContentLookups (line 67) | public int numFailedContentLookups();
    method totalContentLookupTime (line 72) | public long totalContentLookupTime();
    method averageContentLookupTime (line 79) | public double averageContentLookupTime();
    method averageContentLookupRouteLength (line 86) | public double averageContentLookupRouteLength();

FILE: src/kademlia/KademliaNode.java
  type KademliaNode (line 22) | public interface KademliaNode
    method startRefreshOperation (line 28) | public void startRefreshOperation();
    method stopRefreshOperation (line 33) | public void stopRefreshOperation();
    method getNode (line 38) | public Node getNode();
    method getServer (line 43) | public KadServer getServer();
    method getDHT (line 48) | public KademliaDHT getDHT();
    method getCurrentConfiguration (line 53) | public KadConfiguration getCurrentConfiguration();
    method bootstrap (line 64) | public void bootstrap(Node n) throws IOException, RoutingException;
    method put (line 77) | public int put(KadContent content) throws IOException;
    method put (line 90) | public int put(JKademliaStorageEntry entry) throws IOException;
    method putLocally (line 99) | public void putLocally(KadContent content) throws IOException;
    method get (line 111) | public JKademliaStorageEntry get(GetParameter param) throws NoSuchElem...
    method refresh (line 118) | public void refresh() throws IOException;
    method getOwnerId (line 123) | public String getOwnerId();
    method getPort (line 128) | public int getPort();
    method shutdown (line 137) | public void shutdown(final boolean saveState) throws IOException;
    method saveKadState (line 144) | public void saveKadState() throws IOException;
    method getRoutingTable (line 149) | public KademliaRoutingTable getRoutingTable();
    method getStatistician (line 154) | public KadStatistician getStatistician();

FILE: src/kademlia/Statistician.java
  class Statistician (line 13) | public class Statistician implements KadStatistician
    method sentData (line 38) | @Override
    method getTotalDataSent (line 45) | @Override
    method receivedData (line 56) | @Override
    method getTotalDataReceived (line 63) | @Override
    method setBootstrapTime (line 73) | @Override
    method getBootstrapTime (line 79) | @Override
    method addContentLookup (line 85) | @Override
    method numContentLookups (line 100) | @Override
    method numFailedContentLookups (line 106) | @Override
    method totalContentLookupTime (line 112) | @Override
    method averageContentLookupTime (line 118) | @Override
    method averageContentLookupRouteLength (line 131) | @Override
    method toString (line 143) | @Override

FILE: src/kademlia/dht/DHT.java
  class DHT (line 25) | public class DHT implements KademliaDHT
    method DHT (line 34) | public DHT(String ownerId, KadConfiguration config)
    method initialize (line 41) | @Override
    method setConfiguration (line 47) | @Override
    method getSerializer (line 53) | @Override
    method store (line 64) | @Override
    method store (line 126) | @Override
    method retrieve (line 132) | @Override
    method contains (line 140) | @Override
    method get (line 146) | @Override
    method get (line 166) | @Override
    method remove (line 188) | @Override
    method remove (line 194) | @Override
    method getContentStorageFolderName (line 219) | private String getContentStorageFolderName(KademliaId key)
    method getStorageEntries (line 238) | @Override
    method putStorageEntries (line 244) | @Override
    method toString (line 260) | @Override

FILE: src/kademlia/dht/GetParameter.java
  class GetParameter (line 15) | public class GetParameter
    method GetParameter (line 28) | public GetParameter(KademliaId key, String type)
    method GetParameter (line 41) | public GetParameter(KademliaId key, String type, String owner)
    method GetParameter (line 52) | public GetParameter(KadContent c)
    method GetParameter (line 72) | public GetParameter(KademliaStorageEntryMetadata md)
    method getKey (line 87) | public KademliaId getKey()
    method setOwnerId (line 92) | public void setOwnerId(String ownerId)
    method getOwnerId (line 97) | public String getOwnerId()
    method setType (line 102) | public void setType(String type)
    method getType (line 107) | public String getType()
    method toString (line 112) | @Override

FILE: src/kademlia/dht/JKademliaStorageEntry.java
  class JKademliaStorageEntry (line 9) | public class JKademliaStorageEntry implements KademliaStorageEntry
    method JKademliaStorageEntry (line 15) | public JKademliaStorageEntry(final KadContent content)
    method JKademliaStorageEntry (line 20) | public JKademliaStorageEntry(final KadContent content, final StorageEn...
    method setContent (line 26) | @Override
    method getContent (line 32) | @Override
    method getContentMetadata (line 38) | @Override
    method toString (line 44) | @Override

FILE: src/kademlia/dht/KadContent.java
  type KadContent (line 12) | public interface KadContent
    method getKey (line 18) | public KademliaId getKey();
    method getType (line 23) | public String getType();
    method getCreatedTimestamp (line 31) | public long getCreatedTimestamp();
    method getLastUpdatedTimestamp (line 39) | public long getLastUpdatedTimestamp();
    method getOwnerId (line 44) | public String getOwnerId();
    method toSerializedForm (line 55) | public byte[] toSerializedForm();
    method fromSerializedForm (line 64) | public KadContent fromSerializedForm(byte[] data);

FILE: src/kademlia/dht/KademliaDHT.java
  type KademliaDHT (line 18) | public interface KademliaDHT
    method initialize (line 24) | public void initialize();
    method setConfiguration (line 31) | public void setConfiguration(KadConfiguration con);
    method getSerializer (line 38) | public KadSerializer<JKademliaStorageEntry> getSerializer();
    method store (line 49) | public boolean store(JKademliaStorageEntry content) throws IOException;
    method store (line 51) | public boolean store(KadContent content) throws IOException;
    method retrieve (line 64) | public JKademliaStorageEntry retrieve(KademliaId key, int hashCode) th...
    method contains (line 73) | public boolean contains(GetParameter param);
    method get (line 84) | public JKademliaStorageEntry get(KademliaStorageEntryMetadata entry) t...
    method get (line 95) | public JKademliaStorageEntry get(GetParameter param) throws NoSuchElem...
    method remove (line 105) | public void remove(KadContent content) throws ContentNotFoundException;
    method remove (line 107) | public void remove(KademliaStorageEntryMetadata entry) throws ContentN...
    method getStorageEntries (line 112) | public List<KademliaStorageEntryMetadata> getStorageEntries();
    method putStorageEntries (line 120) | public void putStorageEntries(List<KademliaStorageEntryMetadata> ientr...

FILE: src/kademlia/dht/KademliaStorageEntry.java
  type KademliaStorageEntry (line 9) | public interface KademliaStorageEntry
    method setContent (line 17) | public void setContent(final byte[] data);
    method getContent (line 24) | public byte[] getContent();
    method getContentMetadata (line 31) | public KademliaStorageEntryMetadata getContentMetadata();

FILE: src/kademlia/dht/KademliaStorageEntryMetadata.java
  type KademliaStorageEntryMetadata (line 12) | public interface KademliaStorageEntryMetadata
    method getKey (line 18) | public KademliaId getKey();
    method getOwnerId (line 23) | public String getOwnerId();
    method getType (line 28) | public String getType();
    method getContentHash (line 33) | public int getContentHash();
    method getLastUpdatedTimestamp (line 38) | public long getLastUpdatedTimestamp();
    method satisfiesParameters (line 48) | public boolean satisfiesParameters(GetParameter params);
    method lastRepublished (line 53) | public long lastRepublished();
    method updateLastRepublished (line 58) | public void updateLastRepublished();

FILE: src/kademlia/dht/StorageEntryMetadata.java
  class StorageEntryMetadata (line 13) | public class StorageEntryMetadata implements KademliaStorageEntryMetadata
    method StorageEntryMetadata (line 25) | public StorageEntryMetadata(KadContent content)
    method getKey (line 36) | @Override
    method getOwnerId (line 42) | @Override
    method getType (line 48) | @Override
    method getContentHash (line 54) | @Override
    method getLastUpdatedTimestamp (line 60) | @Override
    method satisfiesParameters (line 74) | @Override
    method lastRepublished (line 98) | @Override
    method updateLastRepublished (line 107) | @Override
    method equals (line 113) | @Override
    method hashCode (line 124) | @Override
    method toString (line 134) | @Override

FILE: src/kademlia/dht/StoredContentManager.java
  class StoredContentManager (line 20) | class StoredContentManager
    method put (line 35) | public KademliaStorageEntryMetadata put(KadContent content) throws Con...
    method put (line 45) | public KademliaStorageEntryMetadata put(KademliaStorageEntryMetadata e...
    method contains (line 72) | public synchronized boolean contains(GetParameter param)
    method contains (line 95) | public synchronized boolean contains(KadContent content)
    method contains (line 103) | public synchronized boolean contains(KademliaStorageEntryMetadata entry)
    method get (line 115) | public KademliaStorageEntryMetadata get(GetParameter param) throws NoS...
    method get (line 138) | public KademliaStorageEntryMetadata get(KademliaStorageEntryMetadata md)
    method getAllEntries (line 146) | public synchronized List<KademliaStorageEntryMetadata> getAllEntries()
    method remove (line 161) | public void remove(KadContent content) throws ContentNotFoundException
    method remove (line 166) | public void remove(KademliaStorageEntryMetadata entry) throws ContentN...
    method toString (line 178) | @Override

FILE: src/kademlia/exceptions/ContentExistException.java
  class ContentExistException (line 9) | public class ContentExistException extends Exception
    method ContentExistException (line 12) | public ContentExistException()
    method ContentExistException (line 17) | public ContentExistException(String message)

FILE: src/kademlia/exceptions/ContentNotFoundException.java
  class ContentNotFoundException (line 9) | public class ContentNotFoundException extends Exception
    method ContentNotFoundException (line 12) | public ContentNotFoundException()
    method ContentNotFoundException (line 17) | public ContentNotFoundException(String message)

FILE: src/kademlia/exceptions/KadServerDownException.java
  class KadServerDownException (line 9) | public class KadServerDownException extends RoutingException
    method KadServerDownException (line 12) | public KadServerDownException()
    method KadServerDownException (line 17) | public KadServerDownException(String message)

FILE: src/kademlia/exceptions/RoutingException.java
  class RoutingException (line 11) | public class RoutingException extends IOException
    method RoutingException (line 14) | public RoutingException()
    method RoutingException (line 19) | public RoutingException(String message)

FILE: src/kademlia/exceptions/UnknownMessageException.java
  class UnknownMessageException (line 9) | public class UnknownMessageException extends RuntimeException
    method UnknownMessageException (line 12) | public UnknownMessageException()
    method UnknownMessageException (line 17) | public UnknownMessageException(String message)

FILE: src/kademlia/message/AcknowledgeMessage.java
  class AcknowledgeMessage (line 15) | public class AcknowledgeMessage implements Message
    method AcknowledgeMessage (line 21) | public AcknowledgeMessage(Node origin)
    method AcknowledgeMessage (line 26) | public AcknowledgeMessage(DataInputStream in) throws IOException
    method fromStream (line 31) | @Override
    method toStream (line 37) | @Override
    method getOrigin (line 43) | public Node getOrigin()
    method code (line 48) | @Override
    method toString (line 54) | @Override

FILE: src/kademlia/message/ConnectMessage.java
  class ConnectMessage (line 14) | public class ConnectMessage implements Message
    method ConnectMessage (line 20) | public ConnectMessage(Node origin)
    method ConnectMessage (line 25) | public ConnectMessage(DataInputStream in) throws IOException
    method fromStream (line 30) | @Override
    method toStream (line 36) | @Override
    method getOrigin (line 42) | public Node getOrigin()
    method code (line 47) | @Override
    method toString (line 53) | @Override

FILE: src/kademlia/message/ConnectReceiver.java
  class ConnectReceiver (line 13) | public class ConnectReceiver implements Receiver
    method ConnectReceiver (line 19) | public ConnectReceiver(KadServer server, KademliaNode local)
    method receive (line 32) | @Override
    method timeout (line 54) | @Override

FILE: src/kademlia/message/ContentLookupMessage.java
  class ContentLookupMessage (line 16) | public class ContentLookupMessage implements Message
    method ContentLookupMessage (line 28) | public ContentLookupMessage(Node origin, GetParameter params)
    method ContentLookupMessage (line 34) | public ContentLookupMessage(DataInputStream in) throws IOException
    method getParameters (line 39) | public GetParameter getParameters()
    method getOrigin (line 44) | public Node getOrigin()
    method toStream (line 49) | @Override
    method fromStream (line 58) | @Override
    method code (line 74) | @Override

FILE: src/kademlia/message/ContentLookupReceiver.java
  class ContentLookupReceiver (line 17) | public class ContentLookupReceiver implements Receiver
    method ContentLookupReceiver (line 25) | public ContentLookupReceiver(KadServer server, KademliaNode localNode,...
    method receive (line 33) | @Override
    method timeout (line 64) | @Override

FILE: src/kademlia/message/ContentMessage.java
  class ContentMessage (line 17) | public class ContentMessage implements Message
    method ContentMessage (line 30) | public ContentMessage(Node origin, JKademliaStorageEntry content)
    method ContentMessage (line 36) | public ContentMessage(DataInputStream in) throws IOException
    method toStream (line 41) | @Override
    method fromStream (line 50) | @Override
    method getOrigin (line 65) | public Node getOrigin()
    method getContent (line 70) | public JKademliaStorageEntry getContent()
    method code (line 75) | @Override
    method toString (line 81) | @Override

FILE: src/kademlia/message/KademliaMessageFactory.java
  type KademliaMessageFactory (line 13) | public interface KademliaMessageFactory
    method createMessage (line 26) | public Message createMessage(byte code, DataInputStream in) throws IOE...
    method createReceiver (line 36) | public Receiver createReceiver(byte code, KadServer server);

FILE: src/kademlia/message/Message.java
  type Message (line 3) | public interface Message extends Streamable
    method code (line 13) | public byte code();

FILE: src/kademlia/message/MessageFactory.java
  class MessageFactory (line 16) | public class MessageFactory implements KademliaMessageFactory
    method MessageFactory (line 23) | public MessageFactory(KademliaNode local, KademliaDHT dht, KadConfigur...
    method createMessage (line 30) | @Override
    method createReceiver (line 58) | @Override

FILE: src/kademlia/message/NodeLookupMessage.java
  class NodeLookupMessage (line 15) | public class NodeLookupMessage implements Message
    method NodeLookupMessage (line 29) | public NodeLookupMessage(Node origin, KademliaId lookup)
    method NodeLookupMessage (line 35) | public NodeLookupMessage(DataInputStream in) throws IOException
    method fromStream (line 40) | @Override
    method toStream (line 47) | @Override
    method getOrigin (line 54) | public Node getOrigin()
    method getLookupId (line 59) | public KademliaId getLookupId()
    method code (line 64) | @Override
    method toString (line 70) | @Override

FILE: src/kademlia/message/NodeLookupReceiver.java
  class NodeLookupReceiver (line 16) | public class NodeLookupReceiver implements Receiver
    method NodeLookupReceiver (line 23) | public NodeLookupReceiver(KadServer server, KademliaNode local, KadCon...
    method receive (line 38) | @Override
    method timeout (line 68) | @Override

FILE: src/kademlia/message/NodeReplyMessage.java
  class NodeReplyMessage (line 17) | public class NodeReplyMessage implements Message
    method NodeReplyMessage (line 24) | public NodeReplyMessage(Node origin, List<Node> nodes)
    method NodeReplyMessage (line 30) | public NodeReplyMessage(DataInputStream in) throws IOException
    method fromStream (line 35) | @Override
    method toStream (line 52) | @Override
    method getOrigin (line 73) | public Node getOrigin()
    method code (line 78) | @Override
    method getNodes (line 84) | public List<Node> getNodes()
    method toString (line 89) | @Override

FILE: src/kademlia/message/Receiver.java
  type Receiver (line 11) | public interface Receiver
    method receive (line 22) | public void receive(Message incoming, int conversationId) throws IOExc...
    method timeout (line 32) | public void timeout(int conversationId) throws IOException;

FILE: src/kademlia/message/SimpleMessage.java
  class SimpleMessage (line 13) | public class SimpleMessage implements Message
    method SimpleMessage (line 21) | public SimpleMessage(String message)
    method SimpleMessage (line 26) | public SimpleMessage(DataInputStream in)
    method code (line 31) | @Override
    method toStream (line 37) | @Override
    method fromStream (line 51) | @Override
    method toString (line 67) | @Override

FILE: src/kademlia/message/SimpleReceiver.java
  class SimpleReceiver (line 11) | public class SimpleReceiver implements Receiver
    method receive (line 14) | @Override
    method timeout (line 20) | @Override

FILE: src/kademlia/message/StoreContentMessage.java
  class StoreContentMessage (line 17) | public class StoreContentMessage implements Message
    method StoreContentMessage (line 30) | public StoreContentMessage(Node origin, JKademliaStorageEntry content)
    method StoreContentMessage (line 36) | public StoreContentMessage(DataInputStream in) throws IOException
    method toStream (line 41) | @Override
    method fromStream (line 50) | @Override
    method getOrigin (line 64) | public Node getOrigin()
    method getContent (line 69) | public JKademliaStorageEntry getContent()
    method code (line 74) | @Override
    method toString (line 80) | @Override

FILE: src/kademlia/message/StoreContentReceiver.java
  class StoreContentReceiver (line 14) | public class StoreContentReceiver implements Receiver
    method StoreContentReceiver (line 21) | public StoreContentReceiver(KadServer server, KademliaNode localNode, ...
    method receive (line 28) | @Override
    method timeout (line 49) | @Override

FILE: src/kademlia/message/Streamable.java
  type Streamable (line 20) | public interface Streamable
    method toStream (line 32) | public void toStream(DataOutputStream out) throws IOException;
    method fromStream (line 41) | public void fromStream(DataInputStream out) throws IOException;

FILE: src/kademlia/node/KademliaId.java
  class KademliaId (line 18) | public class KademliaId implements Streamable, Serializable
    method KademliaId (line 29) | public KademliaId(String data)
    method KademliaId (line 41) | public KademliaId()
    method KademliaId (line 52) | public KademliaId(byte[] bytes)
    method KademliaId (line 68) | public KademliaId(DataInputStream in) throws IOException
    method getBytes (line 73) | public byte[] getBytes()
    method getInt (line 81) | public BigInteger getInt()
    method equals (line 93) | @Override
    method hashCode (line 104) | @Override
    method xor (line 119) | public KademliaId xor(KademliaId nid)
    method generateNodeIdByDistance (line 141) | public KademliaId generateNodeIdByDistance(int distance)
    method getFirstSetBitIndex (line 181) | public int getFirstSetBitIndex()
    method getDistance (line 225) | public int getDistance(KademliaId to)
    method toStream (line 235) | @Override
    method fromStream (line 242) | @Override
    method hexRepresentation (line 250) | public String hexRepresentation()
    method toString (line 257) | @Override

FILE: src/kademlia/node/KeyComparator.java
  class KeyComparator (line 12) | public class KeyComparator implements Comparator<Node>
    method KeyComparator (line 20) | public KeyComparator(KademliaId key)
    method compare (line 33) | @Override

FILE: src/kademlia/node/Node.java
  class Node (line 18) | public class Node implements Streamable, Serializable
    method Node (line 26) | public Node(KademliaId nid, InetAddress ip, int port)
    method Node (line 41) | public Node(DataInputStream in) throws IOException
    method setInetAddress (line 52) | public void setInetAddress(InetAddress addr)
    method getNodeId (line 60) | public KademliaId getNodeId()
    method getSocketAddress (line 70) | public InetSocketAddress getSocketAddress()
    method toStream (line 75) | @Override
    method fromStream (line 93) | @Override
    method equals (line 108) | @Override
    method hashCode (line 123) | @Override
    method toString (line 129) | @Override

FILE: src/kademlia/operation/BucketRefreshOperation.java
  class BucketRefreshOperation (line 16) | public class BucketRefreshOperation implements Operation
    method BucketRefreshOperation (line 23) | public BucketRefreshOperation(KadServer server, KademliaNode localNode...
    method execute (line 40) | @Override

FILE: src/kademlia/operation/ConnectOperation.java
  class ConnectOperation (line 20) | public class ConnectOperation implements Operation, Receiver
    method ConnectOperation (line 39) | public ConnectOperation(KadServer server, KademliaNode local, Node boo...
    method execute (line 47) | @Override
    method receive (line 103) | @Override
    method timeout (line 127) | @Override

FILE: src/kademlia/operation/ContentLookupOperation.java
  class ContentLookupOperation (line 36) | public class ContentLookupOperation implements Operation, Receiver
    method ContentLookupOperation (line 77) | public ContentLookupOperation(KadServer server, JKademliaNode localNod...
    method execute (line 98) | @Override
    method addNodes (line 146) | public void addNodes(List<Node> list)
    method askNodesorFinish (line 169) | private boolean askNodesorFinish() throws IOException
    method closestNodesNotFailed (line 215) | private List<Node> closestNodesNotFailed(Byte status)
    method receive (line 240) | @Override
    method timeout (line 292) | @Override
    method isContentFound (line 314) | public boolean isContentFound()
    method getContentFound (line 324) | public JKademliaStorageEntry getContentFound() throws ContentNotFoundE...
    method routeLength (line 339) | public int routeLength()

FILE: src/kademlia/operation/ContentRefreshOperation.java
  class ContentRefreshOperation (line 22) | public class ContentRefreshOperation implements Operation
    method ContentRefreshOperation (line 30) | public ContentRefreshOperation(KadServer server, KademliaNode localNod...
    method execute (line 46) | @Override

FILE: src/kademlia/operation/KadRefreshOperation.java
  class KadRefreshOperation (line 15) | public class KadRefreshOperation implements Operation
    method KadRefreshOperation (line 23) | public KadRefreshOperation(KadServer server, KademliaNode localNode, K...
    method execute (line 31) | @Override

FILE: src/kademlia/operation/NodeLookupOperation.java
  class NodeLookupOperation (line 30) | public class NodeLookupOperation implements Operation, Receiver
    method NodeLookupOperation (line 63) | public NodeLookupOperation(KadServer server, KademliaNode localNode, K...
    method execute (line 83) | @Override
    method getClosestNodes (line 123) | public List<Node> getClosestNodes()
    method addNodes (line 133) | public void addNodes(List<Node> list)
    method askNodesorFinish (line 156) | private boolean askNodesorFinish() throws IOException
    method closestNodes (line 196) | private List<Node> closestNodes(String status)
    method closestNodesNotFailed (line 225) | private List<Node> closestNodesNotFailed(String status)
    method receive (line 257) | @Override
    method timeout (line 290) | @Override
    method getFailedNodes (line 309) | public List<Node> getFailedNodes()

FILE: src/kademlia/operation/Operation.java
  type Operation (line 12) | public interface Operation
    method execute (line 20) | public void execute() throws IOException, RoutingException;

FILE: src/kademlia/operation/PingOperation.java
  class PingOperation (line 15) | public class PingOperation implements Operation
    method PingOperation (line 27) | public PingOperation(KadServer server, Node local, Node toPing)
    method execute (line 34) | @Override

FILE: src/kademlia/operation/StoreOperation.java
  class StoreOperation (line 21) | public class StoreOperation implements Operation
    method StoreOperation (line 37) | public StoreOperation(KadServer server, KademliaNode localNode, JKadem...
    method execute (line 46) | @Override
    method numNodesStoredAt (line 80) | public int numNodesStoredAt()

FILE: src/kademlia/routing/Contact.java
  class Contact (line 16) | public class Contact implements Comparable<Contact>
    method Contact (line 36) | public Contact(Node n)
    method getNode (line 42) | public Node getNode()
    method setSeenNow (line 51) | public void setSeenNow()
    method lastSeen (line 61) | public long lastSeen()
    method equals (line 66) | @Override
    method incrementStaleCount (line 80) | public void incrementStaleCount()
    method staleCount (line 88) | public int staleCount()
    method resetStaleCount (line 96) | public void resetStaleCount()
    method compareTo (line 101) | @Override
    method hashCode (line 112) | @Override

FILE: src/kademlia/routing/ContactLastSeenComparator.java
  class ContactLastSeenComparator (line 11) | public class ContactLastSeenComparator implements Comparator<Contact>
    method compare (line 21) | @Override

FILE: src/kademlia/routing/JKademliaBucket.java
  class JKademliaBucket (line 16) | public class JKademliaBucket implements KademliaBucket
    method JKademliaBucket (line 40) | public JKademliaBucket(int depth, KadConfiguration config)
    method insert (line 46) | @Override
    method insert (line 102) | @Override
    method containsContact (line 108) | @Override
    method containsNode (line 114) | @Override
    method removeContact (line 120) | @Override
    method getFromContacts (line 147) | private synchronized Contact getFromContacts(Node n)
    method removeFromContacts (line 161) | private synchronized Contact removeFromContacts(Node n)
    method removeNode (line 176) | @Override
    method numContacts (line 182) | @Override
    method getDepth (line 188) | @Override
    method getContacts (line 194) | @Override
    method insertIntoReplacementCache (line 217) | private synchronized void insertIntoReplacementCache(Contact c)
    method removeFromReplacementCache (line 242) | private synchronized Contact removeFromReplacementCache(Node n)
    method toString (line 257) | @Override

FILE: src/kademlia/routing/JKademliaRoutingTable.java
  class JKademliaRoutingTable (line 17) | public class JKademliaRoutingTable implements KademliaRoutingTable
    method JKademliaRoutingTable (line 25) | public JKademliaRoutingTable(Node localNode, KadConfiguration config)
    method initialize (line 40) | @Override
    method setConfiguration (line 50) | @Override
    method insert (line 61) | @Override
    method insert (line 72) | @Override
    method getBucketId (line 85) | @Override
    method findClosest (line 102) | @Override
    method getAllNodes (line 126) | @Override
    method getAllContacts (line 145) | @Override
    method getBuckets (line 161) | @Override
    method setBuckets (line 172) | public final void setBuckets(KademliaBucket[] buckets)
    method setUnresponsiveContacts (line 182) | @Override
    method setUnresponsiveContact (line 200) | @Override
    method toString (line 209) | @Override

FILE: src/kademlia/routing/KademliaBucket.java
  type KademliaBucket (line 12) | public interface KademliaBucket
    method insert (line 20) | public void insert(Contact c);
    method insert (line 27) | public void insert(Node n);
    method containsContact (line 36) | public boolean containsContact(Contact c);
    method containsNode (line 45) | public boolean containsNode(Node n);
    method removeContact (line 60) | public boolean removeContact(Contact c);
    method removeNode (line 69) | public boolean removeNode(Node n);
    method numContacts (line 76) | public int numContacts();
    method getDepth (line 81) | public int getDepth();
    method getContacts (line 86) | public List<Contact> getContacts();

FILE: src/kademlia/routing/KademliaRoutingTable.java
  type KademliaRoutingTable (line 14) | public interface KademliaRoutingTable
    method initialize (line 20) | public void initialize();
    method setConfiguration (line 27) | public void setConfiguration(KadConfiguration config);
    method insert (line 34) | public void insert(Contact c);
    method insert (line 41) | public void insert(Node n);
    method getBucketId (line 50) | public int getBucketId(KademliaId nid);
    method findClosest (line 60) | public List<Node> findClosest(KademliaId target, int numNodesRequired);
    method getAllNodes (line 65) | public List getAllNodes();
    method getAllContacts (line 70) | public List getAllContacts();
    method getBuckets (line 75) | public KademliaBucket[] getBuckets();
    method setUnresponsiveContacts (line 82) | public void setUnresponsiveContacts(List<Node> contacts);
    method setUnresponsiveContact (line 89) | public void setUnresponsiveContact(Node n);

FILE: src/kademlia/simulations/AutoRefreshOperation.java
  class AutoRefreshOperation (line 16) | public class AutoRefreshOperation implements Simulation
    method runSimulation (line 19) | @Override

FILE: src/kademlia/simulations/AutoRefreshOperation2.java
  class AutoRefreshOperation2 (line 16) | public class AutoRefreshOperation2 implements Simulation
    method runSimulation (line 19) | @Override

FILE: src/kademlia/simulations/ContentSendingTest.java
  class ContentSendingTest (line 17) | public class ContentSendingTest
    method main (line 20) | public static void main(String[] args)

FILE: src/kademlia/simulations/ContentUpdatingTest.java
  class ContentUpdatingTest (line 16) | public class ContentUpdatingTest
    method main (line 19) | public static void main(String[] args)

FILE: src/kademlia/simulations/DHTContentImpl.java
  class DHTContentImpl (line 13) | public class DHTContentImpl implements KadContent
    method DHTContentImpl (line 29) | public DHTContentImpl()
    method DHTContentImpl (line 34) | public DHTContentImpl(String ownerId, String data)
    method DHTContentImpl (line 41) | public DHTContentImpl(KademliaId key, String ownerId)
    method setData (line 47) | public void setData(String newData)
    method getKey (line 53) | @Override
    method getType (line 59) | @Override
    method getOwnerId (line 65) | @Override
    method setUpdated (line 74) | public void setUpdated()
    method getCreatedTimestamp (line 79) | @Override
    method getLastUpdatedTimestamp (line 85) | @Override
    method toSerializedForm (line 91) | @Override
    method fromSerializedForm (line 98) | @Override
    method toString (line 106) | @Override

FILE: src/kademlia/simulations/NodeConnectionTest.java
  class NodeConnectionTest (line 13) | public class NodeConnectionTest
    method main (line 16) | public static void main(String[] args)

FILE: src/kademlia/simulations/RefreshOperationTest.java
  class RefreshOperationTest (line 16) | public class RefreshOperationTest
    method main (line 19) | public static void main(String[] args)

FILE: src/kademlia/simulations/RoutingTableSimulation.java
  class RoutingTableSimulation (line 13) | public class RoutingTableSimulation
    method RoutingTableSimulation (line 16) | public RoutingTableSimulation()
    method main (line 53) | public static void main(String[] args)

FILE: src/kademlia/simulations/RoutingTableStateTesting.java
  class RoutingTableStateTesting (line 15) | public class RoutingTableStateTesting
    method RoutingTableStateTesting (line 22) | public RoutingTableStateTesting()
    method putContent (line 53) | public KadContent putContent(String content, JKademliaNode owner)
    method shutdownKad (line 70) | public void shutdownKad(JKademliaNode kad)
    method printRoutingTable (line 82) | public void printRoutingTable(int kadId)
    method printRoutingTables (line 87) | public void printRoutingTables()
    method printStorage (line 95) | public void printStorage(int kadId)
    method printStorage (line 100) | public void printStorage()
    method main (line 108) | public static void main(String[] args)

FILE: src/kademlia/simulations/SaveStateTest.java
  class SaveStateTest (line 12) | public class SaveStateTest
    method SaveStateTest (line 15) | public SaveStateTest()
    method main (line 92) | public static void main(String[] args)

FILE: src/kademlia/simulations/SaveStateTest2.java
  class SaveStateTest2 (line 15) | public class SaveStateTest2
    method SaveStateTest2 (line 18) | public SaveStateTest2()
    method main (line 66) | public static void main(String[] args)

FILE: src/kademlia/simulations/SimpleMessageTest.java
  class SimpleMessageTest (line 15) | public class SimpleMessageTest
    method main (line 18) | public static void main(String[] args)

FILE: src/kademlia/simulations/Simulation.java
  type Simulation (line 9) | public interface Simulation
    method runSimulation (line 15) | public void runSimulation();

FILE: src/kademlia/util/HashCalculator.java
  class HashCalculator (line 12) | public class HashCalculator
    method sha1Hash (line 24) | public static byte[] sha1Hash(String toHash) throws NoSuchAlgorithmExc...
    method sha1Hash (line 46) | public static byte[] sha1Hash(String toHash, String salt) throws NoSuc...
    method md5Hash (line 67) | public static byte[] md5Hash(String toHash) throws NoSuchAlgorithmExce...
    method md5Hash (line 89) | public static byte[] md5Hash(String toHash, String salt) throws NoSuch...

FILE: src/kademlia/util/RouteLengthChecker.java
  class RouteLengthChecker (line 19) | public class RouteLengthChecker
    method addInitialNodes (line 39) | public void addInitialNodes(Collection<Node> initialNodes)
    method addNodes (line 55) | public void addNodes(Collection<Node> inputSet, Node sender)
    method getRouteLength (line 88) | public int getRouteLength()

FILE: src/kademlia/util/serializer/JsonDHTSerializer.java
  class JsonDHTSerializer (line 42) | public class JsonDHTSerializer implements KadSerializer<KademliaDHT>
    method write (line 57) | @Override
    method read (line 75) | @Override

FILE: src/kademlia/util/serializer/JsonRoutingTableSerializer.java
  class JsonRoutingTableSerializer (line 43) | public class JsonRoutingTableSerializer implements KadSerializer<Kademli...
    method JsonRoutingTableSerializer (line 64) | public JsonRoutingTableSerializer(KadConfiguration config)
    method write (line 69) | @Override
    method read (line 86) | @Override

FILE: src/kademlia/util/serializer/JsonSerializer.java
  class JsonSerializer (line 21) | public class JsonSerializer<T> implements KadSerializer<T>
    method write (line 31) | @Override
    method read (line 48) | @Override

FILE: src/kademlia/util/serializer/KadSerializer.java
  type KadSerializer (line 17) | public interface KadSerializer<T>
    method write (line 28) | public void write(T data, DataOutputStream out) throws IOException;
    method read (line 40) | public T read(DataInputStream in) throws IOException, ClassNotFoundExc...
Condensed preview — 86 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (323K chars).
[
  {
    "path": ".gitignore",
    "chars": 15,
    "preview": "/dist/\r\n/build/"
  },
  {
    "path": "LICENSE",
    "chars": 1081,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Joshua Kissoon\n\nPermission is hereby granted, free of charge, to any person ob"
  },
  {
    "path": "README.md",
    "chars": 4092,
    "preview": "Kademlia\n========\n\nThis is an implementation of the Kademlia (http://en.wikipedia.org/wiki/Kademlia) routing protocol an"
  },
  {
    "path": "build.xml",
    "chars": 3609,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!-- You may freely edit this file. See commented blocks below for -->\r\n<!-- som"
  },
  {
    "path": "manifest.mf",
    "chars": 85,
    "preview": "Manifest-Version: 1.0\r\nX-COMMENT: Main-Class will be added automatically by build\r\n\r\n"
  },
  {
    "path": "nbproject/build-impl.xml",
    "chars": 79320,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!--\r\n*** GENERATED FROM project.xml - DO NOT EDIT  ***\r\n***         EDIT ../bui"
  },
  {
    "path": "nbproject/genfiles.properties",
    "chars": 475,
    "preview": "build.xml.data.CRC32=7e563d6e\r\nbuild.xml.script.CRC32=c3cd04bd\r\nbuild.xml.stylesheet.CRC32=8064a381@1.68.1.46\r\n# This fi"
  },
  {
    "path": "nbproject/project.properties",
    "chars": 2619,
    "preview": "annotation.processing.enabled=true\r\nannotation.processing.enabled.in.editor=false\r\nannotation.processing.processors.list"
  },
  {
    "path": "nbproject/project.xml",
    "chars": 516,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://www.netbeans.org/ns/project/1\">\r\n    <type>org.netbeans.m"
  },
  {
    "path": "src/kademlia/DefaultConfiguration.java",
    "chars": 2210,
    "preview": "package kademlia;\n\nimport java.io.File;\n\n/**\n * A set of Kademlia configuration parameters. Default values are\n * suppli"
  },
  {
    "path": "src/kademlia/JKademliaNode.java",
    "chars": 13936,
    "preview": "package kademlia;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.File;\nimport java.io."
  },
  {
    "path": "src/kademlia/KadConfiguration.java",
    "chars": 1421,
    "preview": "package kademlia;\n\n/**\n * Interface that defines a KadConfiguration object\n *\n * @author Joshua Kissoon\n * @since 201403"
  },
  {
    "path": "src/kademlia/KadServer.java",
    "chars": 11092,
    "preview": "package kademlia;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.DataInputSt"
  },
  {
    "path": "src/kademlia/KadStatistician.java",
    "chars": 2191,
    "preview": "package kademlia;\n\n/**\n * Specification for class that keeps statistics for a Kademlia instance.\n *\n * These statistics "
  },
  {
    "path": "src/kademlia/KademliaNode.java",
    "chars": 4319,
    "preview": "package kademlia;\n\nimport java.io.IOException;\nimport java.util.NoSuchElementException;\nimport kademlia.dht.GetParameter"
  },
  {
    "path": "src/kademlia/Statistician.java",
    "chars": 4325,
    "preview": "package kademlia;\n\nimport java.text.DecimalFormat;\n\n/**\n * Class that keeps statistics for this Kademlia instance.\n *\n *"
  },
  {
    "path": "src/kademlia/Todo",
    "chars": 592,
    "preview": "# What's left to add to the implementation\r\n\r\n1. Implement the \"Optimized Contact Accounting\" features as mentioned in t"
  },
  {
    "path": "src/kademlia/dht/DHT.java",
    "chars": 8552,
    "preview": "package kademlia.dht;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.File;\nimport java"
  },
  {
    "path": "src/kademlia/dht/GetParameter.java",
    "chars": 2294,
    "preview": "package kademlia.dht;\n\nimport kademlia.node.KademliaId;\n\n/**\n * A GET request can get content based on Key, Owner, Type,"
  },
  {
    "path": "src/kademlia/dht/JKademliaStorageEntry.java",
    "chars": 1298,
    "preview": "package kademlia.dht;\n\n/**\n * A JKademliaStorageEntry class that is used to store a content on the DHT\n *\n * @author Jos"
  },
  {
    "path": "src/kademlia/dht/KadContent.java",
    "chars": 1571,
    "preview": "package kademlia.dht;\n\nimport kademlia.node.KademliaId;\n\n/**\n * Any piece of content that needs to be stored on the DHT\n"
  },
  {
    "path": "src/kademlia/dht/KademliaDHT.java",
    "chars": 3702,
    "preview": "package kademlia.dht;\n\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.util.List;\nimport j"
  },
  {
    "path": "src/kademlia/dht/KademliaStorageEntry.java",
    "chars": 700,
    "preview": "package kademlia.dht;\n\n/**\n * A StorageEntry interface for the storage entry class used to store a content on the DHT\n *"
  },
  {
    "path": "src/kademlia/dht/KademliaStorageEntryMetadata.java",
    "chars": 1414,
    "preview": "package kademlia.dht;\n\nimport kademlia.node.KademliaId;\n\n/**\n * Keeps track of data for a Content stored in the DHT\n * U"
  },
  {
    "path": "src/kademlia/dht/StorageEntryMetadata.java",
    "chars": 3619,
    "preview": "package kademlia.dht;\n\nimport java.util.Objects;\nimport kademlia.node.KademliaId;\n\n/**\n * Keeps track of data for a Cont"
  },
  {
    "path": "src/kademlia/dht/StoredContentManager.java",
    "chars": 5621,
    "preview": "package kademlia.dht;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map"
  },
  {
    "path": "src/kademlia/exceptions/ContentExistException.java",
    "chars": 369,
    "preview": "package kademlia.exceptions;\n\n/**\n * An exception used to indicate that a content already exist on the DHT\n *\n * @author"
  },
  {
    "path": "src/kademlia/exceptions/ContentNotFoundException.java",
    "chars": 379,
    "preview": "package kademlia.exceptions;\n\n/**\n * An exception used to indicate that a content does not exist on the DHT\n *\n * @autho"
  },
  {
    "path": "src/kademlia/exceptions/KadServerDownException.java",
    "chars": 367,
    "preview": "package kademlia.exceptions;\n\n/**\n * An exception to be thrown whenever the Kad Server is down\n *\n * @author Joshua Kiss"
  },
  {
    "path": "src/kademlia/exceptions/RoutingException.java",
    "chars": 377,
    "preview": "package kademlia.exceptions;\n\nimport java.io.IOException;\n\n/**\n * An exception to be thrown whenever there is a routing "
  },
  {
    "path": "src/kademlia/exceptions/UnknownMessageException.java",
    "chars": 394,
    "preview": "package kademlia.exceptions;\n\n/**\n * An exception used to indicate an unknown message type or communication identifier\n "
  },
  {
    "path": "src/kademlia/message/AcknowledgeMessage.java",
    "chars": 1190,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/message/ConnectMessage.java",
    "chars": 1108,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/message/ConnectReceiver.java",
    "chars": 1387,
    "preview": "package kademlia.message;\n\nimport java.io.IOException;\nimport kademlia.KadServer;\nimport kademlia.KademliaNode;\n\n/**\n * "
  },
  {
    "path": "src/kademlia/message/ContentLookupMessage.java",
    "chars": 1736,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/message/ContentLookupReceiver.java",
    "chars": 2273,
    "preview": "package kademlia.message;\n\nimport java.io.IOException;\nimport java.util.NoSuchElementException;\nimport kademlia.KadConfi"
  },
  {
    "path": "src/kademlia/message/ContentMessage.java",
    "chars": 1975,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/message/KademliaMessageFactory.java",
    "chars": 876,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.IOException;\nimport kademlia.KadServer;\n\n/**\n "
  },
  {
    "path": "src/kademlia/message/Message.java",
    "chars": 390,
    "preview": "package kademlia.message;\n\npublic interface Message extends Streamable\n{\n\n    /**\n     * The unique code for the message"
  },
  {
    "path": "src/kademlia/message/MessageFactory.java",
    "chars": 2519,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.IOException;\nimport kademlia.KadConfiguration;"
  },
  {
    "path": "src/kademlia/message/NodeLookupMessage.java",
    "chars": 1633,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/message/NodeLookupReceiver.java",
    "chars": 1916,
    "preview": "package kademlia.message;\n\nimport java.io.IOException;\nimport java.util.List;\nimport kademlia.KadConfiguration;\nimport k"
  },
  {
    "path": "src/kademlia/message/NodeReplyMessage.java",
    "chars": 2102,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/message/Receiver.java",
    "chars": 955,
    "preview": "package kademlia.message;\n\nimport java.io.IOException;\n\n/**\n * A receiver waits for incoming messages and perform some a"
  },
  {
    "path": "src/kademlia/message/SimpleMessage.java",
    "chars": 1380,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/message/SimpleReceiver.java",
    "chars": 517,
    "preview": "package kademlia.message;\n\nimport java.io.IOException;\n\n/**\n * Default receiver if none other is called\n *\n * @author Jo"
  },
  {
    "path": "src/kademlia/message/StoreContentMessage.java",
    "chars": 1931,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/message/StoreContentReceiver.java",
    "chars": 1460,
    "preview": "package kademlia.message;\n\nimport java.io.IOException;\nimport kademlia.KadServer;\nimport kademlia.KademliaNode;\nimport k"
  },
  {
    "path": "src/kademlia/message/Streamable.java",
    "chars": 1380,
    "preview": "package kademlia.message;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\n"
  },
  {
    "path": "src/kademlia/node/KademliaId.java",
    "chars": 6643,
    "preview": "/**\n * @author Joshua Kissoon\n * @created 20140215\n * @desc Represents a Kademlia Node ID\n */\npackage kademlia.node;\n\nim"
  },
  {
    "path": "src/kademlia/node/KeyComparator.java",
    "chars": 1032,
    "preview": "package kademlia.node;\n\nimport java.math.BigInteger;\nimport java.util.Comparator;\n\n/**\n * A Comparator to compare 2 keys"
  },
  {
    "path": "src/kademlia/node/Node.java",
    "chars": 3003,
    "preview": "package kademlia.node;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOException;\nimp"
  },
  {
    "path": "src/kademlia/operation/BucketRefreshOperation.java",
    "chars": 2184,
    "preview": "package kademlia.operation;\n\nimport java.io.IOException;\nimport kademlia.KadConfiguration;\nimport kademlia.KadServer;\nim"
  },
  {
    "path": "src/kademlia/operation/ConnectOperation.java",
    "chars": 4553,
    "preview": "/**\n * @author Joshua Kissoon\n * @created 20140218\n * @desc Operation that handles connecting to an existing Kademlia ne"
  },
  {
    "path": "src/kademlia/operation/ContentLookupOperation.java",
    "chars": 10968,
    "preview": "package kademlia.operation;\n\nimport kademlia.message.Receiver;\nimport java.io.IOException;\nimport java.util.ArrayList;\ni"
  },
  {
    "path": "src/kademlia/operation/ContentRefreshOperation.java",
    "chars": 3613,
    "preview": "package kademlia.operation;\n\nimport java.io.IOException;\nimport java.util.List;\nimport kademlia.KadConfiguration;\nimport"
  },
  {
    "path": "src/kademlia/operation/KadRefreshOperation.java",
    "chars": 1191,
    "preview": "package kademlia.operation;\n\nimport java.io.IOException;\nimport kademlia.KadConfiguration;\nimport kademlia.KadServer;\nim"
  },
  {
    "path": "src/kademlia/operation/NodeLookupOperation.java",
    "chars": 10058,
    "preview": "package kademlia.operation;\n\nimport kademlia.message.Receiver;\nimport java.io.IOException;\nimport java.util.ArrayList;\ni"
  },
  {
    "path": "src/kademlia/operation/Operation.java",
    "chars": 451,
    "preview": "package kademlia.operation;\n\nimport java.io.IOException;\nimport kademlia.exceptions.RoutingException;\n\n/**\n * An operati"
  },
  {
    "path": "src/kademlia/operation/PingOperation.java",
    "chars": 1116,
    "preview": "/**\n * Implementation of the Kademlia Ping operation,\n * This is on hold at the moment since I'm not sure if we'll use p"
  },
  {
    "path": "src/kademlia/operation/StoreOperation.java",
    "chars": 2585,
    "preview": "package kademlia.operation;\n\nimport java.io.IOException;\nimport java.util.List;\nimport kademlia.KadConfiguration;\nimport"
  },
  {
    "path": "src/kademlia/routing/Contact.java",
    "chars": 2569,
    "preview": "package kademlia.routing;\n\nimport kademlia.node.Node;\n\n/**\n * Keeps information about contacts of the Node; Contacts are"
  },
  {
    "path": "src/kademlia/routing/ContactLastSeenComparator.java",
    "chars": 811,
    "preview": "package kademlia.routing;\n\nimport java.util.Comparator;\n\n/**\n * A Comparator to compare 2 contacts by their last seen ti"
  },
  {
    "path": "src/kademlia/routing/JKademliaBucket.java",
    "chars": 7875,
    "preview": "package kademlia.routing;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.NoSuchElementException;\ni"
  },
  {
    "path": "src/kademlia/routing/JKademliaRoutingTable.java",
    "chars": 6347,
    "preview": "package kademlia.routing;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.TreeSet;\nimport kademlia."
  },
  {
    "path": "src/kademlia/routing/KademliaBucket.java",
    "chars": 2145,
    "preview": "package kademlia.routing;\n\nimport java.util.List;\nimport kademlia.node.Node;\n\n/**\n * A bucket used to store Contacts in "
  },
  {
    "path": "src/kademlia/routing/KademliaRoutingTable.java",
    "chars": 2422,
    "preview": "package kademlia.routing;\n\nimport java.util.List;\nimport kademlia.KadConfiguration;\nimport kademlia.node.Node;\nimport ka"
  },
  {
    "path": "src/kademlia/simulations/AutoRefreshOperation.java",
    "chars": 3483,
    "preview": "package kademlia.simulations;\n\nimport java.util.Timer;\nimport java.util.TimerTask;\nimport kademlia.DefaultConfiguration;"
  },
  {
    "path": "src/kademlia/simulations/AutoRefreshOperation2.java",
    "chars": 2720,
    "preview": "package kademlia.simulations;\n\nimport java.util.Timer;\nimport java.util.TimerTask;\nimport kademlia.DefaultConfiguration;"
  },
  {
    "path": "src/kademlia/simulations/ContentSendingTest.java",
    "chars": 2039,
    "preview": "package kademlia.simulations;\n\nimport java.io.IOException;\nimport java.util.UUID;\nimport kademlia.dht.GetParameter;\nimpo"
  },
  {
    "path": "src/kademlia/simulations/ContentUpdatingTest.java",
    "chars": 2231,
    "preview": "package kademlia.simulations;\n\nimport java.io.IOException;\nimport kademlia.dht.GetParameter;\nimport kademlia.JKademliaNo"
  },
  {
    "path": "src/kademlia/simulations/DHTContentImpl.java",
    "chars": 2123,
    "preview": "package kademlia.simulations;\n\nimport com.google.gson.Gson;\nimport kademlia.dht.KadContent;\nimport kademlia.node.Kademli"
  },
  {
    "path": "src/kademlia/simulations/NodeConnectionTest.java",
    "chars": 3233,
    "preview": "package kademlia.simulations;\n\nimport java.io.IOException;\nimport kademlia.JKademliaNode;\nimport kademlia.node.KademliaI"
  },
  {
    "path": "src/kademlia/simulations/RefreshOperationTest.java",
    "chars": 1383,
    "preview": "package kademlia.simulations;\n\nimport java.io.IOException;\nimport kademlia.dht.GetParameter;\nimport kademlia.JKademliaNo"
  },
  {
    "path": "src/kademlia/simulations/RoutingTableSimulation.java",
    "chars": 1818,
    "preview": "package kademlia.simulations;\n\nimport kademlia.JKademliaNode;\nimport kademlia.node.KademliaId;\nimport kademlia.routing.K"
  },
  {
    "path": "src/kademlia/simulations/RoutingTableStateTesting.java",
    "chars": 4265,
    "preview": "package kademlia.simulations;\n\nimport java.io.IOException;\nimport java.util.Scanner;\nimport kademlia.JKademliaNode;\nimpo"
  },
  {
    "path": "src/kademlia/simulations/SaveStateTest.java",
    "chars": 3100,
    "preview": "package kademlia.simulations;\n\nimport kademlia.JKademliaNode;\nimport kademlia.node.KademliaId;\n\n/**\n * Testing the save "
  },
  {
    "path": "src/kademlia/simulations/SaveStateTest2.java",
    "chars": 2225,
    "preview": "package kademlia.simulations;\n\nimport kademlia.JKademliaNode;\nimport kademlia.dht.GetParameter;\nimport kademlia.dht.Kade"
  },
  {
    "path": "src/kademlia/simulations/SimpleMessageTest.java",
    "chars": 854,
    "preview": "package kademlia.simulations;\n\nimport java.io.IOException;\nimport kademlia.JKademliaNode;\nimport kademlia.message.Simple"
  },
  {
    "path": "src/kademlia/simulations/Simulation.java",
    "chars": 264,
    "preview": "package kademlia.simulations;\n\n/**\n * A class that specifies the structure for simulations.\n *\n * @author Joshua Kissoon"
  },
  {
    "path": "src/kademlia/util/HashCalculator.java",
    "chars": 2608,
    "preview": "package kademlia.util;\n\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\n\n/**\n * A cla"
  },
  {
    "path": "src/kademlia/util/RouteLengthChecker.java",
    "chars": 2348,
    "preview": "package kademlia.util;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport kademlia.node.Node;\n\n/**\n * Class "
  },
  {
    "path": "src/kademlia/util/serializer/JsonDHTSerializer.java",
    "chars": 2723,
    "preview": "package kademlia.util.serializer;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\nimport com.goo"
  },
  {
    "path": "src/kademlia/util/serializer/JsonRoutingTableSerializer.java",
    "chars": 3141,
    "preview": "package kademlia.util.serializer;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\nimport com.goo"
  },
  {
    "path": "src/kademlia/util/serializer/JsonSerializer.java",
    "chars": 1693,
    "preview": "package kademlia.util.serializer;\n\nimport com.google.gson.Gson;\nimport com.google.gson.stream.JsonReader;\nimport com.goo"
  },
  {
    "path": "src/kademlia/util/serializer/KadSerializer.java",
    "chars": 1033,
    "preview": "package kademlia.util.serializer;\n\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.IOExc"
  }
]

About this extraction

This page contains the full source code of the JoshuaKissoon/Kademlia GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 86 files (295.1 KB), approximately 69.1k tokens, and a symbol index with 531 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!